Annotation of qemu/block/qcow2-refcount.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Block driver for the QCOW version 2 format
                      3:  *
                      4:  * Copyright (c) 2004-2006 Fabrice Bellard
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: #include "qemu-common.h"
                     26: #include "block_int.h"
                     27: #include "block/qcow2.h"
                     28: 
                     29: static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size);
                     30: static int update_refcount(BlockDriverState *bs,
                     31:                             int64_t offset, int64_t length,
                     32:                             int addend);
                     33: 
                     34: 
                     35: static int cache_refcount_updates = 0;
                     36: 
                     37: static int write_refcount_block(BDRVQcowState *s)
                     38: {
                     39:     size_t size = s->cluster_size;
                     40: 
                     41:     if (s->refcount_block_cache_offset == 0) {
                     42:         return 0;
                     43:     }
                     44: 
                     45:     if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
                     46:             s->refcount_block_cache, size) != size)
                     47:     {
                     48:         return -EIO;
                     49:     }
                     50: 
                     51:     return 0;
                     52: }
                     53: 
                     54: /*********************************************************/
                     55: /* refcount handling */
                     56: 
                     57: int qcow2_refcount_init(BlockDriverState *bs)
                     58: {
                     59:     BDRVQcowState *s = bs->opaque;
                     60:     int ret, refcount_table_size2, i;
                     61: 
                     62:     s->refcount_block_cache = qemu_malloc(s->cluster_size);
                     63:     refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
                     64:     s->refcount_table = qemu_malloc(refcount_table_size2);
                     65:     if (s->refcount_table_size > 0) {
                     66:         ret = bdrv_pread(s->hd, s->refcount_table_offset,
                     67:                          s->refcount_table, refcount_table_size2);
                     68:         if (ret != refcount_table_size2)
                     69:             goto fail;
                     70:         for(i = 0; i < s->refcount_table_size; i++)
                     71:             be64_to_cpus(&s->refcount_table[i]);
                     72:     }
                     73:     return 0;
                     74:  fail:
                     75:     return -ENOMEM;
                     76: }
                     77: 
                     78: void qcow2_refcount_close(BlockDriverState *bs)
                     79: {
                     80:     BDRVQcowState *s = bs->opaque;
                     81:     qemu_free(s->refcount_block_cache);
                     82:     qemu_free(s->refcount_table);
                     83: }
                     84: 
                     85: 
                     86: static int load_refcount_block(BlockDriverState *bs,
                     87:                                int64_t refcount_block_offset)
                     88: {
                     89:     BDRVQcowState *s = bs->opaque;
                     90:     int ret;
                     91: 
                     92:     if (cache_refcount_updates) {
                     93:         write_refcount_block(s);
                     94:     }
                     95: 
                     96:     ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
                     97:                      s->cluster_size);
                     98:     if (ret != s->cluster_size)
                     99:         return -EIO;
                    100:     s->refcount_block_cache_offset = refcount_block_offset;
                    101:     return 0;
                    102: }
                    103: 
                    104: static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
                    105: {
                    106:     BDRVQcowState *s = bs->opaque;
                    107:     int refcount_table_index, block_index;
                    108:     int64_t refcount_block_offset;
                    109: 
                    110:     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
                    111:     if (refcount_table_index >= s->refcount_table_size)
                    112:         return 0;
                    113:     refcount_block_offset = s->refcount_table[refcount_table_index];
                    114:     if (!refcount_block_offset)
                    115:         return 0;
                    116:     if (refcount_block_offset != s->refcount_block_cache_offset) {
                    117:         /* better than nothing: return allocated if read error */
                    118:         if (load_refcount_block(bs, refcount_block_offset) < 0)
                    119:             return 1;
                    120:     }
                    121:     block_index = cluster_index &
                    122:         ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
                    123:     return be16_to_cpu(s->refcount_block_cache[block_index]);
                    124: }
                    125: 
                    126: static int grow_refcount_table(BlockDriverState *bs, int min_size)
                    127: {
                    128:     BDRVQcowState *s = bs->opaque;
                    129:     int new_table_size, new_table_size2, refcount_table_clusters, i, ret;
                    130:     uint64_t *new_table;
                    131:     int64_t table_offset;
                    132:     uint8_t data[12];
                    133:     int old_table_size;
                    134:     int64_t old_table_offset;
                    135: 
                    136:     if (min_size <= s->refcount_table_size)
                    137:         return 0;
                    138:     /* compute new table size */
                    139:     refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);
                    140:     for(;;) {
                    141:         if (refcount_table_clusters == 0) {
                    142:             refcount_table_clusters = 1;
                    143:         } else {
                    144:             refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2;
                    145:         }
                    146:         new_table_size = refcount_table_clusters << (s->cluster_bits - 3);
                    147:         if (min_size <= new_table_size)
                    148:             break;
                    149:     }
                    150: #ifdef DEBUG_ALLOC2
                    151:     printf("grow_refcount_table from %d to %d\n",
                    152:            s->refcount_table_size,
                    153:            new_table_size);
                    154: #endif
                    155:     new_table_size2 = new_table_size * sizeof(uint64_t);
                    156:     new_table = qemu_mallocz(new_table_size2);
                    157:     memcpy(new_table, s->refcount_table,
                    158:            s->refcount_table_size * sizeof(uint64_t));
                    159:     for(i = 0; i < s->refcount_table_size; i++)
                    160:         cpu_to_be64s(&new_table[i]);
                    161:     /* Note: we cannot update the refcount now to avoid recursion */
                    162:     table_offset = alloc_clusters_noref(bs, new_table_size2);
                    163:     ret = bdrv_pwrite(s->hd, table_offset, new_table, new_table_size2);
                    164:     if (ret != new_table_size2)
                    165:         goto fail;
                    166:     for(i = 0; i < s->refcount_table_size; i++)
                    167:         be64_to_cpus(&new_table[i]);
                    168: 
                    169:     cpu_to_be64w((uint64_t*)data, table_offset);
                    170:     cpu_to_be32w((uint32_t*)(data + 8), refcount_table_clusters);
                    171:     if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
                    172:                     data, sizeof(data)) != sizeof(data))
                    173:         goto fail;
                    174:     qemu_free(s->refcount_table);
                    175:     old_table_offset = s->refcount_table_offset;
                    176:     old_table_size = s->refcount_table_size;
                    177:     s->refcount_table = new_table;
                    178:     s->refcount_table_size = new_table_size;
                    179:     s->refcount_table_offset = table_offset;
                    180: 
                    181:     update_refcount(bs, table_offset, new_table_size2, 1);
                    182:     qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
                    183:     return 0;
                    184:  fail:
                    185:     qcow2_free_clusters(bs, table_offset, new_table_size2);
                    186:     qemu_free(new_table);
                    187:     return -EIO;
                    188: }
                    189: 
                    190: 
                    191: static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
                    192: {
                    193:     BDRVQcowState *s = bs->opaque;
                    194:     int64_t offset, refcount_block_offset;
                    195:     int ret, refcount_table_index;
                    196:     uint64_t data64;
                    197:     int cache = cache_refcount_updates;
                    198: 
                    199:     /* Find L1 index and grow refcount table if needed */
                    200:     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
                    201:     if (refcount_table_index >= s->refcount_table_size) {
                    202:         ret = grow_refcount_table(bs, refcount_table_index + 1);
                    203:         if (ret < 0)
                    204:             return ret;
                    205:     }
                    206: 
                    207:     /* Load or allocate the refcount block */
                    208:     refcount_block_offset = s->refcount_table[refcount_table_index];
                    209:     if (!refcount_block_offset) {
                    210:         if (cache_refcount_updates) {
                    211:             write_refcount_block(s);
                    212:             cache_refcount_updates = 0;
                    213:         }
                    214:         /* create a new refcount block */
                    215:         /* Note: we cannot update the refcount now to avoid recursion */
                    216:         offset = alloc_clusters_noref(bs, s->cluster_size);
                    217:         memset(s->refcount_block_cache, 0, s->cluster_size);
                    218:         ret = bdrv_pwrite(s->hd, offset, s->refcount_block_cache, s->cluster_size);
                    219:         if (ret != s->cluster_size)
                    220:             return -EINVAL;
                    221:         s->refcount_table[refcount_table_index] = offset;
                    222:         data64 = cpu_to_be64(offset);
                    223:         ret = bdrv_pwrite(s->hd, s->refcount_table_offset +
                    224:                           refcount_table_index * sizeof(uint64_t),
                    225:                           &data64, sizeof(data64));
                    226:         if (ret != sizeof(data64))
                    227:             return -EINVAL;
                    228: 
                    229:         refcount_block_offset = offset;
                    230:         s->refcount_block_cache_offset = offset;
                    231:         update_refcount(bs, offset, s->cluster_size, 1);
                    232:         cache_refcount_updates = cache;
                    233:     } else {
                    234:         if (refcount_block_offset != s->refcount_block_cache_offset) {
                    235:             if (load_refcount_block(bs, refcount_block_offset) < 0)
                    236:                 return -EIO;
                    237:         }
                    238:     }
                    239: 
                    240:     return refcount_block_offset;
                    241: }
                    242: 
                    243: #define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT)
                    244: static int write_refcount_block_entries(BDRVQcowState *s,
                    245:     int64_t refcount_block_offset, int first_index, int last_index)
                    246: {
                    247:     size_t size;
                    248: 
                    249:     if (cache_refcount_updates) {
                    250:         return 0;
                    251:     }
                    252: 
                    253:     first_index &= ~(REFCOUNTS_PER_SECTOR - 1);
                    254:     last_index = (last_index + REFCOUNTS_PER_SECTOR)
                    255:         & ~(REFCOUNTS_PER_SECTOR - 1);
                    256: 
                    257:     size = (last_index - first_index) << REFCOUNT_SHIFT;
                    258:     if (bdrv_pwrite(s->hd,
                    259:         refcount_block_offset + (first_index << REFCOUNT_SHIFT),
                    260:         &s->refcount_block_cache[first_index], size) != size)
                    261:     {
                    262:         return -EIO;
                    263:     }
                    264: 
                    265:     return 0;
                    266: }
                    267: 
                    268: /* XXX: cache several refcount block clusters ? */
                    269: static int update_refcount(BlockDriverState *bs,
                    270:                             int64_t offset, int64_t length,
                    271:                             int addend)
                    272: {
                    273:     BDRVQcowState *s = bs->opaque;
                    274:     int64_t start, last, cluster_offset;
                    275:     int64_t refcount_block_offset = 0;
                    276:     int64_t table_index = -1, old_table_index;
                    277:     int first_index = -1, last_index = -1;
                    278: 
                    279: #ifdef DEBUG_ALLOC2
                    280:     printf("update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n",
                    281:            offset, length, addend);
                    282: #endif
                    283:     if (length <= 0)
                    284:         return -EINVAL;
                    285:     start = offset & ~(s->cluster_size - 1);
                    286:     last = (offset + length - 1) & ~(s->cluster_size - 1);
                    287:     for(cluster_offset = start; cluster_offset <= last;
                    288:         cluster_offset += s->cluster_size)
                    289:     {
                    290:         int block_index, refcount;
                    291:         int64_t cluster_index = cluster_offset >> s->cluster_bits;
                    292: 
                    293:         /* Only write refcount block to disk when we are done with it */
                    294:         old_table_index = table_index;
                    295:         table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
                    296:         if ((old_table_index >= 0) && (table_index != old_table_index)) {
                    297: 
                    298:             if (write_refcount_block_entries(s, refcount_block_offset,
                    299:                 first_index, last_index) < 0)
                    300:             {
                    301:                 return -EIO;
                    302:             }
                    303: 
                    304:             first_index = -1;
                    305:             last_index = -1;
                    306:         }
                    307: 
                    308:         /* Load the refcount block and allocate it if needed */
                    309:         refcount_block_offset = alloc_refcount_block(bs, cluster_index);
                    310:         if (refcount_block_offset < 0) {
                    311:             return refcount_block_offset;
                    312:         }
                    313: 
                    314:         /* we can update the count and save it */
                    315:         block_index = cluster_index &
                    316:             ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
                    317:         if (first_index == -1 || block_index < first_index) {
                    318:             first_index = block_index;
                    319:         }
                    320:         if (block_index > last_index) {
                    321:             last_index = block_index;
                    322:         }
                    323: 
                    324:         refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
                    325:         refcount += addend;
                    326:         if (refcount < 0 || refcount > 0xffff)
                    327:             return -EINVAL;
                    328:         if (refcount == 0 && cluster_index < s->free_cluster_index) {
                    329:             s->free_cluster_index = cluster_index;
                    330:         }
                    331:         s->refcount_block_cache[block_index] = cpu_to_be16(refcount);
                    332:     }
                    333: 
                    334:     /* Write last changed block to disk */
                    335:     if (refcount_block_offset != 0) {
                    336:         if (write_refcount_block_entries(s, refcount_block_offset,
                    337:             first_index, last_index) < 0)
                    338:         {
                    339:             return -EIO;
                    340:         }
                    341:     }
                    342: 
                    343:     return 0;
                    344: }
                    345: 
                    346: /* addend must be 1 or -1 */
                    347: static int update_cluster_refcount(BlockDriverState *bs,
                    348:                                    int64_t cluster_index,
                    349:                                    int addend)
                    350: {
                    351:     BDRVQcowState *s = bs->opaque;
                    352:     int ret;
                    353: 
                    354:     ret = update_refcount(bs, cluster_index << s->cluster_bits, 1, addend);
                    355:     if (ret < 0) {
                    356:         return ret;
                    357:     }
                    358: 
                    359:     return get_refcount(bs, cluster_index);
                    360: }
                    361: 
                    362: 
                    363: 
                    364: /*********************************************************/
                    365: /* cluster allocation functions */
                    366: 
                    367: 
                    368: 
                    369: /* return < 0 if error */
                    370: static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
                    371: {
                    372:     BDRVQcowState *s = bs->opaque;
                    373:     int i, nb_clusters;
                    374: 
                    375:     nb_clusters = size_to_clusters(s, size);
                    376: retry:
                    377:     for(i = 0; i < nb_clusters; i++) {
                    378:         int64_t i = s->free_cluster_index++;
                    379:         if (get_refcount(bs, i) != 0)
                    380:             goto retry;
                    381:     }
                    382: #ifdef DEBUG_ALLOC2
                    383:     printf("alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
                    384:             size,
                    385:             (s->free_cluster_index - nb_clusters) << s->cluster_bits);
                    386: #endif
                    387:     return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
                    388: }
                    389: 
                    390: int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
                    391: {
                    392:     int64_t offset;
                    393: 
                    394:     offset = alloc_clusters_noref(bs, size);
                    395:     update_refcount(bs, offset, size, 1);
                    396:     return offset;
                    397: }
                    398: 
                    399: /* only used to allocate compressed sectors. We try to allocate
                    400:    contiguous sectors. size must be <= cluster_size */
                    401: int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
                    402: {
                    403:     BDRVQcowState *s = bs->opaque;
                    404:     int64_t offset, cluster_offset;
                    405:     int free_in_cluster;
                    406: 
                    407:     assert(size > 0 && size <= s->cluster_size);
                    408:     if (s->free_byte_offset == 0) {
                    409:         s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
                    410:     }
                    411:  redo:
                    412:     free_in_cluster = s->cluster_size -
                    413:         (s->free_byte_offset & (s->cluster_size - 1));
                    414:     if (size <= free_in_cluster) {
                    415:         /* enough space in current cluster */
                    416:         offset = s->free_byte_offset;
                    417:         s->free_byte_offset += size;
                    418:         free_in_cluster -= size;
                    419:         if (free_in_cluster == 0)
                    420:             s->free_byte_offset = 0;
                    421:         if ((offset & (s->cluster_size - 1)) != 0)
                    422:             update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
                    423:     } else {
                    424:         offset = qcow2_alloc_clusters(bs, s->cluster_size);
                    425:         cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);
                    426:         if ((cluster_offset + s->cluster_size) == offset) {
                    427:             /* we are lucky: contiguous data */
                    428:             offset = s->free_byte_offset;
                    429:             update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
                    430:             s->free_byte_offset += size;
                    431:         } else {
                    432:             s->free_byte_offset = offset;
                    433:             goto redo;
                    434:         }
                    435:     }
                    436:     return offset;
                    437: }
                    438: 
                    439: void qcow2_free_clusters(BlockDriverState *bs,
                    440:                           int64_t offset, int64_t size)
                    441: {
                    442:     update_refcount(bs, offset, size, -1);
                    443: }
                    444: 
                    445: /*
                    446:  * free_any_clusters
                    447:  *
                    448:  * free clusters according to its type: compressed or not
                    449:  *
                    450:  */
                    451: 
                    452: void qcow2_free_any_clusters(BlockDriverState *bs,
                    453:     uint64_t cluster_offset, int nb_clusters)
                    454: {
                    455:     BDRVQcowState *s = bs->opaque;
                    456: 
                    457:     /* free the cluster */
                    458: 
                    459:     if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
                    460:         int nb_csectors;
                    461:         nb_csectors = ((cluster_offset >> s->csize_shift) &
                    462:                        s->csize_mask) + 1;
                    463:         qcow2_free_clusters(bs,
                    464:             (cluster_offset & s->cluster_offset_mask) & ~511,
                    465:             nb_csectors * 512);
                    466:         return;
                    467:     }
                    468: 
                    469:     qcow2_free_clusters(bs, cluster_offset, nb_clusters << s->cluster_bits);
                    470: 
                    471:     return;
                    472: }
                    473: 
                    474: 
                    475: 
                    476: /*********************************************************/
                    477: /* snapshots and image creation */
                    478: 
                    479: 
                    480: 
                    481: void qcow2_create_refcount_update(QCowCreateState *s, int64_t offset,
                    482:     int64_t size)
                    483: {
                    484:     int refcount;
                    485:     int64_t start, last, cluster_offset;
                    486:     uint16_t *p;
                    487: 
                    488:     start = offset & ~(s->cluster_size - 1);
                    489:     last = (offset + size - 1)  & ~(s->cluster_size - 1);
                    490:     for(cluster_offset = start; cluster_offset <= last;
                    491:         cluster_offset += s->cluster_size) {
                    492:         p = &s->refcount_block[cluster_offset >> s->cluster_bits];
                    493:         refcount = be16_to_cpu(*p);
                    494:         refcount++;
                    495:         *p = cpu_to_be16(refcount);
                    496:     }
                    497: }
                    498: 
                    499: /* update the refcounts of snapshots and the copied flag */
                    500: int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                    501:     int64_t l1_table_offset, int l1_size, int addend)
                    502: {
                    503:     BDRVQcowState *s = bs->opaque;
                    504:     uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
                    505:     int64_t old_offset, old_l2_offset;
                    506:     int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
                    507: 
                    508:     qcow2_l2_cache_reset(bs);
                    509:     cache_refcount_updates = 1;
                    510: 
                    511:     l2_table = NULL;
                    512:     l1_table = NULL;
                    513:     l1_size2 = l1_size * sizeof(uint64_t);
                    514:     l1_allocated = 0;
                    515:     if (l1_table_offset != s->l1_table_offset) {
                    516:         l1_table = qemu_mallocz(align_offset(l1_size2, 512));
                    517:         l1_allocated = 1;
                    518:         if (bdrv_pread(s->hd, l1_table_offset,
                    519:                        l1_table, l1_size2) != l1_size2)
                    520:             goto fail;
                    521:         for(i = 0;i < l1_size; i++)
                    522:             be64_to_cpus(&l1_table[i]);
                    523:     } else {
                    524:         assert(l1_size == s->l1_size);
                    525:         l1_table = s->l1_table;
                    526:         l1_allocated = 0;
                    527:     }
                    528: 
                    529:     l2_size = s->l2_size * sizeof(uint64_t);
                    530:     l2_table = qemu_malloc(l2_size);
                    531:     l1_modified = 0;
                    532:     for(i = 0; i < l1_size; i++) {
                    533:         l2_offset = l1_table[i];
                    534:         if (l2_offset) {
                    535:             old_l2_offset = l2_offset;
                    536:             l2_offset &= ~QCOW_OFLAG_COPIED;
                    537:             l2_modified = 0;
                    538:             if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
                    539:                 goto fail;
                    540:             for(j = 0; j < s->l2_size; j++) {
                    541:                 offset = be64_to_cpu(l2_table[j]);
                    542:                 if (offset != 0) {
                    543:                     old_offset = offset;
                    544:                     offset &= ~QCOW_OFLAG_COPIED;
                    545:                     if (offset & QCOW_OFLAG_COMPRESSED) {
                    546:                         nb_csectors = ((offset >> s->csize_shift) &
                    547:                                        s->csize_mask) + 1;
                    548:                         if (addend != 0)
                    549:                             update_refcount(bs, (offset & s->cluster_offset_mask) & ~511,
                    550:                                             nb_csectors * 512, addend);
                    551:                         /* compressed clusters are never modified */
                    552:                         refcount = 2;
                    553:                     } else {
                    554:                         if (addend != 0) {
                    555:                             refcount = update_cluster_refcount(bs, offset >> s->cluster_bits, addend);
                    556:                         } else {
                    557:                             refcount = get_refcount(bs, offset >> s->cluster_bits);
                    558:                         }
                    559:                     }
                    560: 
                    561:                     if (refcount == 1) {
                    562:                         offset |= QCOW_OFLAG_COPIED;
                    563:                     }
                    564:                     if (offset != old_offset) {
                    565:                         l2_table[j] = cpu_to_be64(offset);
                    566:                         l2_modified = 1;
                    567:                     }
                    568:                 }
                    569:             }
                    570:             if (l2_modified) {
                    571:                 if (bdrv_pwrite(s->hd,
                    572:                                 l2_offset, l2_table, l2_size) != l2_size)
                    573:                     goto fail;
                    574:             }
                    575: 
                    576:             if (addend != 0) {
                    577:                 refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend);
                    578:             } else {
                    579:                 refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
                    580:             }
                    581:             if (refcount == 1) {
                    582:                 l2_offset |= QCOW_OFLAG_COPIED;
                    583:             }
                    584:             if (l2_offset != old_l2_offset) {
                    585:                 l1_table[i] = l2_offset;
                    586:                 l1_modified = 1;
                    587:             }
                    588:         }
                    589:     }
                    590:     if (l1_modified) {
                    591:         for(i = 0; i < l1_size; i++)
                    592:             cpu_to_be64s(&l1_table[i]);
                    593:         if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
                    594:                         l1_size2) != l1_size2)
                    595:             goto fail;
                    596:         for(i = 0; i < l1_size; i++)
                    597:             be64_to_cpus(&l1_table[i]);
                    598:     }
                    599:     if (l1_allocated)
                    600:         qemu_free(l1_table);
                    601:     qemu_free(l2_table);
                    602:     cache_refcount_updates = 0;
                    603:     write_refcount_block(s);
                    604:     return 0;
                    605:  fail:
                    606:     if (l1_allocated)
                    607:         qemu_free(l1_table);
                    608:     qemu_free(l2_table);
                    609:     cache_refcount_updates = 0;
                    610:     write_refcount_block(s);
                    611:     return -EIO;
                    612: }
                    613: 
                    614: 
                    615: 
                    616: 
                    617: /*********************************************************/
                    618: /* refcount checking functions */
                    619: 
                    620: 
                    621: 
                    622: /*
                    623:  * Increases the refcount for a range of clusters in a given refcount table.
                    624:  * This is used to construct a temporary refcount table out of L1 and L2 tables
                    625:  * which can be compared the the refcount table saved in the image.
                    626:  *
                    627:  * Returns the number of errors in the image that were found
                    628:  */
                    629: static int inc_refcounts(BlockDriverState *bs,
                    630:                           uint16_t *refcount_table,
                    631:                           int refcount_table_size,
                    632:                           int64_t offset, int64_t size)
                    633: {
                    634:     BDRVQcowState *s = bs->opaque;
                    635:     int64_t start, last, cluster_offset;
                    636:     int k;
                    637:     int errors = 0;
                    638: 
                    639:     if (size <= 0)
                    640:         return 0;
                    641: 
                    642:     start = offset & ~(s->cluster_size - 1);
                    643:     last = (offset + size - 1) & ~(s->cluster_size - 1);
                    644:     for(cluster_offset = start; cluster_offset <= last;
                    645:         cluster_offset += s->cluster_size) {
                    646:         k = cluster_offset >> s->cluster_bits;
                    647:         if (k < 0 || k >= refcount_table_size) {
                    648:             fprintf(stderr, "ERROR: invalid cluster offset=0x%" PRIx64 "\n",
                    649:                 cluster_offset);
                    650:             errors++;
                    651:         } else {
                    652:             if (++refcount_table[k] == 0) {
                    653:                 fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64
                    654:                     "\n", cluster_offset);
                    655:                 errors++;
                    656:             }
                    657:         }
                    658:     }
                    659: 
                    660:     return errors;
                    661: }
                    662: 
                    663: /*
                    664:  * Increases the refcount in the given refcount table for the all clusters
                    665:  * referenced in the L2 table. While doing so, performs some checks on L2
                    666:  * entries.
                    667:  *
                    668:  * Returns the number of errors found by the checks or -errno if an internal
                    669:  * error occurred.
                    670:  */
                    671: static int check_refcounts_l2(BlockDriverState *bs,
                    672:     uint16_t *refcount_table, int refcount_table_size, int64_t l2_offset,
                    673:     int check_copied)
                    674: {
                    675:     BDRVQcowState *s = bs->opaque;
                    676:     uint64_t *l2_table, offset;
                    677:     int i, l2_size, nb_csectors, refcount;
                    678:     int errors = 0;
                    679: 
                    680:     /* Read L2 table from disk */
                    681:     l2_size = s->l2_size * sizeof(uint64_t);
                    682:     l2_table = qemu_malloc(l2_size);
                    683: 
                    684:     if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
                    685:         goto fail;
                    686: 
                    687:     /* Do the actual checks */
                    688:     for(i = 0; i < s->l2_size; i++) {
                    689:         offset = be64_to_cpu(l2_table[i]);
                    690:         if (offset != 0) {
                    691:             if (offset & QCOW_OFLAG_COMPRESSED) {
                    692:                 /* Compressed clusters don't have QCOW_OFLAG_COPIED */
                    693:                 if (offset & QCOW_OFLAG_COPIED) {
                    694:                     fprintf(stderr, "ERROR: cluster %" PRId64 ": "
                    695:                         "copied flag must never be set for compressed "
                    696:                         "clusters\n", offset >> s->cluster_bits);
                    697:                     offset &= ~QCOW_OFLAG_COPIED;
                    698:                     errors++;
                    699:                 }
                    700: 
                    701:                 /* Mark cluster as used */
                    702:                 nb_csectors = ((offset >> s->csize_shift) &
                    703:                                s->csize_mask) + 1;
                    704:                 offset &= s->cluster_offset_mask;
                    705:                 errors += inc_refcounts(bs, refcount_table,
                    706:                               refcount_table_size,
                    707:                               offset & ~511, nb_csectors * 512);
                    708:             } else {
                    709:                 /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */
                    710:                 if (check_copied) {
                    711:                     uint64_t entry = offset;
                    712:                     offset &= ~QCOW_OFLAG_COPIED;
                    713:                     refcount = get_refcount(bs, offset >> s->cluster_bits);
                    714:                     if ((refcount == 1) != ((entry & QCOW_OFLAG_COPIED) != 0)) {
                    715:                         fprintf(stderr, "ERROR OFLAG_COPIED: offset=%"
                    716:                             PRIx64 " refcount=%d\n", entry, refcount);
                    717:                         errors++;
                    718:                     }
                    719:                 }
                    720: 
                    721:                 /* Mark cluster as used */
                    722:                 offset &= ~QCOW_OFLAG_COPIED;
                    723:                 errors += inc_refcounts(bs, refcount_table,
                    724:                               refcount_table_size,
                    725:                               offset, s->cluster_size);
                    726: 
                    727:                 /* Correct offsets are cluster aligned */
                    728:                 if (offset & (s->cluster_size - 1)) {
                    729:                     fprintf(stderr, "ERROR offset=%" PRIx64 ": Cluster is not "
                    730:                         "properly aligned; L2 entry corrupted.\n", offset);
                    731:                     errors++;
                    732:                 }
                    733:             }
                    734:         }
                    735:     }
                    736: 
                    737:     qemu_free(l2_table);
                    738:     return errors;
                    739: 
                    740: fail:
                    741:     fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
                    742:     qemu_free(l2_table);
                    743:     return -EIO;
                    744: }
                    745: 
                    746: /*
                    747:  * Increases the refcount for the L1 table, its L2 tables and all referenced
                    748:  * clusters in the given refcount table. While doing so, performs some checks
                    749:  * on L1 and L2 entries.
                    750:  *
                    751:  * Returns the number of errors found by the checks or -errno if an internal
                    752:  * error occurred.
                    753:  */
                    754: static int check_refcounts_l1(BlockDriverState *bs,
                    755:                               uint16_t *refcount_table,
                    756:                               int refcount_table_size,
                    757:                               int64_t l1_table_offset, int l1_size,
                    758:                               int check_copied)
                    759: {
                    760:     BDRVQcowState *s = bs->opaque;
                    761:     uint64_t *l1_table, l2_offset, l1_size2;
                    762:     int i, refcount, ret;
                    763:     int errors = 0;
                    764: 
                    765:     l1_size2 = l1_size * sizeof(uint64_t);
                    766: 
                    767:     /* Mark L1 table as used */
                    768:     errors += inc_refcounts(bs, refcount_table, refcount_table_size,
                    769:                   l1_table_offset, l1_size2);
                    770: 
                    771:     /* Read L1 table entries from disk */
                    772:     l1_table = qemu_malloc(l1_size2);
                    773:     if (bdrv_pread(s->hd, l1_table_offset,
                    774:                    l1_table, l1_size2) != l1_size2)
                    775:         goto fail;
                    776:     for(i = 0;i < l1_size; i++)
                    777:         be64_to_cpus(&l1_table[i]);
                    778: 
                    779:     /* Do the actual checks */
                    780:     for(i = 0; i < l1_size; i++) {
                    781:         l2_offset = l1_table[i];
                    782:         if (l2_offset) {
                    783:             /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */
                    784:             if (check_copied) {
                    785:                 refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED)
                    786:                     >> s->cluster_bits);
                    787:                 if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) {
                    788:                     fprintf(stderr, "ERROR OFLAG_COPIED: l2_offset=%" PRIx64
                    789:                         " refcount=%d\n", l2_offset, refcount);
                    790:                     errors++;
                    791:                 }
                    792:             }
                    793: 
                    794:             /* Mark L2 table as used */
                    795:             l2_offset &= ~QCOW_OFLAG_COPIED;
                    796:             errors += inc_refcounts(bs, refcount_table,
                    797:                           refcount_table_size,
                    798:                           l2_offset,
                    799:                           s->cluster_size);
                    800: 
                    801:             /* L2 tables are cluster aligned */
                    802:             if (l2_offset & (s->cluster_size - 1)) {
                    803:                 fprintf(stderr, "ERROR l2_offset=%" PRIx64 ": Table is not "
                    804:                     "cluster aligned; L1 entry corrupted\n", l2_offset);
                    805:                 errors++;
                    806:             }
                    807: 
                    808:             /* Process and check L2 entries */
                    809:             ret = check_refcounts_l2(bs, refcount_table, refcount_table_size,
                    810:                 l2_offset, check_copied);
                    811:             if (ret < 0) {
                    812:                 goto fail;
                    813:             }
                    814:             errors += ret;
                    815:         }
                    816:     }
                    817:     qemu_free(l1_table);
                    818:     return errors;
                    819: 
                    820: fail:
                    821:     fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
                    822:     qemu_free(l1_table);
                    823:     return -EIO;
                    824: }
                    825: 
                    826: /*
                    827:  * Checks an image for refcount consistency.
                    828:  *
                    829:  * Returns 0 if no errors are found, the number of errors in case the image is
                    830:  * detected as corrupted, and -errno when an internal error occured.
                    831:  */
                    832: int qcow2_check_refcounts(BlockDriverState *bs)
                    833: {
                    834:     BDRVQcowState *s = bs->opaque;
                    835:     int64_t size;
                    836:     int nb_clusters, refcount1, refcount2, i;
                    837:     QCowSnapshot *sn;
                    838:     uint16_t *refcount_table;
                    839:     int ret, errors = 0;
                    840: 
                    841:     size = bdrv_getlength(s->hd);
                    842:     nb_clusters = size_to_clusters(s, size);
                    843:     refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
                    844: 
                    845:     /* header */
                    846:     errors += inc_refcounts(bs, refcount_table, nb_clusters,
                    847:                   0, s->cluster_size);
                    848: 
                    849:     /* current L1 table */
                    850:     ret = check_refcounts_l1(bs, refcount_table, nb_clusters,
                    851:                        s->l1_table_offset, s->l1_size, 1);
                    852:     if (ret < 0) {
                    853:         return ret;
                    854:     }
                    855:     errors += ret;
                    856: 
                    857:     /* snapshots */
                    858:     for(i = 0; i < s->nb_snapshots; i++) {
                    859:         sn = s->snapshots + i;
                    860:         check_refcounts_l1(bs, refcount_table, nb_clusters,
                    861:                            sn->l1_table_offset, sn->l1_size, 0);
                    862:     }
                    863:     errors += inc_refcounts(bs, refcount_table, nb_clusters,
                    864:                   s->snapshots_offset, s->snapshots_size);
                    865: 
                    866:     /* refcount data */
                    867:     errors += inc_refcounts(bs, refcount_table, nb_clusters,
                    868:                   s->refcount_table_offset,
                    869:                   s->refcount_table_size * sizeof(uint64_t));
                    870:     for(i = 0; i < s->refcount_table_size; i++) {
                    871:         int64_t offset;
                    872:         offset = s->refcount_table[i];
                    873:         if (offset != 0) {
                    874:             errors += inc_refcounts(bs, refcount_table, nb_clusters,
                    875:                           offset, s->cluster_size);
                    876:         }
                    877:     }
                    878: 
                    879:     /* compare ref counts */
                    880:     for(i = 0; i < nb_clusters; i++) {
                    881:         refcount1 = get_refcount(bs, i);
                    882:         refcount2 = refcount_table[i];
                    883:         if (refcount1 != refcount2) {
                    884:             fprintf(stderr, "ERROR cluster %d refcount=%d reference=%d\n",
                    885:                    i, refcount1, refcount2);
                    886:             errors++;
                    887:         }
                    888:     }
                    889: 
                    890:     qemu_free(refcount_table);
                    891: 
                    892:     return errors;
                    893: }
                    894: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.