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>
This commit is contained in:
parent
bd131d6705
commit
0bb79c97fd
3
block.c
3
block.c
@ -7250,7 +7250,8 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
|
||||
{
|
||||
BdrvOpBlocker *blocker;
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
assume_graph_lock(); /* FIXME */
|
||||
|
||||
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
|
||||
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
|
||||
|
@ -2905,6 +2905,8 @@ const BdrvChild *blk_root(BlockBackend *blk)
|
||||
int blk_make_empty(BlockBackend *blk, Error **errp)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
if (!blk_is_available(blk)) {
|
||||
error_setg(errp, "No medium inserted");
|
||||
return -ENOMEDIUM;
|
||||
|
@ -206,7 +206,8 @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
|
||||
static void GRAPH_RDLOCK
|
||||
clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
|
||||
uint32_t bitmap_table_size)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
@ -261,7 +262,8 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
|
||||
static int GRAPH_RDLOCK
|
||||
free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
|
||||
{
|
||||
int ret;
|
||||
uint64_t *bitmap_table;
|
||||
@ -732,7 +734,8 @@ out:
|
||||
* Store bitmap list to qcow2 image as a bitmap directory.
|
||||
* Everything is checked.
|
||||
*/
|
||||
static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
|
||||
static int GRAPH_RDLOCK
|
||||
bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
|
||||
uint64_t *offset, uint64_t *size, bool in_place)
|
||||
{
|
||||
int ret;
|
||||
@ -831,7 +834,8 @@ fail:
|
||||
* Bitmap List end
|
||||
*/
|
||||
|
||||
static int update_ext_header_and_dir_in_place(BlockDriverState *bs,
|
||||
static int GRAPH_RDLOCK
|
||||
update_ext_header_and_dir_in_place(BlockDriverState *bs,
|
||||
Qcow2BitmapList *bm_list)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
@ -879,8 +883,8 @@ static int update_ext_header_and_dir_in_place(BlockDriverState *bs,
|
||||
*/
|
||||
}
|
||||
|
||||
static int update_ext_header_and_dir(BlockDriverState *bs,
|
||||
Qcow2BitmapList *bm_list)
|
||||
static int GRAPH_RDLOCK
|
||||
update_ext_header_and_dir(BlockDriverState *bs, Qcow2BitmapList *bm_list)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int ret;
|
||||
@ -1273,8 +1277,8 @@ out:
|
||||
/* store_bitmap_data()
|
||||
* Store bitmap to image, filling bitmap table accordingly.
|
||||
*/
|
||||
static uint64_t *store_bitmap_data(BlockDriverState *bs,
|
||||
BdrvDirtyBitmap *bitmap,
|
||||
static uint64_t * GRAPH_RDLOCK
|
||||
store_bitmap_data(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
|
||||
uint32_t *bitmap_table_size, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
@ -1372,7 +1376,8 @@ fail:
|
||||
* Store bm->dirty_bitmap to qcow2.
|
||||
* 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;
|
||||
uint64_t *tb;
|
||||
|
@ -163,7 +163,8 @@ int qcow2_cache_destroy(Qcow2Cache *c)
|
||||
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;
|
||||
|
||||
@ -178,7 +179,8 @@ static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
|
||||
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;
|
||||
int ret = 0;
|
||||
@ -318,8 +320,9 @@ int qcow2_cache_empty(BlockDriverState *bs, Qcow2Cache *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
|
||||
uint64_t offset, void **table, bool read_from_disk)
|
||||
static int GRAPH_RDLOCK
|
||||
qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
|
||||
void **table, bool read_from_disk)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int i;
|
||||
|
@ -207,7 +207,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
* the cache is used; otherwise the L2 slice is loaded from the image
|
||||
* file.
|
||||
*/
|
||||
static int l2_load(BlockDriverState *bs, uint64_t offset,
|
||||
static int GRAPH_RDLOCK
|
||||
l2_load(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t l2_offset, uint64_t **l2_slice)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
@ -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;
|
||||
uint64_t old_l2_offset;
|
||||
@ -751,9 +752,9 @@ fail:
|
||||
*
|
||||
* Returns 0 on success, -errno in failure case
|
||||
*/
|
||||
static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t **new_l2_slice,
|
||||
int *new_l2_index)
|
||||
static int GRAPH_RDLOCK
|
||||
get_cluster_table(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t **new_l2_slice, int *new_l2_index)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
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.
|
||||
*/
|
||||
static int coroutine_fn calculate_l2_meta(BlockDriverState *bs,
|
||||
uint64_t host_cluster_offset,
|
||||
uint64_t guest_offset, unsigned bytes,
|
||||
uint64_t *l2_slice, QCowL2Meta **m,
|
||||
bool keep_old)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
calculate_l2_meta(BlockDriverState *bs, uint64_t host_cluster_offset,
|
||||
uint64_t guest_offset, unsigned bytes, uint64_t *l2_slice,
|
||||
QCowL2Meta **m, bool keep_old)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
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
|
||||
*/
|
||||
static int coroutine_fn handle_copied(BlockDriverState *bs,
|
||||
uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
|
||||
QCowL2Meta **m)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
handle_copied(BlockDriverState *bs, uint64_t guest_offset,
|
||||
uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int l2_index;
|
||||
@ -1600,10 +1600,9 @@ out:
|
||||
* function has been waiting for another request and the allocation must be
|
||||
* restarted, but the whole request should not be failed.
|
||||
*/
|
||||
static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
|
||||
uint64_t guest_offset,
|
||||
uint64_t *host_offset,
|
||||
uint64_t *nb_clusters)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
|
||||
uint64_t *host_offset, uint64_t *nb_clusters)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
|
||||
@ -1658,9 +1657,9 @@ static int coroutine_fn do_alloc_cluster_offset(BlockDriverState *bs,
|
||||
*
|
||||
* -errno: in error cases
|
||||
*/
|
||||
static int coroutine_fn handle_alloc(BlockDriverState *bs,
|
||||
uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
|
||||
QCowL2Meta **m)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
|
||||
uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int l2_index;
|
||||
@ -1898,8 +1897,8 @@ again:
|
||||
* all clusters in the same L2 slice) and returns the number of discarded
|
||||
* clusters.
|
||||
*/
|
||||
static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t nb_clusters,
|
||||
static int GRAPH_RDLOCK
|
||||
discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters,
|
||||
enum qcow2_discard_type type, bool full_discard)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
@ -2037,7 +2036,7 @@ fail:
|
||||
* all clusters in the same L2 slice) and returns the number of zeroed
|
||||
* clusters.
|
||||
*/
|
||||
static int coroutine_fn
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t nb_clusters, int flags)
|
||||
{
|
||||
@ -2093,7 +2092,7 @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
|
||||
return nb_clusters;
|
||||
}
|
||||
|
||||
static int coroutine_fn
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
|
||||
unsigned nb_subclusters)
|
||||
{
|
||||
@ -2231,7 +2230,8 @@ fail:
|
||||
* status_cb(). l1_entries contains the total number of L1 entries and
|
||||
* *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
|
||||
expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
int l1_size, int64_t *visited_l1_entries,
|
||||
int64_t l1_entries,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
|
@ -229,8 +229,8 @@ static void set_refcount_ro6(void *refcount_array, uint64_t index,
|
||||
}
|
||||
|
||||
|
||||
static int load_refcount_block(BlockDriverState *bs,
|
||||
int64_t refcount_block_offset,
|
||||
static int GRAPH_RDLOCK
|
||||
load_refcount_block(BlockDriverState *bs, int64_t refcount_block_offset,
|
||||
void **refcount_block)
|
||||
{
|
||||
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
|
||||
*/
|
||||
static int alloc_refcount_block(BlockDriverState *bs,
|
||||
int64_t cluster_index, void **refcount_block)
|
||||
static int GRAPH_RDLOCK
|
||||
alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index,
|
||||
void **refcount_block)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
unsigned int refcount_table_index;
|
||||
@ -806,12 +807,9 @@ found:
|
||||
/* XXX: cache several refcount block clusters ? */
|
||||
/* @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 */
|
||||
static int update_refcount(BlockDriverState *bs,
|
||||
int64_t offset,
|
||||
int64_t length,
|
||||
uint64_t addend,
|
||||
bool decrease,
|
||||
enum qcow2_discard_type type)
|
||||
static int GRAPH_RDLOCK
|
||||
update_refcount(BlockDriverState *bs, int64_t offset, int64_t length,
|
||||
uint64_t addend, bool decrease, enum qcow2_discard_type type)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int64_t start, last, cluster_offset;
|
||||
@ -967,8 +965,8 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
|
||||
|
||||
|
||||
/* return < 0 if error */
|
||||
static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
|
||||
uint64_t max)
|
||||
static int64_t GRAPH_RDLOCK
|
||||
alloc_clusters_noref(BlockDriverState *bs, uint64_t size, uint64_t max)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
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
|
||||
* 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,
|
||||
BdrvCheckMode fix, bool *rebuild,
|
||||
int64_t *highest_cluster,
|
||||
@ -3103,7 +3101,8 @@ 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.
|
||||
*/
|
||||
typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
|
||||
typedef int /* GRAPH_RDLOCK_PTR */
|
||||
(RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
|
||||
uint64_t reftable_index, uint64_t *reftable_size,
|
||||
void *refblock, bool refblock_empty,
|
||||
bool *allocated, Error **errp);
|
||||
@ -3113,7 +3112,8 @@ typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
|
||||
* it is not empty) and inserts its offset into the new reftable. The size of
|
||||
* this new reftable is increased as required.
|
||||
*/
|
||||
static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
static int GRAPH_RDLOCK
|
||||
alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
uint64_t reftable_index, uint64_t *reftable_size,
|
||||
void *refblock, bool refblock_empty, bool *allocated,
|
||||
Error **errp)
|
||||
@ -3166,7 +3166,8 @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
* offset specified by the new reftable's entry. It does not modify the new
|
||||
* reftable or change any refcounts.
|
||||
*/
|
||||
static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
static int GRAPH_RDLOCK
|
||||
flush_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
uint64_t reftable_index, uint64_t *reftable_size,
|
||||
void *refblock, bool refblock_empty, bool *allocated,
|
||||
Error **errp)
|
||||
@ -3210,7 +3211,8 @@ static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
*
|
||||
* @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
|
||||
walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
|
||||
uint64_t *new_reftable_index,
|
||||
uint64_t *new_reftable_size,
|
||||
void *new_refblock, int new_refblock_size,
|
||||
@ -3545,8 +3547,8 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs,
|
||||
uint64_t offset)
|
||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||
get_refblock_offset(BlockDriverState *bs, uint64_t offset)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
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;
|
||||
}
|
||||
|
||||
static int coroutine_fn
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
|
@ -536,7 +536,7 @@ int qcow2_mark_dirty(BlockDriverState *bs)
|
||||
* function when there are no pending requests, it does not guard against
|
||||
* 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;
|
||||
|
||||
@ -570,7 +570,8 @@ int qcow2_mark_corrupt(BlockDriverState *bs)
|
||||
* Marks the image as consistent, i.e., unsets the corrupt bit, and flushes
|
||||
* 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;
|
||||
|
||||
@ -980,10 +981,9 @@ typedef struct Qcow2ReopenState {
|
||||
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
|
||||
} Qcow2ReopenState;
|
||||
|
||||
static int qcow2_update_options_prepare(BlockDriverState *bs,
|
||||
Qcow2ReopenState *r,
|
||||
QDict *options, int flags,
|
||||
Error **errp)
|
||||
static int GRAPH_RDLOCK
|
||||
qcow2_update_options_prepare(BlockDriverState *bs, Qcow2ReopenState *r,
|
||||
QDict *options, int flags, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
QemuOpts *opts = NULL;
|
||||
@ -1260,7 +1260,7 @@ static void qcow2_update_options_abort(BlockDriverState *bs,
|
||||
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,
|
||||
Error **errp)
|
||||
{
|
||||
@ -1969,13 +1969,17 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
bs->bl.pdiscard_alignment = s->cluster_size;
|
||||
}
|
||||
|
||||
static int qcow2_reopen_prepare(BDRVReopenState *state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
static int GRAPH_UNLOCKED
|
||||
qcow2_reopen_prepare(BDRVReopenState *state,BlockReopenQueue *queue,
|
||||
Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = state->bs->opaque;
|
||||
Qcow2ReopenState *r;
|
||||
int ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
r = g_new0(Qcow2ReopenState, 1);
|
||||
state->opaque = r;
|
||||
|
||||
@ -2038,6 +2042,8 @@ static void qcow2_reopen_commit(BDRVReopenState *state)
|
||||
|
||||
static void qcow2_reopen_commit_post(BDRVReopenState *state)
|
||||
{
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
if (state->flags & BDRV_O_RDWR) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
@ -4079,8 +4085,8 @@ qcow2_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
|
||||
int64_t offset, int64_t bytes)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
qcow2_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
|
||||
{
|
||||
int ret;
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
@ -4825,7 +4831,7 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int make_completely_empty(BlockDriverState *bs)
|
||||
static int GRAPH_RDLOCK make_completely_empty(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
Error *local_err = NULL;
|
||||
@ -4976,7 +4982,7 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow2_make_empty(BlockDriverState *bs)
|
||||
static int GRAPH_RDLOCK qcow2_make_empty(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t offset, end_offset;
|
||||
@ -5020,7 +5026,7 @@ static int qcow2_make_empty(BlockDriverState *bs)
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
static int qcow2_has_compressed_clusters(BlockDriverState *bs)
|
||||
static int GRAPH_RDLOCK qcow2_has_compressed_clusters(BlockDriverState *bs)
|
||||
{
|
||||
int64_t offset = 0;
|
||||
int64_t bytes = bdrv_getlength(bs);
|
||||
@ -5405,7 +5411,8 @@ static int qcow2_has_compressed_clusters(BlockDriverState *bs)
|
||||
* Downgrades an image's version. To achieve this, any incompatible features
|
||||
* have to be removed.
|
||||
*/
|
||||
static int qcow2_downgrade(BlockDriverState *bs, int target_version,
|
||||
static int GRAPH_RDLOCK
|
||||
qcow2_downgrade(BlockDriverState *bs, int target_version,
|
||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
||||
Error **errp)
|
||||
{
|
||||
@ -5515,7 +5522,8 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
|
||||
* features of older versions, some things may have to be presented
|
||||
* differently.
|
||||
*/
|
||||
static int qcow2_upgrade(BlockDriverState *bs, int target_version,
|
||||
static int GRAPH_RDLOCK
|
||||
qcow2_upgrade(BlockDriverState *bs, int target_version,
|
||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
||||
Error **errp)
|
||||
{
|
||||
@ -5643,11 +5651,10 @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
|
||||
info->original_cb_opaque);
|
||||
}
|
||||
|
||||
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque,
|
||||
bool force,
|
||||
Error **errp)
|
||||
static int GRAPH_RDLOCK
|
||||
qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
||||
bool force, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
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;
|
||||
va_list ap;
|
||||
|
||||
assume_graph_lock(); /* FIXME */
|
||||
|
||||
fatal = fatal && bdrv_is_writable(bs);
|
||||
|
||||
if (s->signaled_corruption &&
|
||||
|
130
block/qcow2.h
130
block/qcow2.h
@ -838,7 +838,8 @@ int qcow2_mark_dirty(BlockDriverState *bs);
|
||||
int qcow2_mark_corrupt(BlockDriverState *bs);
|
||||
int qcow2_update_header(BlockDriverState *bs);
|
||||
|
||||
void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
|
||||
void GRAPH_RDLOCK
|
||||
qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
|
||||
int64_t size, const char *message_format, ...)
|
||||
G_GNUC_PRINTF(5, 6);
|
||||
|
||||
@ -851,33 +852,41 @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
|
||||
int coroutine_fn GRAPH_RDLOCK qcow2_refcount_init(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);
|
||||
|
||||
int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
|
||||
uint64_t addend, bool decrease,
|
||||
enum qcow2_discard_type type);
|
||||
|
||||
int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t offset,
|
||||
int64_t GRAPH_RDLOCK
|
||||
qcow2_refcount_area(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t additional_clusters, bool exact_size,
|
||||
int new_refblock_index,
|
||||
uint64_t new_refblock_offset);
|
||||
|
||||
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 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 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,
|
||||
enum qcow2_discard_type type);
|
||||
void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
|
||||
void GRAPH_RDLOCK
|
||||
qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
|
||||
enum qcow2_discard_type type);
|
||||
|
||||
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
int64_t l1_table_offset, int l1_size, int addend);
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_update_snapshot_refcount(BlockDriverState *bs, int64_t l1_table_offset,
|
||||
int l1_size, int addend);
|
||||
|
||||
int qcow2_flush_caches(BlockDriverState *bs);
|
||||
int qcow2_write_caches(BlockDriverState *bs);
|
||||
int GRAPH_RDLOCK qcow2_flush_caches(BlockDriverState *bs);
|
||||
int GRAPH_RDLOCK qcow2_write_caches(BlockDriverState *bs);
|
||||
int coroutine_fn qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
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,
|
||||
int64_t size);
|
||||
int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
|
||||
int GRAPH_RDLOCK
|
||||
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,
|
||||
void **refcount_table,
|
||||
int64_t *refcount_table_size,
|
||||
int64_t offset, int64_t size);
|
||||
|
||||
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque, Error **errp);
|
||||
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
|
||||
qcow2_detect_metadata_preallocation(BlockDriverState *bs);
|
||||
|
||||
/* qcow2-cluster.c functions */
|
||||
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
bool exact_size);
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size);
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
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,
|
||||
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
|
||||
|
||||
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
|
||||
unsigned int *bytes, uint64_t *host_offset,
|
||||
QCow2SubclusterType *subcluster_type);
|
||||
int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
|
||||
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
|
||||
qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t 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
|
||||
qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
|
||||
|
||||
void coroutine_fn qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
|
||||
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t bytes, enum qcow2_discard_type type,
|
||||
bool full_discard);
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
|
||||
|
||||
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
|
||||
qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
int flags);
|
||||
|
||||
int qcow2_expand_zero_clusters(BlockDriverState *bs,
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_expand_zero_clusters(BlockDriverState *bs,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque);
|
||||
|
||||
/* qcow2-snapshot.c functions */
|
||||
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
|
||||
int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id);
|
||||
int qcow2_snapshot_delete(BlockDriverState *bs,
|
||||
const char *snapshot_id,
|
||||
const char *name,
|
||||
Error **errp);
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
|
||||
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id);
|
||||
|
||||
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_load_tmp(BlockDriverState *bs,
|
||||
const char *snapshot_id,
|
||||
@ -956,14 +981,14 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
|
||||
void qcow2_free_snapshots(BlockDriverState *bs);
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
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
|
||||
qcow2_check_read_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
|
||||
BdrvCheckMode fix);
|
||||
|
||||
int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
|
||||
BdrvCheckResult *result,
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
qcow2_check_fix_snapshot_table(BlockDriverState *bs, BdrvCheckResult *result,
|
||||
BdrvCheckMode fix);
|
||||
|
||||
/* qcow2-cache.c functions */
|
||||
@ -972,19 +997,23 @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
|
||||
int qcow2_cache_destroy(Qcow2Cache *c);
|
||||
|
||||
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
|
||||
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
|
||||
int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
|
||||
int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
|
||||
int GRAPH_RDLOCK qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
|
||||
int GRAPH_RDLOCK qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
|
||||
int GRAPH_RDLOCK qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
|
||||
Qcow2Cache *dependency);
|
||||
void qcow2_cache_depends_on_flush(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 qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
|
||||
void **table);
|
||||
int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
|
||||
|
||||
int GRAPH_RDLOCK
|
||||
qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
|
||||
void **table);
|
||||
|
||||
void qcow2_cache_put(Qcow2Cache *c, void **table);
|
||||
void *qcow2_cache_is_table_offset(Qcow2Cache *c, uint64_t offset);
|
||||
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);
|
||||
bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
|
||||
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);
|
||||
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
|
||||
bool release_stored, Error **errp);
|
||||
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
|
||||
|
||||
bool GRAPH_RDLOCK
|
||||
qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, bool release_stored,
|
||||
Error **errp);
|
||||
|
||||
bool coroutine_fn GRAPH_RDLOCK
|
||||
qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
|
||||
uint32_t granularity, Error **errp);
|
||||
int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
|
||||
const char *name,
|
||||
|
||||
int coroutine_fn GRAPH_RDLOCK
|
||||
qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
|
||||
Error **errp);
|
||||
|
||||
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
|
||||
uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
|
||||
uint32_t cluster_size);
|
||||
|
@ -307,13 +307,16 @@ out:
|
||||
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;
|
||||
BdrvChild *active_disk = bs->file;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
if (!s->backup_job) {
|
||||
error_setg(errp, "Backup job was cancelled unexpectedly");
|
||||
return;
|
||||
@ -531,13 +534,16 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
/* Must be true, or the bdrv_getlength() calls would have failed */
|
||||
assert(active_disk->bs->drv && hidden_disk->bs->drv);
|
||||
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
if (!active_disk->bs->drv->bdrv_make_empty ||
|
||||
!hidden_disk->bs->drv->bdrv_make_empty) {
|
||||
error_setg(errp,
|
||||
"Active disk or hidden disk doesn't support make_empty");
|
||||
aio_context_release(aio_context);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
return;
|
||||
}
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
/* reopen the backing file in r/w mode */
|
||||
reopen_backing_file(bs, true, &local_err);
|
||||
|
@ -138,7 +138,7 @@ void GRAPH_RDLOCK
|
||||
bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
|
||||
|
||||
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,
|
||||
const char *backing_fmt, bool warn);
|
||||
void bdrv_register(BlockDriver *bdrv);
|
||||
|
@ -264,7 +264,7 @@ struct BlockDriver {
|
||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user