qcow2: Use negated overflow check mask
In qcow2_check_metadata_overlap and qcow2_pre_write_overlap_check, change the parameter signifying the checks to perform from its current positive form to a negative one, i.e., it will no longer explicitly specify every check to perform but rather a mask of checks not to perform. Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
		
							parent
							
								
									8f94a6e40e
								
							
						
					
					
						commit
						231bb26764
					
				@ -115,15 +115,13 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c == s->refcount_block_cache) {
 | 
					    if (c == s->refcount_block_cache) {
 | 
				
			||||||
        ret = qcow2_pre_write_overlap_check(bs,
 | 
					        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_BLOCK,
 | 
				
			||||||
                QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_BLOCK,
 | 
					 | 
				
			||||||
                c->entries[i].offset, s->cluster_size);
 | 
					                c->entries[i].offset, s->cluster_size);
 | 
				
			||||||
    } else if (c == s->l2_table_cache) {
 | 
					    } else if (c == s->l2_table_cache) {
 | 
				
			||||||
        ret = qcow2_pre_write_overlap_check(bs,
 | 
					        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2,
 | 
				
			||||||
                QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2,
 | 
					 | 
				
			||||||
                c->entries[i].offset, s->cluster_size);
 | 
					                c->entries[i].offset, s->cluster_size);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
 | 
					        ret = qcow2_pre_write_overlap_check(bs, 0,
 | 
				
			||||||
                c->entries[i].offset, s->cluster_size);
 | 
					                c->entries[i].offset, s->cluster_size);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -83,8 +83,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* the L1 position has not yet been updated, so these clusters must
 | 
					    /* the L1 position has not yet been updated, so these clusters must
 | 
				
			||||||
     * indeed be completely free */
 | 
					     * indeed be completely free */
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, 0, new_l1_table_offset,
 | 
				
			||||||
                                        new_l1_table_offset, new_l1_size2);
 | 
					                                        new_l1_size2);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -160,8 +160,7 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
 | 
				
			|||||||
        buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
 | 
					        buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
 | 
				
			||||||
            QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1,
 | 
					 | 
				
			||||||
            s->l1_table_offset + 8 * l1_start_index, sizeof(buf));
 | 
					            s->l1_table_offset + 8 * l1_start_index, sizeof(buf));
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
@ -396,7 +395,7 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
 | 
				
			|||||||
                        &s->aes_encrypt_key);
 | 
					                        &s->aes_encrypt_key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, 0,
 | 
				
			||||||
            cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE);
 | 
					            cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
@ -1604,8 +1603,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
 | 
					            ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size);
 | 
				
			||||||
                                                offset, s->cluster_size);
 | 
					 | 
				
			||||||
            if (ret < 0) {
 | 
					            if (ret < 0) {
 | 
				
			||||||
                if (!preallocated) {
 | 
					                if (!preallocated) {
 | 
				
			||||||
                    qcow2_free_clusters(bs, offset, s->cluster_size,
 | 
					                    qcow2_free_clusters(bs, offset, s->cluster_size,
 | 
				
			||||||
@ -1661,8 +1659,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if (l2_dirty) {
 | 
					            if (l2_dirty) {
 | 
				
			||||||
                ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT &
 | 
					                ret = qcow2_pre_write_overlap_check(bs,
 | 
				
			||||||
                        ~(QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2), l2_offset,
 | 
					                        QCOW2_OL_INACTIVE_L2 | QCOW2_OL_ACTIVE_L2, l2_offset,
 | 
				
			||||||
                        s->cluster_size);
 | 
					                        s->cluster_size);
 | 
				
			||||||
                if (ret < 0) {
 | 
					                if (ret < 0) {
 | 
				
			||||||
                    goto fail;
 | 
					                    goto fail;
 | 
				
			||||||
 | 
				
			|||||||
@ -1311,9 +1311,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (l2_dirty) {
 | 
					        if (l2_dirty) {
 | 
				
			||||||
            ret = qcow2_pre_write_overlap_check(bs,
 | 
					            ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2,
 | 
				
			||||||
                    QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, l2_offset,
 | 
					                                                l2_offset, s->cluster_size);
 | 
				
			||||||
                    s->cluster_size);
 | 
					 | 
				
			||||||
            if (ret < 0) {
 | 
					            if (ret < 0) {
 | 
				
			||||||
                fprintf(stderr, "ERROR: Could not write L2 table; metadata "
 | 
					                fprintf(stderr, "ERROR: Could not write L2 table; metadata "
 | 
				
			||||||
                        "overlap check failed: %s\n", strerror(-ret));
 | 
					                        "overlap check failed: %s\n", strerror(-ret));
 | 
				
			||||||
@ -1354,8 +1353,7 @@ static int write_reftable_entry(BlockDriverState *bs, int rt_index)
 | 
				
			|||||||
        buf[i] = cpu_to_be64(s->refcount_table[rt_start_index + i]);
 | 
					        buf[i] = cpu_to_be64(s->refcount_table[rt_start_index + i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_TABLE,
 | 
				
			||||||
            QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_TABLE,
 | 
					 | 
				
			||||||
            s->refcount_table_offset + rt_start_index * sizeof(uint64_t),
 | 
					            s->refcount_table_offset + rt_start_index * sizeof(uint64_t),
 | 
				
			||||||
            sizeof(buf));
 | 
					            sizeof(buf));
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
@ -1406,8 +1404,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* new block has not yet been entered into refcount table, therefore it is
 | 
					    /* new block has not yet been entered into refcount table, therefore it is
 | 
				
			||||||
     * no refcount block yet (regarding this check) */
 | 
					     * no refcount block yet (regarding this check) */
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, new_offset,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, 0, new_offset, s->cluster_size);
 | 
				
			||||||
            s->cluster_size);
 | 
					 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        fprintf(stderr, "Could not write refcount block; metadata overlap "
 | 
					        fprintf(stderr, "Could not write refcount block; metadata overlap "
 | 
				
			||||||
                "check failed: %s\n", strerror(-ret));
 | 
					                "check failed: %s\n", strerror(-ret));
 | 
				
			||||||
@ -1639,8 +1636,8 @@ fail:
 | 
				
			|||||||
 * looking for overlaps with important metadata sections (L1/L2 tables etc.),
 | 
					 * looking for overlaps with important metadata sections (L1/L2 tables etc.),
 | 
				
			||||||
 * i.e. a sanity check without relying on the refcount tables.
 | 
					 * i.e. a sanity check without relying on the refcount tables.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The chk parameter specifies exactly what checks to perform (being a bitmask
 | 
					 * The ign parameter specifies what checks not to perform (being a bitmask of
 | 
				
			||||||
 * of QCow2MetadataOverlap values).
 | 
					 * QCow2MetadataOverlap values), i.e., what sections to ignore.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns:
 | 
					 * Returns:
 | 
				
			||||||
 * - 0 if writing to this offset will not affect the mentioned metadata
 | 
					 * - 0 if writing to this offset will not affect the mentioned metadata
 | 
				
			||||||
@ -1648,10 +1645,11 @@ fail:
 | 
				
			|||||||
 * - a negative value (-errno) indicating an error while performing a check,
 | 
					 * - a negative value (-errno) indicating an error while performing a check,
 | 
				
			||||||
 *   e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2
 | 
					 *   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)
 | 
					                                 int64_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BDRVQcowState *s = bs->opaque;
 | 
					    BDRVQcowState *s = bs->opaque;
 | 
				
			||||||
 | 
					    int chk = QCOW2_OL_DEFAULT & ~ign;
 | 
				
			||||||
    int i, j;
 | 
					    int i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!size) {
 | 
					    if (!size) {
 | 
				
			||||||
@ -1767,10 +1765,10 @@ static const char *metadata_ol_names[] = {
 | 
				
			|||||||
 * Returns 0 if there were neither overlaps nor errors while checking for
 | 
					 * Returns 0 if there were neither overlaps nor errors while checking for
 | 
				
			||||||
 * overlaps; or a negative value (-errno) on error.
 | 
					 * 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)
 | 
					                                  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) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
 | 
				
			|||||||
@ -192,8 +192,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* The snapshot list position has not yet been updated, so these clusters
 | 
					    /* The snapshot list position has not yet been updated, so these clusters
 | 
				
			||||||
     * must indeed be completely free */
 | 
					     * must indeed be completely free */
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, 0, offset, snapshots_size);
 | 
				
			||||||
                                        snapshots_size);
 | 
					 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -395,8 +394,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 | 
				
			|||||||
        l1_table[i] = cpu_to_be64(s->l1_table[i]);
 | 
					        l1_table[i] = cpu_to_be64(s->l1_table[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset,
 | 
				
			||||||
            sn->l1_table_offset, s->l1_size * sizeof(uint64_t));
 | 
					                                        s->l1_size * sizeof(uint64_t));
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -521,8 +520,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 | 
				
			|||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qcow2_pre_write_overlap_check(bs,
 | 
					    ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
 | 
				
			||||||
            QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1,
 | 
					 | 
				
			||||||
                                        s->l1_table_offset, cur_l1_bytes);
 | 
					                                        s->l1_table_offset, cur_l1_bytes);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
 | 
				
			|||||||
@ -965,7 +965,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 | 
				
			|||||||
                cur_nr_sectors * 512);
 | 
					                cur_nr_sectors * 512);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
 | 
					        ret = qcow2_pre_write_overlap_check(bs, 0,
 | 
				
			||||||
                cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE,
 | 
					                cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE,
 | 
				
			||||||
                cur_nr_sectors * BDRV_SECTOR_SIZE);
 | 
					                cur_nr_sectors * BDRV_SECTOR_SIZE);
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
@ -1751,8 +1751,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        cluster_offset &= s->cluster_offset_mask;
 | 
					        cluster_offset &= s->cluster_offset_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
 | 
					        ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
 | 
				
			||||||
                cluster_offset, out_len);
 | 
					 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -433,9 +433,9 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void qcow2_process_discards(BlockDriverState *bs, int ret);
 | 
					void qcow2_process_discards(BlockDriverState *bs, int ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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);
 | 
					                                 int64_t size);
 | 
				
			||||||
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);
 | 
					                                  int64_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* qcow2-cluster.c functions */
 | 
					/* qcow2-cluster.c functions */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user