return -error;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
bs->bl.request_alignment = s->sectorsize;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
blk_log_writes_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return fr.file_ret;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
{
return bdrv_co_pwritev(fr->bs->file, fr->offset, fr->bytes,
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
- assume_graph_lock(); /* FIXME */
return blk_log_writes_co_log(bs, offset, bytes, qiov, flags,
blk_log_writes_co_do_file_pwritev, 0, false);
}
replay_block_event(req->bh, reqid);
}
-static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
uint64_t reqid = blkreplay_next_id();
int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
return ret;
}
-static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
uint64_t reqid = blkreplay_next_id();
int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
IO_CODE();
blk_wait_while_drained(blk);
+ GRAPH_RDLOCK_GUARD();
/* Call blk_bs() only after waiting, the graph may have changed */
bs = blk_bs(blk);
IO_CODE();
blk_wait_while_drained(blk);
+ GRAPH_RDLOCK_GUARD();
/* Call blk_bs() only after waiting, the graph may have changed */
bs = blk_bs(blk);
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
bochs_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
},
};
-static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_commit_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
}
int snapshot_error;
} BDRVCopyBeforeWriteState;
-static coroutine_fn int cbw_co_preadv(
- BlockDriverState *bs, int64_t offset, int64_t bytes,
- QEMUIOVector *qiov, BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+cbw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
}
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
}
-static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static coroutine_fn GRAPH_RDLOCK
+int cbw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
if (ret < 0) {
BdrvChild *file;
int ret;
+ assume_graph_lock(); /* FIXME */
+
/* TODO: upgrade to async loop using AioTask */
while (bytes) {
int64_t cur_bytes;
}
-static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
- int64_t offset, int64_t bytes,
- QEMUIOVector *qiov,
- size_t qiov_offset,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset,
+ BdrvRequestFlags flags)
{
int64_t n;
int local_flags;
}
-static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- QEMUIOVector *qiov,
- size_t qiov_offset,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+cor_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset,
+ BdrvRequestFlags flags)
{
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
flags);
}
-static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov)
{
return bdrv_co_pwritev(bs->file, offset, bytes, qiov,
BDRV_REQ_WRITE_COMPRESSED);
*/
#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
-static coroutine_fn int
+static int coroutine_fn GRAPH_RDLOCK
block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
}
-static coroutine_fn int
+static int coroutine_fn GRAPH_RDLOCK
block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
}
-static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
- int64_t offset, int64_t bytes,
- QEMUIOVector *qiov,
- size_t qiov_offset,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+compress_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset,
+ BdrvRequestFlags flags)
{
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
flags);
}
-static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- QEMUIOVector *qiov,
- size_t qiov_offset,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+compress_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset,
+ BdrvRequestFlags flags)
{
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
flags | BDRV_REQ_WRITE_COMPRESSED);
unsigned int nb_sectors;
QEMUIOVector local_qiov;
int ret;
+ assert_bdrv_graph_readable();
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
assert(!(flags & ~bs->supported_read_flags));
unsigned int nb_sectors;
QEMUIOVector local_qiov;
int ret;
+ assert_bdrv_graph_readable();
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
BlockDriver *drv = bs->drv;
QEMUIOVector local_qiov;
int ret;
+ assert_bdrv_graph_readable();
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
int ret;
IO_CODE();
- assume_graph_lock(); /* FIXME */
-
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
if (!bdrv_co_is_inserted(bs)) {
bool padded = false;
IO_CODE();
- assume_graph_lock(); /* FIXME */
-
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
if (!bdrv_co_is_inserted(bs)) {
op->is_in_flight = true;
trace_mirror_one_iteration(s, op->offset, op->bytes);
- ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
- &op->qiov, 0);
+ WITH_GRAPH_RDLOCK_GUARD() {
+ ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes,
+ &op->qiov, 0);
+ }
mirror_read_complete(op, ret);
}
g_free(op);
}
-static int coroutine_fn bdrv_mirror_top_preadv(BlockDriverState *bs,
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_mirror_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
}
return ret;
}
-static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
- int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_mirror_top_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
MirrorBDSOpaque *s = bs->opaque;
QEMUIOVector bounce_qiov;
int ret = 0;
bool copy_to_target = false;
- assume_graph_lock(); /* FIXME */
-
if (s->job) {
copy_to_target = s->job->ret >= 0 &&
!job_is_cancelled(&s->job->common.job) &&
}
-static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
+static int coroutine_fn GRAPH_RDLOCK
+parallels_co_flush_to_os(BlockDriverState *bs)
{
BDRVParallelsState *s = bs->opaque;
unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block);
return ret;
}
-static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+parallels_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
+ QEMUIOVector *qiov)
{
BDRVParallelsState *s = bs->opaque;
uint64_t bytes_done = 0;
state->opaque = NULL;
}
-static coroutine_fn int preallocate_co_preadv_part(
- BlockDriverState *bs, int64_t offset, int64_t bytes,
- QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+preallocate_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset,
+ BdrvRequestFlags flags)
{
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
flags);
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
}
-static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- QEMUIOVector *qiov,
- size_t qiov_offset,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+preallocate_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset,
+ BdrvRequestFlags flags)
{
- assume_graph_lock(); /* FIXME */
handle_write(bs, offset, bytes, false);
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
static QemuOptsList qcow_create_opts;
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
- uint64_t cluster_offset);
+static int coroutine_fn GRAPH_RDLOCK
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
return 0;
}
-static int coroutine_fn decompress_cluster(BlockDriverState *bs,
- uint64_t cluster_offset)
+static int coroutine_fn GRAPH_RDLOCK
+decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
{
BDRVQcowState *s = bs->opaque;
int ret, csize;
return 0;
}
-static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
- uint64_t cluster_offset,
- unsigned offset_in_cluster,
- QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset,
+ unsigned offset_in_cluster, QEMUIOVector *qiov)
{
BDRVQcow2State *s = bs->opaque;
int ret;
}
}
-static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
- BdrvCheckResult *result,
- BdrvCheckMode fix)
+static int coroutine_fn GRAPH_RDLOCK
+qcow2_co_check_locked(BlockDriverState *bs, BdrvCheckResult *result,
+ BdrvCheckMode fix)
{
BdrvCheckResult snapshot_res = {};
BdrvCheckResult refcount_res = {};
return ret;
}
-static int coroutine_fn qcow2_co_check(BlockDriverState *bs,
- BdrvCheckResult *result,
- BdrvCheckMode fix)
+static int coroutine_fn GRAPH_RDLOCK
+qcow2_co_check(BlockDriverState *bs, BdrvCheckResult *result,
+ BdrvCheckMode fix)
{
BDRVQcow2State *s = bs->opaque;
int ret;
}
/* Called with s->lock held. */
-static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
- int flags, bool open_data_file,
- Error **errp)
+static int coroutine_fn GRAPH_RDLOCK
+qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
+ bool open_data_file, Error **errp)
{
ERRP_GUARD();
BDRVQcow2State *s = bs->opaque;
QCow2OpenCo *qoc = opaque;
BDRVQcow2State *s = qoc->bs->opaque;
+ assume_graph_lock(); /* FIXME */
+
qemu_co_mutex_lock(&s->lock);
qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
qoc->errp);
return ret;
}
-static coroutine_fn int
+static int coroutine_fn GRAPH_RDLOCK
qcow2_co_preadv_encrypted(BlockDriverState *bs,
uint64_t host_offset,
uint64_t offset,
return 0;
}
-static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
- QCow2SubclusterType subc_type,
- uint64_t host_offset,
- uint64_t offset, uint64_t bytes,
- QEMUIOVector *qiov,
- size_t qiov_offset)
+static int coroutine_fn GRAPH_RDLOCK
+qcow2_co_preadv_task(BlockDriverState *bs, QCow2SubclusterType subc_type,
+ uint64_t host_offset, uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset)
{
BDRVQcow2State *s = bs->opaque;
g_assert_not_reached();
}
-static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
+/*
+ * This function can count as GRAPH_RDLOCK because qcow2_co_preadv_part() holds
+ * the graph lock and keeps it until this coroutine has terminated.
+ */
+static int coroutine_fn GRAPH_RDLOCK qcow2_co_preadv_task_entry(AioTask *task)
{
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
t->qiov, t->qiov_offset);
}
-static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
- int64_t offset, int64_t bytes,
- QEMUIOVector *qiov,
- size_t qiov_offset,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+qcow2_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset,
+ BdrvRequestFlags flags)
{
BDRVQcow2State *s = bs->opaque;
int ret = 0;
qcow2_do_close(bs, true);
}
-static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
- Error **errp)
+static void coroutine_fn GRAPH_RDLOCK
+qcow2_co_invalidate_cache(BlockDriverState *bs, Error **errp)
{
ERRP_GUARD();
BDRVQcow2State *s = bs->opaque;
return ret;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
qcow2_co_preadv_compressed(BlockDriverState *bs,
uint64_t l2_entry,
uint64_t offset,
Error **errp);
/* qcow2-refcount.c functions */
-int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
+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 qcow2_read_snapshots(BlockDriverState *bs, Error **errp);
int qcow2_write_snapshots(BlockDriverState *bs);
-int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
- BdrvCheckResult *result,
- BdrvCheckMode fix);
+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,
BdrvCheckMode fix);
#include "qemu/memalign.h"
/* Called with table_lock held. */
-static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset,
- QEDTable *table)
+static int coroutine_fn GRAPH_RDLOCK
+qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
{
unsigned int bytes = s->header.cluster_size * s->header.table_size;
*
* No new allocating reqs can start while this function runs.
*/
-static int coroutine_fn qed_write_header(BDRVQEDState *s)
+static int coroutine_fn GRAPH_RDLOCK qed_write_header(BDRVQEDState *s)
{
/* We must write full sectors for O_DIRECT but cannot necessarily generate
* the data following the header if an unrecognized compat feature is
return ret;
}
-static int coroutine_fn bdrv_qed_co_block_status(BlockDriverState *bs,
- bool want_zero,
- int64_t pos, int64_t bytes,
- int64_t *pnum, int64_t *map,
- BlockDriverState **file)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_block_status(BlockDriverState *bs, bool want_zero, int64_t pos,
+ int64_t bytes, int64_t *pnum, int64_t *map,
+ BlockDriverState **file)
{
BDRVQEDState *s = bs->opaque;
size_t len = MIN(bytes, SIZE_MAX);
* This function reads qiov->size bytes starting at pos from the backing file.
* If there is no backing file then zeroes are read.
*/
-static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
- QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+qed_read_backing_file(BDRVQEDState *s, uint64_t pos, QEMUIOVector *qiov)
{
if (s->bs->backing) {
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
* @len: Number of bytes
* @offset: Byte offset in image file
*/
-static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s,
- uint64_t pos, uint64_t len,
- uint64_t offset)
+static int coroutine_fn GRAPH_RDLOCK
+qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, uint64_t len,
+ uint64_t offset)
{
QEMUIOVector qiov;
int ret;
*
* Called with table_lock *not* held.
*/
-static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_main(QEDAIOCB *acb)
{
BDRVQEDState *s = acb_to_s(acb);
uint64_t offset = acb->cur_cluster +
*
* Called with table_lock held.
*/
-static int coroutine_fn qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset,
- size_t len)
+static int coroutine_fn GRAPH_RDLOCK
+qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, size_t len)
{
BDRVQEDState *s = acb_to_s(acb);
int r;
*
* Called with table_lock held.
*/
-static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
- uint64_t offset, size_t len)
+static int coroutine_fn GRAPH_RDLOCK
+qed_aio_read_data(void *opaque, int ret, uint64_t offset, size_t len)
{
QEDAIOCB *acb = opaque;
BDRVQEDState *s = acb_to_s(acb);
/**
* Table I/O functions
*/
-int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s);
+int coroutine_fn GRAPH_RDLOCK qed_read_l1_table_sync(BDRVQEDState *s);
int coroutine_fn GRAPH_RDLOCK
qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n);
int coroutine_fn GRAPH_RDLOCK
qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n);
-int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
- uint64_t offset);
-int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
- uint64_t offset);
+int coroutine_fn GRAPH_RDLOCK
+qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
+
+int coroutine_fn GRAPH_RDLOCK
+qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset);
int coroutine_fn GRAPH_RDLOCK
qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, unsigned int index,
/**
* Cluster functions
*/
-int coroutine_fn qed_find_cluster(BDRVQEDState *s, QEDRequest *request,
- uint64_t pos, size_t *len,
- uint64_t *img_offset);
+int coroutine_fn GRAPH_RDLOCK
+qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
+ size_t *len, uint64_t *img_offset);
/**
* Consistency check
int coroutine_fn GRAPH_RDLOCK
qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix);
-
QEDTable *qed_alloc_table(BDRVQEDState *s);
/**
}
}
-static void coroutine_fn quorum_rewrite_entry(void *opaque)
+/*
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
+ * the graph lock and keeps it until this coroutine has terminated.
+ */
+static void coroutine_fn GRAPH_RDLOCK quorum_rewrite_entry(void *opaque)
{
QuorumCo *co = opaque;
QuorumAIOCB *acb = co->acb;
}
}
-static bool quorum_rewrite_bad_versions(QuorumAIOCB *acb,
- QuorumVoteValue *value)
+static bool coroutine_fn GRAPH_RDLOCK
+quorum_rewrite_bad_versions(QuorumAIOCB *acb, QuorumVoteValue *value)
{
QuorumVoteVersion *version;
QuorumVoteItem *item;
return ret;
}
-static void quorum_vote(QuorumAIOCB *acb)
+static void coroutine_fn GRAPH_RDLOCK quorum_vote(QuorumAIOCB *acb)
{
bool quorum = true;
int i, j, ret;
quorum_free_vote_list(&acb->votes);
}
-static void coroutine_fn read_quorum_children_entry(void *opaque)
+/*
+ * This function can count as GRAPH_RDLOCK because read_quorum_children() holds
+ * the graph lock and keeps it until this coroutine has terminated.
+ */
+static void coroutine_fn GRAPH_RDLOCK read_quorum_children_entry(void *opaque)
{
QuorumCo *co = opaque;
QuorumAIOCB *acb = co->acb;
}
}
-static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
+static int coroutine_fn GRAPH_RDLOCK read_quorum_children(QuorumAIOCB *acb)
{
BDRVQuorumState *s = acb->bs->opaque;
int i;
return acb->vote_ret;
}
-static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
+static int coroutine_fn GRAPH_RDLOCK read_fifo_child(QuorumAIOCB *acb)
{
BDRVQuorumState *s = acb->bs->opaque;
int n, ret;
return ret;
}
-static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
- int64_t offset, int64_t bytes,
- QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
BDRVQuorumState *s = bs->opaque;
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
return 0;
}
-static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
- int64_t bytes, QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
int ret;
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
}
-static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
- int64_t bytes, QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
void *buf = NULL;
BlockDriver *drv;
return ret;
}
-static coroutine_fn int replication_co_readv(BlockDriverState *bs,
- int64_t sector_num,
- int remaining_sectors,
- QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+replication_co_readv(BlockDriverState *bs, int64_t sector_num,
+ int remaining_sectors, QEMUIOVector *qiov)
{
BDRVReplicationState *s = bs->opaque;
int ret;
return replication_return_value(s, ret);
}
-static coroutine_fn int replication_co_writev(BlockDriverState *bs,
- int64_t sector_num,
- int remaining_sectors,
- QEMUIOVector *qiov,
- int flags)
+static int coroutine_fn GRAPH_RDLOCK
+replication_co_writev(BlockDriverState *bs, int64_t sector_num,
+ int remaining_sectors, QEMUIOVector *qiov, int flags)
{
BDRVReplicationState *s = bs->opaque;
QEMUIOVector hd_qiov;
return bdrv_co_getlength(bs->file->bs);
}
-static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
- int64_t offset, int64_t bytes,
- QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+throttle_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
ThrottleGroupMember *tgm = bs->opaque;
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
}
-static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
- int64_t offset, int64_t bytes,
- QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+throttle_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
ThrottleGroupMember *tgm = bs->opaque;
throttle_group_co_io_limits_intercept(tgm, bytes, true);
return bdrv_co_pdiscard(bs->file, offset, bytes);
}
-static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+throttle_co_pwritev_compressed(BlockDriverState *bs, int64_t offset,
+ int64_t bytes, QEMUIOVector *qiov)
{
return throttle_co_pwritev(bs, offset, bytes, qiov,
BDRV_REQ_WRITE_COMPRESSED);
(s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vdi_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return ret;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
}
-static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
- int nb_sectors, QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+vhdx_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
+ QEMUIOVector *qiov)
{
BDRVVHDXState *s = bs->opaque;
int ret = 0;
return ret;
}
-static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
- int nb_sectors, QEMUIOVector *qiov,
- int flags)
+static int coroutine_fn GRAPH_RDLOCK
+vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
+ QEMUIOVector *qiov, int flags)
{
int ret = -ENOTSUP;
BDRVVHDXState *s = bs->opaque;
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
* it for call to write user data in the request.
*/
-static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
- VmdkExtent *extent,
- uint64_t cluster_offset,
- uint64_t offset,
- uint64_t skip_start_bytes,
- uint64_t skip_end_bytes,
- bool zeroed)
+static int coroutine_fn GRAPH_RDLOCK
+get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent,
+ uint64_t cluster_offset, uint64_t offset,
+ uint64_t skip_start_bytes, uint64_t skip_end_bytes,
+ bool zeroed)
{
int ret = VMDK_OK;
int64_t cluster_bytes;
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
* VMDK_ERROR if failed.
*/
-static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
- VmdkExtent *extent,
- VmdkMetaData *m_data,
- uint64_t offset,
- bool allocate,
- uint64_t *cluster_offset,
- uint64_t skip_start_bytes,
- uint64_t skip_end_bytes)
+static int coroutine_fn GRAPH_RDLOCK
+get_cluster_offset(BlockDriverState *bs, VmdkExtent *extent,
+ VmdkMetaData *m_data, uint64_t offset, bool allocate,
+ uint64_t *cluster_offset, uint64_t skip_start_bytes,
+ uint64_t skip_end_bytes)
{
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
return extent_relative_offset % cluster_size;
}
-static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
- bool want_zero,
- int64_t offset, int64_t bytes,
- int64_t *pnum, int64_t *map,
- BlockDriverState **file)
+static int coroutine_fn GRAPH_RDLOCK
+vmdk_co_block_status(BlockDriverState *bs, bool want_zero,
+ int64_t offset, int64_t bytes, int64_t *pnum,
+ int64_t *map, BlockDriverState **file)
{
BDRVVmdkState *s = bs->opaque;
int64_t index_in_cluster, n, ret;
return ret;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
int64_t offset_in_cluster, QEMUIOVector *qiov,
uint64_t qiov_offset, uint64_t n_bytes,
return ret;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
- int64_t offset_in_cluster, QEMUIOVector *qiov,
- int bytes)
+ int64_t offset_in_cluster, QEMUIOVector *qiov, int bytes)
{
int ret;
int cluster_bytes, buf_bytes;
return ret;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vmdk_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
*
* Returns: error code with 0 for success.
*/
-static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
- uint64_t bytes, QEMUIOVector *qiov,
- bool zeroed, bool zero_dry_run)
+static int coroutine_fn GRAPH_RDLOCK
+vmdk_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, bool zeroed, bool zero_dry_run)
{
BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent = NULL;
uint64_t bytes_done = 0;
VmdkMetaData m_data;
- assume_graph_lock(); /* FIXME */
-
if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) {
error_report("Wrong offset: offset=0x%" PRIx64
" total_sectors=0x%" PRIx64,
return 0;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vmdk_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
}
-static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+vmdk_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ BdrvRequestFlags flags)
{
int ret;
BDRVVmdkState *s = bs->opaque;
return info;
}
-static int coroutine_fn vmdk_co_check(BlockDriverState *bs,
- BdrvCheckResult *result,
- BdrvCheckMode fix)
+static int coroutine_fn GRAPH_RDLOCK
+vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix)
{
BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent = NULL;
return 0;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vpc_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
return ret;
}
-static int coroutine_fn
+static int coroutine_fn GRAPH_RDLOCK
vpc_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
int64_t offset, int64_t bytes);
-int coroutine_fn bdrv_co_preadv(BdrvChild *child,
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv(BdrvChild *child,
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
BdrvRequestFlags flags);
-int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
+int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_part(BdrvChild *child,
int64_t offset, int64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
-int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev(BdrvChild *child,
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
BdrvRequestFlags flags);
-int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
+int coroutine_fn GRAPH_RDLOCK bdrv_co_pwritev_part(BdrvChild *child,
int64_t offset, int64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
-static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pread(BdrvChild *child,
int64_t offset, int64_t bytes, void *buf, BdrvRequestFlags flags)
{
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
IO_CODE();
+ assert_bdrv_graph_readable();
return bdrv_co_preadv(child, offset, bytes, &qiov, flags);
}
-static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child,
+static inline int coroutine_fn GRAPH_RDLOCK bdrv_co_pwrite(BdrvChild *child,
int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags)
{
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
IO_CODE();
+ assert_bdrv_graph_readable();
return bdrv_co_pwritev(child, offset, bytes, &qiov, flags);
}
}
}
-static int coroutine_fn bdrv_test_top_co_preadv(BlockDriverState *bs,
- int64_t offset, int64_t bytes,
- QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_test_top_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
BDRVTestTopState *tts = bs->opaque;
return bdrv_co_preadv(tts->wait_child, offset, bytes, qiov, flags);
void *buffer = g_malloc(65536);
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536);
+ GRAPH_RDLOCK_GUARD();
+
/* Pretend some internal write operation from parent to child.
* Important: We have to read from the child, not from the parent!
* Draining works by first propagating it all up the tree to the
* Otherwise:
* Set .has_read to true and return success.
*/
-static int coroutine_fn bdrv_replace_test_co_preadv(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- QEMUIOVector *qiov,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_replace_test_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
{
BDRVReplaceTestState *s = bs->opaque;
int ret;
/* Queue a read request post-drain */
+ bdrv_graph_co_rdlock();
ret = bdrv_replace_test_co_preadv(bs, 0, 1, &qiov, 0);
+ bdrv_graph_co_rdunlock();
+
g_assert(ret >= 0);
bdrv_dec_in_flight(bs);
}