}
break;
case QCOW2_CLUSTER_NORMAL:
- qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK,
- nb_clusters << s->cluster_bits, type);
+ case QCOW2_CLUSTER_ZERO:
+ if (l2_entry & L2E_OFFSET_MASK) {
+ qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK,
+ nb_clusters << s->cluster_bits, type);
+ }
break;
case QCOW2_CLUSTER_UNALLOCATED:
- case QCOW2_CLUSTER_ZERO:
break;
default:
abort();
}
if (l2_dirty) {
- ret = qcow2_pre_write_overlap_check(bs,
- QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, l2_offset,
- s->cluster_size);
+ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2,
+ l2_offset, s->cluster_size);
if (ret < 0) {
fprintf(stderr, "ERROR: Could not write L2 table; metadata "
"overlap check failed: %s\n", strerror(-ret));
buf[i] = cpu_to_be64(s->refcount_table[rt_start_index + i]);
}
- ret = qcow2_pre_write_overlap_check(bs,
- QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_TABLE,
+ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_TABLE,
s->refcount_table_offset + rt_start_index * sizeof(uint64_t),
sizeof(buf));
if (ret < 0) {
/* new block has not yet been entered into refcount table, therefore it is
* no refcount block yet (regarding this check) */
- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, new_offset,
- s->cluster_size);
+ ret = qcow2_pre_write_overlap_check(bs, 0, new_offset, s->cluster_size);
if (ret < 0) {
fprintf(stderr, "Could not write refcount block; metadata overlap "
"check failed: %s\n", strerror(-ret));
* looking for overlaps with important metadata sections (L1/L2 tables etc.),
* i.e. a sanity check without relying on the refcount tables.
*
- * The chk parameter specifies exactly what checks to perform (being a bitmask
- * of QCow2MetadataOverlap values).
+ * The ign parameter specifies what checks not to perform (being a bitmask of
+ * QCow2MetadataOverlap values), i.e., what sections to ignore.
*
* Returns:
* - 0 if writing to this offset will not affect the mentioned metadata
* - a negative value (-errno) indicating an error while performing a check,
* e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2
*/
-int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset,
+int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
int64_t size)
{
BDRVQcowState *s = bs->opaque;
+ int chk = s->overlap_check & ~ign;
int i, j;
if (!size) {
* Returns 0 if there were neither overlaps nor errors while checking for
* overlaps; or a negative value (-errno) on error.
*/
-int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset,
+int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
int64_t size)
{
- int ret = qcow2_check_metadata_overlap(bs, chk, offset, size);
+ int ret = qcow2_check_metadata_overlap(bs, ign, offset, size);
if (ret < 0) {
return ret;