Commit 108534b9681579002f46942139a77732a2510436

Authored by aliguori
1 parent 16b98a97

qcow2: Extract code from get_cluster_offset() (Laurent Vivier)

Extract code from get_cluster_offset() into new functions:

- seek_l2_table()

Search an l2 offset in the l2_cache table.

- l2_load()

Read the l2 entry from disk

- l2_allocate()

Allocate a new l2 entry.

Some comment fixups from Kevin Wolf

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Kevin Wolf <kwolf@suse.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5003 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 153 additions and 62 deletions
block-qcow2.c
... ... @@ -480,101 +480,191 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
480 480 return -EIO;
481 481 }
482 482  
483   -/* 'allocate' is:
  483 +/*
  484 + * seek_l2_table
  485 + *
  486 + * seek l2_offset in the l2_cache table
  487 + * if not found, return NULL,
  488 + * if found,
  489 + * increments the l2 cache hit count of the entry,
  490 + * if counter overflow, divide by two all counters
  491 + * return the pointer to the l2 cache entry
  492 + *
  493 + */
  494 +
  495 +static uint64_t *seek_l2_table(BDRVQcowState *s, uint64_t l2_offset)
  496 +{
  497 + int i, j;
  498 +
  499 + for(i = 0; i < L2_CACHE_SIZE; i++) {
  500 + if (l2_offset == s->l2_cache_offsets[i]) {
  501 + /* increment the hit count */
  502 + if (++s->l2_cache_counts[i] == 0xffffffff) {
  503 + for(j = 0; j < L2_CACHE_SIZE; j++) {
  504 + s->l2_cache_counts[j] >>= 1;
  505 + }
  506 + }
  507 + return s->l2_cache + (i << s->l2_bits);
  508 + }
  509 + }
  510 + return NULL;
  511 +}
  512 +
  513 +/*
  514 + * l2_load
484 515 *
485   - * 0 not to allocate.
  516 + * Loads a L2 table into memory. If the table is in the cache, the cache
  517 + * is used; otherwise the L2 table is loaded from the image file.
486 518 *
487   - * 1 to allocate a normal cluster (for sector indexes 'n_start' to
488   - * 'n_end')
  519 + * Returns a pointer to the L2 table on success, or NULL if the read from
  520 + * the image file failed.
  521 + */
  522 +
  523 +static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
  524 +{
  525 + BDRVQcowState *s = bs->opaque;
  526 + int min_index;
  527 + uint64_t *l2_table;
  528 +
  529 + /* seek if the table for the given offset is in the cache */
  530 +
  531 + l2_table = seek_l2_table(s, l2_offset);
  532 + if (l2_table != NULL)
  533 + return l2_table;
  534 +
  535 + /* not found: load a new entry in the least used one */
  536 +
  537 + min_index = l2_cache_new_entry(bs);
  538 + l2_table = s->l2_cache + (min_index << s->l2_bits);
  539 + if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
  540 + s->l2_size * sizeof(uint64_t))
  541 + return NULL;
  542 + s->l2_cache_offsets[min_index] = l2_offset;
  543 + s->l2_cache_counts[min_index] = 1;
  544 +
  545 + return l2_table;
  546 +}
  547 +
  548 +/*
  549 + * l2_allocate
489 550 *
490   - * 2 to allocate a compressed cluster of size
491   - * 'compressed_size'. 'compressed_size' must be > 0 and <
492   - * cluster_size
  551 + * Allocate a new l2 entry in the file. If l1_index points to an already
  552 + * used entry in the L2 table (i.e. we are doing a copy on write for the L2
  553 + * table) copy the contents of the old L2 table into the newly allocated one.
  554 + * Otherwise the new table is initialized with zeros.
493 555 *
494   - * return 0 if not allocated.
495 556 */
  557 +
  558 +static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
  559 +{
  560 + BDRVQcowState *s = bs->opaque;
  561 + int min_index;
  562 + uint64_t old_l2_offset, tmp;
  563 + uint64_t *l2_table, l2_offset;
  564 +
  565 + old_l2_offset = s->l1_table[l1_index];
  566 +
  567 + /* allocate a new l2 entry */
  568 +
  569 + l2_offset = alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
  570 +
  571 + /* update the L1 entry */
  572 +
  573 + s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
  574 +
  575 + tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED);
  576 + if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
  577 + &tmp, sizeof(tmp)) != sizeof(tmp))
  578 + return NULL;
  579 +
  580 + /* allocate a new entry in the l2 cache */
  581 +
  582 + min_index = l2_cache_new_entry(bs);
  583 + l2_table = s->l2_cache + (min_index << s->l2_bits);
  584 +
  585 + if (old_l2_offset == 0) {
  586 + /* if there was no old l2 table, clear the new table */
  587 + memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
  588 + } else {
  589 + /* if there was an old l2 table, read it from the disk */
  590 + if (bdrv_pread(s->hd, old_l2_offset,
  591 + l2_table, s->l2_size * sizeof(uint64_t)) !=
  592 + s->l2_size * sizeof(uint64_t))
  593 + return NULL;
  594 + }
  595 + /* write the l2 table to the file */
  596 + if (bdrv_pwrite(s->hd, l2_offset,
  597 + l2_table, s->l2_size * sizeof(uint64_t)) !=
  598 + s->l2_size * sizeof(uint64_t))
  599 + return NULL;
  600 +
  601 + /* update the l2 cache entry */
  602 +
  603 + s->l2_cache_offsets[min_index] = l2_offset;
  604 + s->l2_cache_counts[min_index] = 1;
  605 +
  606 + return l2_table;
  607 +}
  608 +
496 609 static uint64_t get_cluster_offset(BlockDriverState *bs,
497 610 uint64_t offset, int allocate,
498 611 int compressed_size,
499 612 int n_start, int n_end)
500 613 {
501 614 BDRVQcowState *s = bs->opaque;
502   - int min_index, i, j, l1_index, l2_index, ret;
503   - uint64_t l2_offset, *l2_table, cluster_offset, tmp, old_l2_offset;
  615 + int l1_index, l2_index, ret;
  616 + uint64_t l2_offset, *l2_table, cluster_offset, tmp;
  617 +
  618 + /* seek the the l2 offset in the l1 table */
504 619  
505 620 l1_index = offset >> (s->l2_bits + s->cluster_bits);
506 621 if (l1_index >= s->l1_size) {
507 622 /* outside l1 table is allowed: we grow the table if needed */
508 623 if (!allocate)
509 624 return 0;
510   - if (grow_l1_table(bs, l1_index + 1) < 0)
  625 + ret = grow_l1_table(bs, l1_index + 1);
  626 + if (ret < 0)
511 627 return 0;
512 628 }
513 629 l2_offset = s->l1_table[l1_index];
  630 +
  631 + /* seek the l2 table of the given l2 offset */
  632 +
514 633 if (!l2_offset) {
  634 + /* the l2 table doesn't exist */
515 635 if (!allocate)
516 636 return 0;
517   - l2_allocate:
518   - old_l2_offset = l2_offset;
519   - /* allocate a new l2 entry */
520   - l2_offset = alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
521   - /* update the L1 entry */
522   - s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
523   - tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED);
524   - if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
525   - &tmp, sizeof(tmp)) != sizeof(tmp))
526   - return 0;
527   - min_index = l2_cache_new_entry(bs);
528   - l2_table = s->l2_cache + (min_index << s->l2_bits);
529   -
530   - if (old_l2_offset == 0) {
531   - memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
532   - } else {
533   - if (bdrv_pread(s->hd, old_l2_offset,
534   - l2_table, s->l2_size * sizeof(uint64_t)) !=
535   - s->l2_size * sizeof(uint64_t))
536   - return 0;
537   - }
538   - if (bdrv_pwrite(s->hd, l2_offset,
539   - l2_table, s->l2_size * sizeof(uint64_t)) !=
540   - s->l2_size * sizeof(uint64_t))
  637 + /* allocate a new l2 table for this offset */
  638 + l2_table = l2_allocate(bs, l1_index);
  639 + if (l2_table == NULL)
541 640 return 0;
  641 + l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
542 642 } else {
543   - if (!(l2_offset & QCOW_OFLAG_COPIED)) {
544   - if (allocate) {
545   - free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
546   - goto l2_allocate;
547   - }
  643 + /* the l2 table exists */
  644 + if (!(l2_offset & QCOW_OFLAG_COPIED) && allocate) {
  645 + /* duplicate the l2 table, and free the old table */
  646 + free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
  647 + l2_table = l2_allocate(bs, l1_index);
  648 + if (l2_table == NULL)
  649 + return 0;
  650 + l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
548 651 } else {
  652 + /* load the l2 table in memory */
549 653 l2_offset &= ~QCOW_OFLAG_COPIED;
  654 + l2_table = l2_load(bs, l2_offset);
  655 + if (l2_table == NULL)
  656 + return 0;
550 657 }
551   - for(i = 0; i < L2_CACHE_SIZE; i++) {
552   - if (l2_offset == s->l2_cache_offsets[i]) {
553   - /* increment the hit count */
554   - if (++s->l2_cache_counts[i] == 0xffffffff) {
555   - for(j = 0; j < L2_CACHE_SIZE; j++) {
556   - s->l2_cache_counts[j] >>= 1;
557   - }
558   - }
559   - l2_table = s->l2_cache + (i << s->l2_bits);
560   - goto found;
561   - }
562   - }
563   - /* not found: load a new entry in the least used one */
564   - min_index = l2_cache_new_entry(bs);
565   - l2_table = s->l2_cache + (min_index << s->l2_bits);
566   - if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
567   - s->l2_size * sizeof(uint64_t))
568   - return 0;
569 658 }
570   - s->l2_cache_offsets[min_index] = l2_offset;
571   - s->l2_cache_counts[min_index] = 1;
572   - found:
  659 +
  660 + /* find the cluster offset for the given disk offset */
  661 +
573 662 l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
574 663 cluster_offset = be64_to_cpu(l2_table[l2_index]);
575 664 if (!cluster_offset) {
  665 + /* cluster doesn't exist */
576 666 if (!allocate)
577   - return cluster_offset;
  667 + return 0;
578 668 } else if (!(cluster_offset & QCOW_OFLAG_COPIED)) {
579 669 if (!allocate)
580 670 return cluster_offset;
... ... @@ -592,6 +682,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
592 682 cluster_offset &= ~QCOW_OFLAG_COPIED;
593 683 return cluster_offset;
594 684 }
  685 +
595 686 if (allocate == 1) {
596 687 /* allocate a new cluster */
597 688 cluster_offset = alloc_clusters(bs, s->cluster_size);
... ...