|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.