qcow2: Mark qcow2_signal_corruption() and callers GRAPH_RDLOCK

This adds GRAPH_RDLOCK annotations to declare that callers of
qcow2_signal_corruption() need to hold a reader lock for the graph
because it calls bdrv_get_node_name(), which accesses the parents list
of a node.

For some places, we know that they will hold the lock, but we don't have
the GRAPH_RDLOCK annotations yet. In this case, add assume_graph_lock()
with a FIXME comment. These places will be removed once everything is
properly annotated.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20230929145157.45443-15-kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
master
Kevin Wolf 2023-09-29 16:51:49 +02:00
parent bd131d6705
commit 0bb79c97fd
11 changed files with 249 additions and 191 deletions

View File

@ -7250,7 +7250,8 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
{ {
BdrvOpBlocker *blocker; BdrvOpBlocker *blocker;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
assume_graph_lock(); /* FIXME */
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX); assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
if (!QLIST_EMPTY(&bs->op_blockers[op])) { if (!QLIST_EMPTY(&bs->op_blockers[op])) {

View File

@ -2905,6 +2905,8 @@ const BdrvChild *blk_root(BlockBackend *blk)
int blk_make_empty(BlockBackend *blk, Error **errp) int blk_make_empty(BlockBackend *blk, Error **errp)
{ {
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
if (!blk_is_available(blk)) { if (!blk_is_available(blk)) {
error_setg(errp, "No medium inserted"); error_setg(errp, "No medium inserted");
return -ENOMEDIUM; return -ENOMEDIUM;

View File

@ -206,8 +206,9 @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
return 0; return 0;
} }
static void clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table, static void GRAPH_RDLOCK
uint32_t bitmap_table_size) clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
uint32_t bitmap_table_size)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int i; int i;
@ -261,7 +262,8 @@ fail:
return ret; return ret;
} }
static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb) static int GRAPH_RDLOCK
free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
{ {
int ret; int ret;
uint64_t *bitmap_table; uint64_t *bitmap_table;
@ -732,8 +734,9 @@ out:
* Store bitmap list to qcow2 image as a bitmap directory. * Store bitmap list to qcow2 image as a bitmap directory.
* Everything is checked. * Everything is checked.
*/ */
static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list, static int GRAPH_RDLOCK
uint64_t *offset, uint64_t *size, bool in_place) bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
uint64_t *offset, uint64_t *size, bool in_place)
{ {
int ret; int ret;
uint8_t *dir; uint8_t *dir;
@ -831,8 +834,9 @@ fail:
* Bitmap List end * Bitmap List end
*/ */
static int update_ext_header_and_dir_in_place(BlockDriverState *bs, static int GRAPH_RDLOCK
Qcow2BitmapList *bm_list) update_ext_header_and_dir_in_place(BlockDriverState *bs,
Qcow2BitmapList *bm_list)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int ret; int ret;
@ -879,8 +883,8 @@ static int update_ext_header_and_dir_in_place(BlockDriverState *bs,
*/ */
} }
static int update_ext_header_and_dir(BlockDriverState *bs, static int GRAPH_RDLOCK
Qcow2BitmapList *bm_list) update_ext_header_and_dir(BlockDriverState *bs, Qcow2BitmapList *bm_list)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int ret; int ret;
@ -1273,9 +1277,9 @@ out:
/* store_bitmap_data() /* store_bitmap_data()
* Store bitmap to image, filling bitmap table accordingly. * Store bitmap to image, filling bitmap table accordingly.
*/ */
static uint64_t *store_bitmap_data(BlockDriverState *bs, static uint64_t * GRAPH_RDLOCK
BdrvDirtyBitmap *bitmap, store_bitmap_data(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
uint32_t *bitmap_table_size, Error **errp) uint32_t *bitmap_table_size, Error **errp)
{ {
int ret; int ret;
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
@ -1372,7 +1376,8 @@ fail:
* Store bm->dirty_bitmap to qcow2. * Store bm->dirty_bitmap to qcow2.
* Set bm->table_offset and bm->table_size accordingly. * Set bm->table_offset and bm->table_size accordingly.
*/ */
static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp) static int GRAPH_RDLOCK
store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
{ {
int ret; int ret;
uint64_t *tb; uint64_t *tb;

View File

@ -163,7 +163,8 @@ int qcow2_cache_destroy(Qcow2Cache *c)
return 0; return 0;
} }
static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c) static int GRAPH_RDLOCK
qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
{ {
int ret; int ret;
@ -178,7 +179,8 @@ static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
return 0; return 0;
} }
static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i) static int GRAPH_RDLOCK
qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int ret = 0; int ret = 0;
@ -318,8 +320,9 @@ int qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c)
return 0; return 0;
} }
static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c, static int GRAPH_RDLOCK
uint64_t offset, void **table, bool read_from_disk) qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
void **table, bool read_from_disk)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int i; int i;

View File

@ -207,8 +207,9 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
* the cache is used; otherwise the L2 slice is loaded from the image * the cache is used; otherwise the L2 slice is loaded from the image
* file. * file.
*/ */
static int l2_load(BlockDriverState *bs, uint64_t offset, static int GRAPH_RDLOCK
uint64_t l2_offset, uint64_t **l2_slice) l2_load(BlockDriverState *bs, uint64_t offset,
uint64_t l2_offset, uint64_t **l2_slice)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int start_of_slice = l2_entry_size(s) * int start_of_slice = l2_entry_size(s) *
@ -269,7 +270,7 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
* *
*/ */
static int l2_allocate(BlockDriverState *bs, int l1_index) static int GRAPH_RDLOCK l2_allocate(BlockDriverState *bs, int l1_index)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint64_t old_l2_offset; uint64_t old_l2_offset;
@ -751,9 +752,9 @@ fail:
* *
* Returns 0 on success, -errno in failure case * Returns 0 on success, -errno in failure case
*/ */
static int get_cluster_table(BlockDriverState *bs, uint64_t offset, static int GRAPH_RDLOCK
uint64_t **new_l2_slice, get_cluster_table(BlockDriverState *bs, uint64_t offset,
int *new_l2_index) uint64_t **new_l2_slice, int *new_l2_index)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
unsigned int l2_index; unsigned int l2_index;
@ -1155,11 +1156,10 @@ void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
* *
* Returns 0 on success, -errno on failure. * Returns 0 on success, -errno on failure.
*/ */
static int coroutine_fn calculate_l2_meta(BlockDriverState *bs, static int coroutine_fn GRAPH_RDLOCK
uint64_t host_cluster_offset, calculate_l2_meta(BlockDriverState *bs, uint64_t host_cluster_offset,
uint64_t guest_offset, unsigned bytes, uint64_t guest_offset, unsigned bytes, uint64_t *l2_slice,
uint64_t *l2_slice, QCowL2Meta **m, QCowL2Meta **m, bool keep_old)
bool keep_old)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset); int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset);
@ -1490,9 +1490,9 @@ static int coroutine_fn handle_dependencies(BlockDriverState *bs,
* *
* -errno: in error cases * -errno: in error cases
*/ */
static int coroutine_fn handle_copied(BlockDriverState *bs, static int coroutine_fn GRAPH_RDLOCK
uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes, handle_copied(BlockDriverState *bs, uint64_t guest_offset,
QCowL2Meta **m) uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int l2_index; int l2_index;
@ -1600,10 +1600,9 @@ out:
* function has been waiting for another request and the allocation must be * function has been waiting for another request and the allocation must be
* restarted, but the whole request should not be failed. * restarted, but the whole request should not be failed.
*/ */
static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs, static int coroutine_fn GRAPH_RDLOCK
uint64_t guest_offset, do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
uint64_t *host_offset, uint64_t *host_offset, uint64_t *nb_clusters)
uint64_t *nb_clusters)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
@ -1658,9 +1657,9 @@ static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
* *
* -errno: in error cases * -errno: in error cases
*/ */
static int coroutine_fn handle_alloc(BlockDriverState *bs, static int coroutine_fn GRAPH_RDLOCK
uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes, handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
QCowL2Meta **m) uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int l2_index; int l2_index;
@ -1898,9 +1897,9 @@ again:
* all clusters in the same L2 slice) and returns the number of discarded * all clusters in the same L2 slice) and returns the number of discarded
* clusters. * clusters.
*/ */
static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, static int GRAPH_RDLOCK
uint64_t nb_clusters, discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters,
enum qcow2_discard_type type, bool full_discard) enum qcow2_discard_type type, bool full_discard)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint64_t *l2_slice; uint64_t *l2_slice;
@ -2037,7 +2036,7 @@ fail:
* all clusters in the same L2 slice) and returns the number of zeroed * all clusters in the same L2 slice) and returns the number of zeroed
* clusters. * clusters.
*/ */
static int coroutine_fn static int coroutine_fn GRAPH_RDLOCK
zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
uint64_t nb_clusters, int flags) uint64_t nb_clusters, int flags)
{ {
@ -2093,7 +2092,7 @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
return nb_clusters; return nb_clusters;
} }
static int coroutine_fn static int coroutine_fn GRAPH_RDLOCK
zero_l2_subclusters(BlockDriverState *bs, uint64_t offset, zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
unsigned nb_subclusters) unsigned nb_subclusters)
{ {
@ -2231,11 +2230,12 @@ fail:
* status_cb(). l1_entries contains the total number of L1 entries and * status_cb(). l1_entries contains the total number of L1 entries and
* *visited_l1_entries counts all visited L1 entries. * *visited_l1_entries counts all visited L1 entries.
*/ */
static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, static int GRAPH_RDLOCK
int l1_size, int64_t *visited_l1_entries, expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
int64_t l1_entries, int l1_size, int64_t *visited_l1_entries,
BlockDriverAmendStatusCB *status_cb, int64_t l1_entries,
void *cb_opaque) BlockDriverAmendStatusCB *status_cb,
void *cb_opaque)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
bool is_active_l1 = (l1_table == s->l1_table); bool is_active_l1 = (l1_table == s->l1_table);

View File

@ -229,9 +229,9 @@ static void set_refcount_ro6(void *refcount_array, uint64_t index,
} }
static int load_refcount_block(BlockDriverState *bs, static int GRAPH_RDLOCK
int64_t refcount_block_offset, load_refcount_block(BlockDriverState *bs, int64_t refcount_block_offset,
void **refcount_block) void **refcount_block)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
@ -302,8 +302,9 @@ static int in_same_refcount_block(BDRVQcow2State *s, uint64_t offset_a,
* *
* Returns 0 on success or -errno in error case * Returns 0 on success or -errno in error case
*/ */
static int alloc_refcount_block(BlockDriverState *bs, static int GRAPH_RDLOCK
int64_t cluster_index, void **refcount_block) alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index,
void **refcount_block)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
unsigned int refcount_table_index; unsigned int refcount_table_index;
@ -806,12 +807,9 @@ found:
/* XXX: cache several refcount block clusters ? */ /* XXX: cache several refcount block clusters ? */
/* @addend is the absolute value of the addend; if @decrease is set, @addend /* @addend is the absolute value of the addend; if @decrease is set, @addend
* will be subtracted from the current refcount, otherwise it will be added */ * will be subtracted from the current refcount, otherwise it will be added */
static int update_refcount(BlockDriverState *bs, static int GRAPH_RDLOCK
int64_t offset, update_refcount(BlockDriverState *bs, int64_t offset, int64_t length,
int64_t length, uint64_t addend, bool decrease, enum qcow2_discard_type type)
uint64_t addend,
bool decrease,
enum qcow2_discard_type type)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int64_t start, last, cluster_offset; int64_t start, last, cluster_offset;
@ -967,8 +965,8 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
/* return < 0 if error */ /* return < 0 if error */
static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size, static int64_t GRAPH_RDLOCK
uint64_t max) alloc_clusters_noref(BlockDriverState *bs, uint64_t size, uint64_t max)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint64_t i, nb_clusters, refcount; uint64_t i, nb_clusters, refcount;
@ -2302,7 +2300,7 @@ calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
* Compares the actual reference count for each cluster in the image against the * Compares the actual reference count for each cluster in the image against the
* refcount as reported by the refcount structures on-disk. * refcount as reported by the refcount structures on-disk.
*/ */
static void coroutine_fn static void coroutine_fn GRAPH_RDLOCK
compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res, compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix, bool *rebuild, BdrvCheckMode fix, bool *rebuild,
int64_t *highest_cluster, int64_t *highest_cluster,
@ -3103,20 +3101,22 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
* *
* @allocated should be set to true if a new cluster has been allocated. * @allocated should be set to true if a new cluster has been allocated.
*/ */
typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable, typedef int /* GRAPH_RDLOCK_PTR */
uint64_t reftable_index, uint64_t *reftable_size, (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
void *refblock, bool refblock_empty, uint64_t reftable_index, uint64_t *reftable_size,
bool *allocated, Error **errp); void *refblock, bool refblock_empty,
bool *allocated, Error **errp);
/** /**
* This "operation" for walk_over_reftable() allocates the refblock on disk (if * This "operation" for walk_over_reftable() allocates the refblock on disk (if
* it is not empty) and inserts its offset into the new reftable. The size of * it is not empty) and inserts its offset into the new reftable. The size of
* this new reftable is increased as required. * this new reftable is increased as required.
*/ */
static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable, static int GRAPH_RDLOCK
uint64_t reftable_index, uint64_t *reftable_size, alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
void *refblock, bool refblock_empty, bool *allocated, uint64_t reftable_index, uint64_t *reftable_size,
Error **errp) void *refblock, bool refblock_empty, bool *allocated,
Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int64_t offset; int64_t offset;
@ -3166,10 +3166,11 @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
* offset specified by the new reftable's entry. It does not modify the new * offset specified by the new reftable's entry. It does not modify the new
* reftable or change any refcounts. * reftable or change any refcounts.
*/ */
static int flush_refblock(BlockDriverState *bs, uint64_t **reftable, static int GRAPH_RDLOCK
uint64_t reftable_index, uint64_t *reftable_size, flush_refblock(BlockDriverState *bs, uint64_t **reftable,
void *refblock, bool refblock_empty, bool *allocated, uint64_t reftable_index, uint64_t *reftable_size,
Error **errp) void *refblock, bool refblock_empty, bool *allocated,
Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int64_t offset; int64_t offset;
@ -3210,16 +3211,17 @@ static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
* *
* @allocated is set to true if a new cluster has been allocated. * @allocated is set to true if a new cluster has been allocated.
*/ */
static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable, static int GRAPH_RDLOCK
uint64_t *new_reftable_index, walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
uint64_t *new_reftable_size, uint64_t *new_reftable_index,
void *new_refblock, int new_refblock_size, uint64_t *new_reftable_size,
int new_refcount_bits, void *new_refblock, int new_refblock_size,
RefblockFinishOp *operation, bool *allocated, int new_refcount_bits,
Qcow2SetRefcountFunc *new_set_refcount, RefblockFinishOp *operation, bool *allocated,
BlockDriverAmendStatusCB *status_cb, Qcow2SetRefcountFunc *new_set_refcount,
void *cb_opaque, int index, int total, BlockDriverAmendStatusCB *status_cb,
Error **errp) void *cb_opaque, int index, int total,
Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint64_t reftable_index; uint64_t reftable_index;
@ -3545,8 +3547,8 @@ done:
return ret; return ret;
} }
static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs, static int64_t coroutine_fn GRAPH_RDLOCK
uint64_t offset) get_refblock_offset(BlockDriverState *bs, uint64_t offset)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint32_t index = offset_to_reftable_index(s, offset); uint32_t index = offset_to_reftable_index(s, offset);
@ -3565,7 +3567,7 @@ static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs,
return covering_refblock_offset; return covering_refblock_offset;
} }
static int coroutine_fn static int coroutine_fn GRAPH_RDLOCK
qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs) qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;

View File

@ -536,7 +536,7 @@ int qcow2_mark_dirty(BlockDriverState *bs)
* function when there are no pending requests, it does not guard against * function when there are no pending requests, it does not guard against
* concurrent requests dirtying the image. * concurrent requests dirtying the image.
*/ */
static int qcow2_mark_clean(BlockDriverState *bs) static int GRAPH_RDLOCK qcow2_mark_clean(BlockDriverState *bs)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
@ -570,7 +570,8 @@ int qcow2_mark_corrupt(BlockDriverState *bs)
* Marks the image as consistent, i.e., unsets the corrupt bit, and flushes * Marks the image as consistent, i.e., unsets the corrupt bit, and flushes
* before if necessary. * before if necessary.
*/ */
static int coroutine_fn qcow2_mark_consistent(BlockDriverState *bs) static int coroutine_fn GRAPH_RDLOCK
qcow2_mark_consistent(BlockDriverState *bs)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
@ -980,10 +981,9 @@ typedef struct Qcow2ReopenState {
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */ QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
} Qcow2ReopenState; } Qcow2ReopenState;
static int qcow2_update_options_prepare(BlockDriverState *bs, static int GRAPH_RDLOCK
Qcow2ReopenState *r, qcow2_update_options_prepare(BlockDriverState *bs, Qcow2ReopenState *r,
QDict *options, int flags, QDict *options, int flags, Error **errp)
Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
QemuOpts *opts = NULL; QemuOpts *opts = NULL;
@ -1260,7 +1260,7 @@ static void qcow2_update_options_abort(BlockDriverState *bs,
qapi_free_QCryptoBlockOpenOptions(r->crypto_opts); qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
} }
static int coroutine_fn static int coroutine_fn GRAPH_RDLOCK
qcow2_update_options(BlockDriverState *bs, QDict *options, int flags, qcow2_update_options(BlockDriverState *bs, QDict *options, int flags,
Error **errp) Error **errp)
{ {
@ -1969,13 +1969,17 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
bs->bl.pdiscard_alignment = s->cluster_size; bs->bl.pdiscard_alignment = s->cluster_size;
} }
static int qcow2_reopen_prepare(BDRVReopenState *state, static int GRAPH_UNLOCKED
BlockReopenQueue *queue, Error **errp) qcow2_reopen_prepare(BDRVReopenState *state,BlockReopenQueue *queue,
Error **errp)
{ {
BDRVQcow2State *s = state->bs->opaque; BDRVQcow2State *s = state->bs->opaque;
Qcow2ReopenState *r; Qcow2ReopenState *r;
int ret; int ret;
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
r = g_new0(Qcow2ReopenState, 1); r = g_new0(Qcow2ReopenState, 1);
state->opaque = r; state->opaque = r;
@ -2038,6 +2042,8 @@ static void qcow2_reopen_commit(BDRVReopenState *state)
static void qcow2_reopen_commit_post(BDRVReopenState *state) static void qcow2_reopen_commit_post(BDRVReopenState *state)
{ {
GRAPH_RDLOCK_GUARD_MAINLOOP();
if (state->flags & BDRV_O_RDWR) { if (state->flags & BDRV_O_RDWR) {
Error *local_err = NULL; Error *local_err = NULL;
@ -4079,8 +4085,8 @@ qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
return ret; return ret;
} }
static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs, static int coroutine_fn GRAPH_RDLOCK
int64_t offset, int64_t bytes) qcow2_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
{ {
int ret; int ret;
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
@ -4825,7 +4831,7 @@ fail:
return ret; return ret;
} }
static int make_completely_empty(BlockDriverState *bs) static int GRAPH_RDLOCK make_completely_empty(BlockDriverState *bs)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
Error *local_err = NULL; Error *local_err = NULL;
@ -4976,7 +4982,7 @@ fail:
return ret; return ret;
} }
static int qcow2_make_empty(BlockDriverState *bs) static int GRAPH_RDLOCK qcow2_make_empty(BlockDriverState *bs)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint64_t offset, end_offset; uint64_t offset, end_offset;
@ -5020,7 +5026,7 @@ static int qcow2_make_empty(BlockDriverState *bs)
return ret; return ret;
} }
static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs) static coroutine_fn GRAPH_RDLOCK int qcow2_co_flush_to_os(BlockDriverState *bs)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int ret; int ret;
@ -5369,7 +5375,7 @@ qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
return bs->drv->bdrv_co_preadv_part(bs, offset, qiov->size, qiov, 0, 0); return bs->drv->bdrv_co_preadv_part(bs, offset, qiov->size, qiov, 0, 0);
} }
static int qcow2_has_compressed_clusters(BlockDriverState *bs) static int GRAPH_RDLOCK qcow2_has_compressed_clusters(BlockDriverState *bs)
{ {
int64_t offset = 0; int64_t offset = 0;
int64_t bytes = bdrv_getlength(bs); int64_t bytes = bdrv_getlength(bs);
@ -5405,9 +5411,10 @@ static int qcow2_has_compressed_clusters(BlockDriverState *bs)
* Downgrades an image's version. To achieve this, any incompatible features * Downgrades an image's version. To achieve this, any incompatible features
* have to be removed. * have to be removed.
*/ */
static int qcow2_downgrade(BlockDriverState *bs, int target_version, static int GRAPH_RDLOCK
BlockDriverAmendStatusCB *status_cb, void *cb_opaque, qcow2_downgrade(BlockDriverState *bs, int target_version,
Error **errp) BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int current_version = s->qcow_version; int current_version = s->qcow_version;
@ -5515,9 +5522,10 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
* features of older versions, some things may have to be presented * features of older versions, some things may have to be presented
* differently. * differently.
*/ */
static int qcow2_upgrade(BlockDriverState *bs, int target_version, static int GRAPH_RDLOCK
BlockDriverAmendStatusCB *status_cb, void *cb_opaque, qcow2_upgrade(BlockDriverState *bs, int target_version,
Error **errp) BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
bool need_snapshot_update; bool need_snapshot_update;
@ -5643,11 +5651,10 @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
info->original_cb_opaque); info->original_cb_opaque);
} }
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, static int GRAPH_RDLOCK
BlockDriverAmendStatusCB *status_cb, qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
void *cb_opaque, BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
bool force, bool force, Error **errp)
Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
int old_version = s->qcow_version, new_version = old_version; int old_version = s->qcow_version, new_version = old_version;
@ -5947,8 +5954,6 @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
char *message; char *message;
va_list ap; va_list ap;
assume_graph_lock(); /* FIXME */
fatal = fatal && bdrv_is_writable(bs); fatal = fatal && bdrv_is_writable(bs);
if (s->signaled_corruption && if (s->signaled_corruption &&

View File

@ -838,9 +838,10 @@ int qcow2_mark_dirty(BlockDriverState *bs);
int qcow2_mark_corrupt(BlockDriverState *bs); int qcow2_mark_corrupt(BlockDriverState *bs);
int qcow2_update_header(BlockDriverState *bs); int qcow2_update_header(BlockDriverState *bs);
void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, void GRAPH_RDLOCK
int64_t size, const char *message_format, ...) qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
G_GNUC_PRINTF(5, 6); int64_t size, const char *message_format, ...)
G_GNUC_PRINTF(5, 6);
int qcow2_validate_table(BlockDriverState *bs, uint64_t offset, int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
uint64_t entries, size_t entry_len, uint64_t entries, size_t entry_len,
@ -851,33 +852,41 @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(BlockDriverState *bs); int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(BlockDriverState *bs);
void qcow2_refcount_close(BlockDriverState *bs); void qcow2_refcount_close(BlockDriverState *bs);
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index, int GRAPH_RDLOCK qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
uint64_t *refcount); uint64_t *refcount);
int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index, int GRAPH_RDLOCK
uint64_t addend, bool decrease, qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
enum qcow2_discard_type type); uint64_t addend, bool decrease,
enum qcow2_discard_type type);
int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t offset, int64_t GRAPH_RDLOCK
uint64_t additional_clusters, bool exact_size, qcow2_refcount_area(BlockDriverState *bs, uint64_t offset,
int new_refblock_index, uint64_t additional_clusters, bool exact_size,
uint64_t new_refblock_offset); int new_refblock_index,
uint64_t new_refblock_offset);
int64_t GRAPH_RDLOCK
qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
int64_t GRAPH_RDLOCK coroutine_fn
qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
int64_t nb_clusters);
int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
int64_t coroutine_fn qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
int64_t nb_clusters);
int64_t coroutine_fn GRAPH_RDLOCK qcow2_alloc_bytes(BlockDriverState *bs, int size); int64_t coroutine_fn GRAPH_RDLOCK qcow2_alloc_bytes(BlockDriverState *bs, int size);
void qcow2_free_clusters(BlockDriverState *bs, void GRAPH_RDLOCK qcow2_free_clusters(BlockDriverState *bs,
int64_t offset, int64_t size, int64_t offset, int64_t size,
enum qcow2_discard_type type); enum qcow2_discard_type type);
void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry, void GRAPH_RDLOCK
enum qcow2_discard_type type); qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
enum qcow2_discard_type type);
int qcow2_update_snapshot_refcount(BlockDriverState *bs, int GRAPH_RDLOCK
int64_t l1_table_offset, int l1_size, int addend); qcow2_update_snapshot_refcount(BlockDriverState *bs, int64_t l1_table_offset,
int l1_size, int addend);
int qcow2_flush_caches(BlockDriverState *bs); int GRAPH_RDLOCK qcow2_flush_caches(BlockDriverState *bs);
int qcow2_write_caches(BlockDriverState *bs); int GRAPH_RDLOCK qcow2_write_caches(BlockDriverState *bs);
int coroutine_fn qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, int coroutine_fn qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix); BdrvCheckMode fix);
@ -885,39 +894,48 @@ void qcow2_process_discards(BlockDriverState *bs, int ret);
int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, 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 ign, int64_t offset, int GRAPH_RDLOCK
int64_t size, bool data_file); qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
int64_t size, bool data_file);
int coroutine_fn qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, int coroutine_fn qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
void **refcount_table, void **refcount_table,
int64_t *refcount_table_size, int64_t *refcount_table_size,
int64_t offset, int64_t size); int64_t offset, int64_t size);
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, int GRAPH_RDLOCK
BlockDriverAmendStatusCB *status_cb, qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
void *cb_opaque, Error **errp); BlockDriverAmendStatusCB *status_cb,
void *cb_opaque, Error **errp);
int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs); int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs);
int64_t coroutine_fn qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
int64_t coroutine_fn GRAPH_RDLOCK
qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
qcow2_detect_metadata_preallocation(BlockDriverState *bs); qcow2_detect_metadata_preallocation(BlockDriverState *bs);
/* qcow2-cluster.c functions */ /* qcow2-cluster.c functions */
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, int GRAPH_RDLOCK
bool exact_size); qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size); qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); int GRAPH_RDLOCK qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
uint8_t *buf, int nb_sectors, bool enc, Error **errp); uint8_t *buf, int nb_sectors, bool enc, Error **errp);
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset, int GRAPH_RDLOCK
unsigned int *bytes, uint64_t *host_offset, qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
QCow2SubclusterType *subcluster_type); unsigned int *bytes, uint64_t *host_offset,
int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, QCow2SubclusterType *subcluster_type);
unsigned int *bytes,
uint64_t *host_offset, QCowL2Meta **m); int coroutine_fn GRAPH_RDLOCK
qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
unsigned int *bytes, uint64_t *host_offset,
QCowL2Meta **m);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset,
int compressed_size, uint64_t *host_offset); int compressed_size, uint64_t *host_offset);
@ -927,26 +945,33 @@ void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m); void coroutine_fn GRAPH_RDLOCK
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
uint64_t bytes, enum qcow2_discard_type type,
bool full_discard); int GRAPH_RDLOCK
qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
enum qcow2_discard_type type, bool full_discard);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes, qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
int flags); int flags);
int qcow2_expand_zero_clusters(BlockDriverState *bs, int GRAPH_RDLOCK
BlockDriverAmendStatusCB *status_cb, qcow2_expand_zero_clusters(BlockDriverState *bs,
void *cb_opaque); BlockDriverAmendStatusCB *status_cb,
void *cb_opaque);
/* qcow2-snapshot.c functions */ /* qcow2-snapshot.c functions */
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); int GRAPH_RDLOCK
int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id); qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
int qcow2_snapshot_delete(BlockDriverState *bs,
const char *snapshot_id, int GRAPH_RDLOCK
const char *name, qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id);
Error **errp);
int GRAPH_RDLOCK
qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id,
const char *name, Error **errp);
int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab); int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab);
int qcow2_snapshot_load_tmp(BlockDriverState *bs, int qcow2_snapshot_load_tmp(BlockDriverState *bs,
const char *snapshot_id, const char *snapshot_id,
@ -956,15 +981,15 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
void qcow2_free_snapshots(BlockDriverState *bs); void qcow2_free_snapshots(BlockDriverState *bs);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
qcow2_read_snapshots(BlockDriverState *bs, Error **errp); qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
int qcow2_write_snapshots(BlockDriverState *bs); int GRAPH_RDLOCK qcow2_write_snapshots(BlockDriverState *bs);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result, qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix); BdrvCheckMode fix);
int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs, int coroutine_fn GRAPH_RDLOCK
BdrvCheckResult *result, qcow2_check_fix_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix); BdrvCheckMode fix);
/* qcow2-cache.c functions */ /* qcow2-cache.c functions */
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables, Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
@ -972,19 +997,23 @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
int qcow2_cache_destroy(Qcow2Cache *c); int qcow2_cache_destroy(Qcow2Cache *c);
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table); void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c); int GRAPH_RDLOCK qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c); int GRAPH_RDLOCK qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c, int GRAPH_RDLOCK qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
Qcow2Cache *dependency); Qcow2Cache *dependency);
void qcow2_cache_depends_on_flush(Qcow2Cache *c); void qcow2_cache_depends_on_flush(Qcow2Cache *c);
void qcow2_cache_clean_unused(Qcow2Cache *c); void qcow2_cache_clean_unused(Qcow2Cache *c);
int qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c); int GRAPH_RDLOCK qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c);
int GRAPH_RDLOCK
qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
void **table);
int GRAPH_RDLOCK
qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
void **table);
int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
void **table);
int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
void **table);
void qcow2_cache_put(Qcow2Cache *c, void **table); void qcow2_cache_put(Qcow2Cache *c, void **table);
void *qcow2_cache_is_table_offset(Qcow2Cache *c, uint64_t offset); void *qcow2_cache_is_table_offset(Qcow2Cache *c, uint64_t offset);
void qcow2_cache_discard(Qcow2Cache *c, void *table); void qcow2_cache_discard(Qcow2Cache *c, void *table);
@ -998,17 +1027,22 @@ bool coroutine_fn GRAPH_RDLOCK
qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, Error **errp); qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, Error **errp);
bool qcow2_get_bitmap_info_list(BlockDriverState *bs, bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
Qcow2BitmapInfoList **info_list, Error **errp); Qcow2BitmapInfoList **info_list, Error **errp);
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp); int GRAPH_RDLOCK qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
int GRAPH_RDLOCK qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp); int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
bool release_stored, Error **errp); bool GRAPH_RDLOCK
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp); qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, bool release_stored,
Error **errp);
bool coroutine_fn GRAPH_RDLOCK bool coroutine_fn GRAPH_RDLOCK
qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
uint32_t granularity, Error **errp); uint32_t granularity, Error **errp);
int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
const char *name, int coroutine_fn GRAPH_RDLOCK
Error **errp); qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
Error **errp);
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs); bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs, uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
uint32_t cluster_size); uint32_t cluster_size);

View File

@ -307,13 +307,16 @@ out:
return ret; return ret;
} }
static void secondary_do_checkpoint(BlockDriverState *bs, Error **errp) static void GRAPH_UNLOCKED
secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
{ {
BDRVReplicationState *s = bs->opaque; BDRVReplicationState *s = bs->opaque;
BdrvChild *active_disk = bs->file; BdrvChild *active_disk = bs->file;
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
GRAPH_RDLOCK_GUARD_MAINLOOP();
if (!s->backup_job) { if (!s->backup_job) {
error_setg(errp, "Backup job was cancelled unexpectedly"); error_setg(errp, "Backup job was cancelled unexpectedly");
return; return;
@ -531,13 +534,16 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
/* Must be true, or the bdrv_getlength() calls would have failed */ /* Must be true, or the bdrv_getlength() calls would have failed */
assert(active_disk->bs->drv && hidden_disk->bs->drv); assert(active_disk->bs->drv && hidden_disk->bs->drv);
bdrv_graph_rdlock_main_loop();
if (!active_disk->bs->drv->bdrv_make_empty || if (!active_disk->bs->drv->bdrv_make_empty ||
!hidden_disk->bs->drv->bdrv_make_empty) { !hidden_disk->bs->drv->bdrv_make_empty) {
error_setg(errp, error_setg(errp,
"Active disk or hidden disk doesn't support make_empty"); "Active disk or hidden disk doesn't support make_empty");
aio_context_release(aio_context); aio_context_release(aio_context);
bdrv_graph_rdunlock_main_loop();
return; return;
} }
bdrv_graph_rdunlock_main_loop();
/* reopen the backing file in r/w mode */ /* reopen the backing file in r/w mode */
reopen_backing_file(bs, true, &local_err); reopen_backing_file(bs, true, &local_err);

View File

@ -138,7 +138,7 @@ void GRAPH_RDLOCK
bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp); bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
int bdrv_commit(BlockDriverState *bs); int bdrv_commit(BlockDriverState *bs);
int bdrv_make_empty(BdrvChild *c, Error **errp); int GRAPH_RDLOCK bdrv_make_empty(BdrvChild *c, Error **errp);
int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file, int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
const char *backing_fmt, bool warn); const char *backing_fmt, bool warn);
void bdrv_register(BlockDriver *bdrv); void bdrv_register(BlockDriver *bdrv);

View File

@ -264,7 +264,7 @@ struct BlockDriver {
BlockDriverAmendStatusCB *status_cb, void *cb_opaque, BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
bool force, Error **errp); bool force, Error **errp);
int (*bdrv_make_empty)(BlockDriverState *bs); int GRAPH_RDLOCK_PTR (*bdrv_make_empty)(BlockDriverState *bs);
/* /*
* Refreshes the bs->exact_filename field. If that is impossible, * Refreshes the bs->exact_filename field. If that is impossible,