return 0;
open_failed:
bs->drv = NULL;
+
+ bdrv_graph_wrlock(NULL);
if (bs->file != NULL) {
- bdrv_graph_wrlock(NULL);
bdrv_unref_child(bs, bs->file);
- bdrv_graph_wrunlock();
assert(!bs->file);
}
+ bdrv_graph_wrunlock();
+
g_free(bs->opaque);
bs->opaque = NULL;
return ret;
Error *local_err = NULL;
bool ro;
+ GLOBAL_STATE_CODE();
+
+ bdrv_graph_rdlock_main_loop();
assert(bs->file == NULL);
assert(options != NULL && bs->options != options);
- GLOBAL_STATE_CODE();
+ bdrv_graph_rdunlock_main_loop();
opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
static int blkreplay_snapshot_goto(BlockDriverState *bs,
const char *snapshot_id)
{
- return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL);
+ BlockDriverState *file_bs;
+
+ bdrv_graph_rdlock_main_loop();
+ file_bs = bs->file->bs;
+ bdrv_graph_rdunlock_main_loop();
+
+ return bdrv_snapshot_goto(file_bs, snapshot_id, NULL);
}
static BlockDriver bdrv_blkreplay = {
* It's guaranteed that guest writes will not interact in the region until
* cbw_snapshot_read_unlock() called.
*/
-static coroutine_fn BlockReq *
+static BlockReq * coroutine_fn GRAPH_RDLOCK
cbw_snapshot_read_lock(BlockDriverState *bs, int64_t offset, int64_t bytes,
int64_t *pnum, BdrvChild **file)
{
BlockDriverState *bs = opaque;
ssize_t ret;
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
ret = bdrv_pread(bs->file, offset, buflen, buf, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read encryption header");
BlockDriverState *bs = opaque;
ssize_t ret;
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
ret = bdrv_pwrite(bs->file, offset, buflen, buf, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not write encryption header");
return 0;
}
-static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
+static int GRAPH_RDLOCK
+read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
{
uint64_t buffer;
int ret;
return 0;
}
-static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
+static int GRAPH_RDLOCK
+read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
{
uint32_t buffer;
int ret;
return ret;
}
-static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
- uint64_t info_begin, uint64_t info_length)
+static int GRAPH_RDLOCK
+dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
+ uint64_t info_begin, uint64_t info_length)
{
BDRVDMGState *s = bs->opaque;
int ret;
return ret;
}
-static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
- uint64_t info_begin, uint64_t info_length)
+static int GRAPH_RDLOCK
+dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
+ uint64_t info_begin, uint64_t info_length)
{
BDRVDMGState *s = bs->opaque;
int ret;
} QEMU_PACKED ParallelsDirtyBitmapFeature;
/* Given L1 table read bitmap data from the image and populate @bitmap */
-static int parallels_load_bitmap_data(BlockDriverState *bs,
- const uint64_t *l1_table,
- uint32_t l1_size,
- BdrvDirtyBitmap *bitmap,
- Error **errp)
+static int GRAPH_RDLOCK
+parallels_load_bitmap_data(BlockDriverState *bs, const uint64_t *l1_table,
+ uint32_t l1_size, BdrvDirtyBitmap *bitmap,
+ Error **errp)
{
BDRVParallelsState *s = bs->opaque;
int ret = 0;
* @data buffer (of @data_size size) is the Dirty bitmaps feature which
* consists of ParallelsDirtyBitmapFeature followed by L1 table.
*/
-static BdrvDirtyBitmap *parallels_load_bitmap(BlockDriverState *bs,
- uint8_t *data,
- size_t data_size,
- Error **errp)
+static BdrvDirtyBitmap * GRAPH_RDLOCK
+parallels_load_bitmap(BlockDriverState *bs, uint8_t *data, size_t data_size,
+ Error **errp)
{
int ret;
ParallelsDirtyBitmapFeature bf;
return bitmap;
}
-static int parallels_parse_format_extension(BlockDriverState *bs,
- uint8_t *ext_cluster, Error **errp)
+static int GRAPH_RDLOCK
+parallels_parse_format_extension(BlockDriverState *bs, uint8_t *ext_cluster,
+ Error **errp)
{
BDRVParallelsState *s = bs->opaque;
int ret;
* bitmap anyway, as much as we can. This information will be used for
* error resolution.
*/
-static int parallels_fill_used_bitmap(BlockDriverState *bs)
+static int GRAPH_RDLOCK parallels_fill_used_bitmap(BlockDriverState *bs)
{
BDRVParallelsState *s = bs->opaque;
int64_t payload_bytes;
return 0;
}
-static int parallels_update_header(BlockDriverState *bs)
+static int GRAPH_RDLOCK parallels_update_header(BlockDriverState *bs)
{
BDRVParallelsState *s = bs->opaque;
unsigned size = MAX(bdrv_opt_mem_align(bs->file->bs),
{
BDRVParallelsState *s = bs->opaque;
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
if ((bs->open_flags & BDRV_O_RDWR) && !(bs->open_flags & BDRV_O_INACTIVE)) {
s->header->inuse = 0;
parallels_update_header(bs);
Error *migration_blocker;
} BDRVParallelsState;
-int parallels_read_format_extension(BlockDriverState *bs,
- int64_t ext_off, Error **errp);
+int GRAPH_RDLOCK
+parallels_read_format_extension(BlockDriverState *bs, int64_t ext_off,
+ Error **errp);
#endif
return 0;
}
-static int preallocate_truncate_to_real_size(BlockDriverState *bs, Error **errp)
+static int GRAPH_RDLOCK
+preallocate_truncate_to_real_size(BlockDriverState *bs, Error **errp)
{
BDRVPreallocateState *s = bs->opaque;
int ret;
{
BDRVPreallocateState *s = bs->opaque;
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
qemu_bh_cancel(s->drop_resize_bh);
qemu_bh_delete(s->drop_resize_bh);
PreallocateOpts *opts = g_new0(PreallocateOpts, 1);
int ret;
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
if (!preallocate_absorb_opts(opts, reopen_state->options,
reopen_state->bs->file->bs, errp)) {
g_free(opts);
return (perm & BLK_PERM_WRITE) && (perm & BLK_PERM_RESIZE);
}
-static bool has_prealloc_perms(BlockDriverState *bs)
+static bool GRAPH_RDLOCK has_prealloc_perms(BlockDriverState *bs)
{
BDRVPreallocateState *s = bs->opaque;
return ret;
}
-static int preallocate_drop_resize(BlockDriverState *bs, Error **errp)
+static int GRAPH_RDLOCK
+preallocate_drop_resize(BlockDriverState *bs, Error **errp)
{
BDRVPreallocateState *s = bs->opaque;
int ret;
*/
s->data_end = s->file_end = s->zero_start = -EINVAL;
- bdrv_graph_rdlock_main_loop();
bdrv_child_refresh_perms(bs, bs->file, NULL);
- bdrv_graph_rdunlock_main_loop();
return 0;
}
static void preallocate_drop_resize_bh(void *opaque)
{
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
/*
* In case of errors, we'll simply keep the exclusive lock on the image
* indefinitely.
return 0;
}
-static void bdrv_qed_close(BlockDriverState *bs)
+static void GRAPH_RDLOCK bdrv_qed_do_close(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
qemu_vfree(s->l1_table);
}
+static void GRAPH_UNLOCKED bdrv_qed_close(BlockDriverState *bs)
+{
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
+ bdrv_qed_do_close(bs);
+}
+
static int coroutine_fn GRAPH_UNLOCKED
bdrv_qed_co_create(BlockdevCreateOptions *opts, Error **errp)
{
BDRVQEDState *s = bs->opaque;
int ret;
- bdrv_qed_close(bs);
+ bdrv_qed_do_close(bs);
bdrv_qed_init_state(bs);
qemu_co_mutex_lock(&s->table_lock);
/**
* Header functions
*/
-int qed_write_header_sync(BDRVQEDState *s);
+int GRAPH_RDLOCK qed_write_header_sync(BDRVQEDState *s);
/**
* L2 cache functions
return ret;
}
-static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
- uint64_t offset, bool has_size, uint64_t size,
- Error **errp)
+static int GRAPH_RDLOCK
+raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset,
+ bool has_size, uint64_t size, Error **errp)
{
int64_t real_size = 0;
uint64_t offset, size;
int ret;
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
assert(reopen_state != NULL);
assert(reopen_state->bs != NULL);
secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
{
BDRVReplicationState *s = bs->opaque;
- BdrvChild *active_disk = bs->file;
+ BdrvChild *active_disk;
Error *local_err = NULL;
int ret;
return;
}
+ active_disk = bs->file;
if (!active_disk->bs->drv) {
error_setg(errp, "Active disk %s is ejected",
active_disk->bs->node_name);
return;
}
+ bdrv_graph_rdlock_main_loop();
s->stage = BLOCK_REPLICATION_FAILOVER;
s->commit_job = commit_active_start(
NULL, bs->file->bs, s->secondary_disk->bs,
JOB_INTERNAL, 0, BLOCKDEV_ON_ERROR_REPORT,
NULL, replication_done, bs, true, errp);
+ bdrv_graph_rdunlock_main_loop();
break;
default:
aio_context_release(aio_context);
}
/* Return -ve errno, or 0 on success and write CID into *pcid. */
-static int vmdk_read_cid(BlockDriverState *bs, int parent, uint32_t *pcid)
+static int GRAPH_RDLOCK
+vmdk_read_cid(BlockDriverState *bs, int parent, uint32_t *pcid)
{
char *desc;
uint32_t cid;
BDRVVmdkReopenState *rs;
int i;
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
assert(state != NULL);
assert(state->bs != NULL);
assert(state->opaque == NULL);
BDRVVmdkReopenState *rs = state->opaque;
int i;
+ GLOBAL_STATE_CODE();
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
+
for (i = 0; i < s->num_extents; i++) {
if (rs->extents_using_bs_file[i]) {
s->extents[i].file = state->bs->file;
vmdk_reopen_clean(state);
}
-static int vmdk_parent_open(BlockDriverState *bs)
+static int GRAPH_RDLOCK vmdk_parent_open(BlockDriverState *bs)
{
char *p_name;
char *desc;
ret = -EINVAL;
goto exit;
}
+
+ bdrv_graph_co_rdlock();
ret = vmdk_read_cid(blk_bs(backing), 0, &parent_cid);
+ bdrv_graph_co_rdunlock();
blk_co_unref(backing);
if (ret) {
error_setg(errp, "Failed to read parent CID");
*/
QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) children;
BdrvChild * GRAPH_RDLOCK_PTR backing;
- BdrvChild *file;
+ BdrvChild * GRAPH_RDLOCK_PTR file;
QLIST_HEAD(, BdrvChild GRAPH_RDLOCK_PTR) parents;