aboutsummaryrefslogtreecommitdiff
path: root/block/qed.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/qed.c')
-rw-r--r--block/qed.c328
1 files changed, 180 insertions, 148 deletions
diff --git a/block/qed.c b/block/qed.c
index f45c640513..fa5bc11085 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -20,6 +20,7 @@
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/option.h"
+#include "qemu/memalign.h"
#include "trace.h"
#include "qed.h"
#include "sysemu/block-backend.h"
@@ -86,14 +87,9 @@ static void qed_header_cpu_to_le(const QEDHeader *cpu, QEDHeader *le)
int qed_write_header_sync(BDRVQEDState *s)
{
QEDHeader le;
- int ret;
qed_header_cpu_to_le(&s->header, &le);
- ret = bdrv_pwrite(s->bs->file, 0, &le, sizeof(le));
- if (ret != sizeof(le)) {
- return ret;
- }
- return 0;
+ return bdrv_pwrite(s->bs->file, 0, sizeof(le), &le, 0);
}
/**
@@ -104,7 +100,7 @@ int qed_write_header_sync(BDRVQEDState *s)
*
* 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
@@ -199,14 +195,15 @@ static bool qed_is_image_size_valid(uint64_t image_size, uint32_t cluster_size,
*
* The string is NUL-terminated.
*/
-static int qed_read_string(BdrvChild *file, uint64_t offset, size_t n,
- char *buf, size_t buflen)
+static int coroutine_fn GRAPH_RDLOCK
+qed_read_string(BdrvChild *file, uint64_t offset,
+ size_t n, char *buf, size_t buflen)
{
int ret;
if (n >= buflen) {
return -EINVAL;
}
- ret = bdrv_pread(file, offset, buf, n);
+ ret = bdrv_co_pread(file, offset, n, buf, 0);
if (ret < 0) {
return ret;
}
@@ -258,7 +255,7 @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s)
return l2_table;
}
-static bool qed_plug_allocating_write_reqs(BDRVQEDState *s)
+static bool coroutine_fn qed_plug_allocating_write_reqs(BDRVQEDState *s)
{
qemu_co_mutex_lock(&s->table_lock);
@@ -266,7 +263,7 @@ static bool qed_plug_allocating_write_reqs(BDRVQEDState *s)
assert(!s->allocating_write_reqs_plugged);
if (s->allocating_acb != NULL) {
/* Another allocating write came concurrently. This cannot happen
- * from bdrv_qed_co_drain_begin, but it can happen when the timer runs.
+ * from bdrv_qed_drain_begin, but it can happen when the timer runs.
*/
qemu_co_mutex_unlock(&s->table_lock);
return false;
@@ -277,7 +274,7 @@ static bool qed_plug_allocating_write_reqs(BDRVQEDState *s)
return true;
}
-static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
+static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s)
{
qemu_co_mutex_lock(&s->table_lock);
assert(s->allocating_write_reqs_plugged);
@@ -286,12 +283,12 @@ static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
qemu_co_mutex_unlock(&s->table_lock);
}
-static void coroutine_fn qed_need_check_timer_entry(void *opaque)
+static void coroutine_fn GRAPH_RDLOCK qed_need_check_timer(BDRVQEDState *s)
{
- BDRVQEDState *s = opaque;
int ret;
trace_qed_need_check_timer_cb(s);
+ assert_bdrv_graph_readable();
if (!qed_plug_allocating_write_reqs(s)) {
return;
@@ -314,9 +311,21 @@ static void coroutine_fn qed_need_check_timer_entry(void *opaque)
(void) ret;
}
+static void coroutine_fn qed_need_check_timer_entry(void *opaque)
+{
+ BDRVQEDState *s = opaque;
+ GRAPH_RDLOCK_GUARD();
+
+ qed_need_check_timer(opaque);
+ bdrv_dec_in_flight(s->bs);
+}
+
static void qed_need_check_timer_cb(void *opaque)
{
+ BDRVQEDState *s = opaque;
Coroutine *co = qemu_coroutine_create(qed_need_check_timer_entry, opaque);
+
+ bdrv_inc_in_flight(s->bs);
qemu_coroutine_enter(co);
}
@@ -359,7 +368,7 @@ static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
}
}
-static void coroutine_fn bdrv_qed_co_drain_begin(BlockDriverState *bs)
+static void bdrv_qed_drain_begin(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
@@ -367,8 +376,12 @@ static void coroutine_fn bdrv_qed_co_drain_begin(BlockDriverState *bs)
* header is flushed.
*/
if (s->need_check_timer && timer_pending(s->need_check_timer)) {
+ Coroutine *co;
+
qed_cancel_need_check_timer(s);
- qed_need_check_timer_entry(s);
+ co = qemu_coroutine_create(qed_need_check_timer_entry, s);
+ bdrv_inc_in_flight(bs);
+ aio_co_enter(bdrv_get_aio_context(bs), co);
}
}
@@ -383,15 +396,15 @@ static void bdrv_qed_init_state(BlockDriverState *bs)
}
/* Called with table_lock held. */
-static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
- int flags, Error **errp)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
{
BDRVQEDState *s = bs->opaque;
QEDHeader le_header;
int64_t file_size;
int ret;
- ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header));
+ ret = bdrv_co_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
if (ret < 0) {
error_setg(errp, "Failed to read QED header");
return ret;
@@ -414,7 +427,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
}
/* Round down file size to the last cluster */
- file_size = bdrv_getlength(bs->file->bs);
+ file_size = bdrv_co_getlength(bs->file->bs);
if (file_size < 0) {
error_setg(errp, "Failed to get file length");
return file_size;
@@ -449,6 +462,8 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
}
if ((s->header.features & QED_F_BACKING_FILE)) {
+ g_autofree char *backing_file_str = NULL;
+
if ((uint64_t)s->header.backing_filename_offset +
s->header.backing_filename_size >
s->header.cluster_size * s->header.header_size) {
@@ -456,16 +471,21 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
return -EINVAL;
}
+ backing_file_str = g_malloc(sizeof(bs->backing_file));
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
s->header.backing_filename_size,
- bs->auto_backing_file,
- sizeof(bs->auto_backing_file));
+ backing_file_str, sizeof(bs->backing_file));
if (ret < 0) {
error_setg(errp, "Failed to read backing filename");
return ret;
}
- pstrcpy(bs->backing_file, sizeof(bs->backing_file),
- bs->auto_backing_file);
+
+ if (!g_str_equal(backing_file_str, bs->backing_file)) {
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ backing_file_str);
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file_str);
+ }
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
@@ -489,7 +509,7 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
}
/* From here on only known autoclear feature bits are valid */
- bdrv_flush(bs->file->bs);
+ bdrv_co_flush(bs->file->bs);
}
s->l1_table = qed_alloc_table(s);
@@ -543,13 +563,15 @@ static void coroutine_fn bdrv_qed_open_entry(void *opaque)
QEDOpenCo *qoc = opaque;
BDRVQEDState *s = qoc->bs->opaque;
+ GRAPH_RDLOCK_GUARD();
+
qemu_co_mutex_lock(&s->table_lock);
qoc->ret = bdrv_qed_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp);
qemu_co_mutex_unlock(&s->table_lock);
}
-static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
- Error **errp)
+static int coroutine_mixed_fn bdrv_qed_open(BlockDriverState *bs, QDict *options,
+ int flags, Error **errp)
{
QEDOpenCo qoc = {
.bs = bs,
@@ -558,22 +580,19 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
.errp = errp,
.ret = -EINPROGRESS
};
+ int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
bdrv_qed_init_state(bs);
- if (qemu_in_coroutine()) {
- bdrv_qed_open_entry(&qoc);
- } else {
- assert(qemu_get_current_aio_context() == qemu_get_aio_context());
- qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
- BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
- }
+ assert(!qemu_in_coroutine());
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
+ qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
+
return qoc.ret;
}
@@ -582,6 +601,7 @@ static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
BDRVQEDState *s = bs->opaque;
bs->bl.pwrite_zeroes_alignment = s->header.cluster_size;
+ bs->bl.max_pwrite_zeroes = QEMU_ALIGN_DOWN(INT_MAX, s->header.cluster_size);
}
/* We have nothing to do for QED reopen, stubs just return
@@ -592,7 +612,7 @@ static int bdrv_qed_reopen_prepare(BDRVReopenState *state,
return 0;
}
-static void bdrv_qed_close(BlockDriverState *bs)
+static void GRAPH_RDLOCK bdrv_qed_do_close(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
@@ -611,8 +631,16 @@ static void bdrv_qed_close(BlockDriverState *bs)
qemu_vfree(s->l1_table);
}
-static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
- Error **errp)
+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)
{
BlockdevCreateOptionsQed *qed_opts;
BlockBackend *blk = NULL;
@@ -658,13 +686,13 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
}
/* Create BlockBackend to write to the image */
- bs = bdrv_open_blockdev_ref(qed_opts->file, errp);
+ bs = bdrv_co_open_blockdev_ref(qed_opts->file, errp);
if (bs == NULL) {
return -EIO;
}
- blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
- errp);
+ blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
+ errp);
if (!blk) {
ret = -EPERM;
goto out;
@@ -689,12 +717,12 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
* The QED format associates file length with allocation status,
* so a new file (which is empty) must have a length of 0.
*/
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
+ ret = blk_co_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
if (ret < 0) {
goto out;
}
- if (qed_opts->has_backing_file) {
+ if (qed_opts->backing_file) {
header.features |= QED_F_BACKING_FILE;
header.backing_filename_offset = sizeof(le_header);
header.backing_filename_size = strlen(qed_opts->backing_file);
@@ -708,18 +736,18 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
}
qed_header_cpu_to_le(&header, &le_header);
- ret = blk_pwrite(blk, 0, &le_header, sizeof(le_header), 0);
+ ret = blk_co_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
if (ret < 0) {
goto out;
}
- ret = blk_pwrite(blk, sizeof(le_header), qed_opts->backing_file,
- header.backing_filename_size, 0);
+ ret = blk_co_pwrite(blk, sizeof(le_header), header.backing_filename_size,
+ qed_opts->backing_file, 0);
if (ret < 0) {
goto out;
}
l1_table = g_malloc0(l1_size);
- ret = blk_pwrite(blk, header.l1_table_offset, l1_table, l1_size, 0);
+ ret = blk_co_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
if (ret < 0) {
goto out;
}
@@ -727,15 +755,14 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
ret = 0; /* success */
out:
g_free(l1_table);
- blk_unref(blk);
- bdrv_unref(bs);
+ blk_co_unref(blk);
+ bdrv_co_unref(bs);
return ret;
}
-static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv,
- const char *filename,
- QemuOpts *opts,
- Error **errp)
+static int coroutine_fn GRAPH_UNLOCKED
+bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
+ QemuOpts *opts, Error **errp)
{
BlockdevCreateOptions *create_options = NULL;
QDict *qdict;
@@ -760,13 +787,13 @@ static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv,
}
/* Create and open the file (protocol layer) */
- ret = bdrv_create_file(filename, opts, errp);
+ ret = bdrv_co_create_file(filename, opts, errp);
if (ret < 0) {
goto fail;
}
- bs = bdrv_open(filename, NULL, NULL,
- BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
+ bs = bdrv_co_open(filename, NULL, NULL,
+ BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (bs == NULL) {
ret = -EIO;
goto fail;
@@ -799,16 +826,15 @@ static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv,
fail:
qobject_unref(qdict);
- bdrv_unref(bs);
+ bdrv_co_unref(bs);
qapi_free_BlockdevCreateOptions(create_options);
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);
@@ -861,11 +887,11 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
* 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);
+ BLKDBG_CO_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
return bdrv_co_preadv(s->bs->backing, pos, qiov->size, qiov, 0);
}
qemu_iovec_memset(qiov, 0, 0, qiov->size);
@@ -880,9 +906,9 @@ static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
* @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;
@@ -900,7 +926,7 @@ static int coroutine_fn qed_copy_from_backing_file(BDRVQEDState *s,
goto out;
}
- BLKDBG_EVENT(s->bs->file, BLKDBG_COW_WRITE);
+ BLKDBG_CO_EVENT(s->bs->file, BLKDBG_COW_WRITE);
ret = bdrv_co_pwritev(s->bs->file, offset, qiov.size, &qiov, 0);
if (ret < 0) {
goto out;
@@ -975,7 +1001,7 @@ static void coroutine_fn qed_aio_complete(QEDAIOCB *acb)
*
* Called with table_lock held.
*/
-static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_l1_update(QEDAIOCB *acb)
{
BDRVQEDState *s = acb_to_s(acb);
CachedL2Table *l2_table = acb->request.l2_table;
@@ -1005,7 +1031,8 @@ static int coroutine_fn qed_aio_write_l1_update(QEDAIOCB *acb)
*
* Called with table_lock held.
*/
-static int coroutine_fn qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
+static int coroutine_fn GRAPH_RDLOCK
+qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
{
BDRVQEDState *s = acb_to_s(acb);
bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1;
@@ -1043,7 +1070,7 @@ static int coroutine_fn qed_aio_write_l2_update(QEDAIOCB *acb, uint64_t offset)
*
* 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 +
@@ -1051,7 +1078,7 @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
trace_qed_aio_write_main(s, acb, 0, offset, acb->cur_qiov.size);
- BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO);
+ BLKDBG_CO_EVENT(s->bs->file, BLKDBG_WRITE_AIO);
return bdrv_co_pwritev(s->bs->file, offset, acb->cur_qiov.size,
&acb->cur_qiov, 0);
}
@@ -1061,7 +1088,7 @@ static int coroutine_fn qed_aio_write_main(QEDAIOCB *acb)
*
* Called with table_lock held.
*/
-static int coroutine_fn qed_aio_write_cow(QEDAIOCB *acb)
+static int coroutine_fn GRAPH_RDLOCK qed_aio_write_cow(QEDAIOCB *acb)
{
BDRVQEDState *s = acb_to_s(acb);
uint64_t start, len, offset;
@@ -1119,7 +1146,7 @@ out:
/**
* Check if the QED_F_NEED_CHECK bit should be set during allocating write
*/
-static bool qed_should_set_need_check(BDRVQEDState *s)
+static bool GRAPH_RDLOCK qed_should_set_need_check(BDRVQEDState *s)
{
/* The flush before L2 update path ensures consistency */
if (s->bs->backing) {
@@ -1139,7 +1166,8 @@ static bool qed_should_set_need_check(BDRVQEDState *s)
*
* Called with table_lock held.
*/
-static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
+static int coroutine_fn GRAPH_RDLOCK
+qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
{
BDRVQEDState *s = acb_to_s(acb);
int ret;
@@ -1202,8 +1230,8 @@ static int coroutine_fn qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
*
* 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;
@@ -1245,8 +1273,8 @@ out:
*
* Called with table_lock held.
*/
-static int coroutine_fn qed_aio_write_data(void *opaque, int ret,
- uint64_t offset, size_t len)
+static int coroutine_fn GRAPH_RDLOCK
+qed_aio_write_data(void *opaque, int ret, uint64_t offset, size_t len)
{
QEDAIOCB *acb = opaque;
@@ -1278,8 +1306,8 @@ static int coroutine_fn qed_aio_write_data(void *opaque, int ret,
*
* 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);
@@ -1304,7 +1332,7 @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
} else if (ret != QED_CLUSTER_FOUND) {
r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov);
} else {
- BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
+ BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO);
r = bdrv_co_preadv(bs->file, offset, acb->cur_qiov.size,
&acb->cur_qiov, 0);
}
@@ -1316,7 +1344,7 @@ static int coroutine_fn qed_aio_read_data(void *opaque, int ret,
/**
* Begin next I/O or complete the request
*/
-static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
+static int coroutine_fn GRAPH_RDLOCK qed_aio_next_io(QEDAIOCB *acb)
{
BDRVQEDState *s = acb_to_s(acb);
uint64_t offset;
@@ -1361,9 +1389,9 @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
return ret;
}
-static int coroutine_fn qed_co_request(BlockDriverState *bs, int64_t sector_num,
- QEMUIOVector *qiov, int nb_sectors,
- int flags)
+static int coroutine_fn GRAPH_RDLOCK
+qed_co_request(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov,
+ int nb_sectors, int flags)
{
QEDAIOCB acb = {
.bs = bs,
@@ -1380,25 +1408,23 @@ static int coroutine_fn qed_co_request(BlockDriverState *bs, int64_t sector_num,
return qed_aio_next_io(&acb);
}
-static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors,
- QEMUIOVector *qiov)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_readv(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
+ QEMUIOVector *qiov)
{
return qed_co_request(bs, sector_num, qiov, nb_sectors, 0);
}
-static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors,
- QEMUIOVector *qiov, int flags)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
+ QEMUIOVector *qiov, int flags)
{
- assert(!flags);
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
}
-static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
- int64_t offset,
- int bytes,
- BdrvRequestFlags flags)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
+ BdrvRequestFlags flags)
{
BDRVQEDState *s = bs->opaque;
@@ -1408,6 +1434,12 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
*/
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, bytes);
+ /*
+ * QED is not prepared for 63bit write-zero requests, so rely on
+ * max_pwrite_zeroes.
+ */
+ assert(bytes <= INT_MAX);
+
/* Fall back if the request is not aligned */
if (qed_offset_into_cluster(s, offset) ||
qed_offset_into_cluster(s, bytes)) {
@@ -1419,12 +1451,10 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
QED_AIOCB_WRITE | QED_AIOCB_ZERO);
}
-static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
- int64_t offset,
- bool exact,
- PreallocMode prealloc,
- BdrvRequestFlags flags,
- Error **errp)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
+ PreallocMode prealloc, BdrvRequestFlags flags,
+ Error **errp)
{
BDRVQEDState *s = bs->opaque;
uint64_t old_image_size;
@@ -1457,13 +1487,14 @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
return ret;
}
-static int64_t bdrv_qed_getlength(BlockDriverState *bs)
+static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
return s->header.image_size;
}
-static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+static int coroutine_fn
+bdrv_qed_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQEDState *s = bs->opaque;
@@ -1473,9 +1504,9 @@ static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return 0;
}
-static int bdrv_qed_change_backing_file(BlockDriverState *bs,
- const char *backing_file,
- const char *backing_fmt)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt)
{
BDRVQEDState *s = bs->opaque;
QEDHeader new_header, le_header;
@@ -1537,7 +1568,7 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
}
/* Write new header */
- ret = bdrv_pwrite_sync(bs->file, 0, buffer, buffer_len);
+ ret = bdrv_co_pwrite_sync(bs->file, 0, buffer_len, buffer, 0);
g_free(buffer);
if (ret == 0) {
memcpy(&s->header, &new_header, sizeof(new_header));
@@ -1545,13 +1576,14 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
return ret;
}
-static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
- Error **errp)
+static void coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_invalidate_cache(BlockDriverState *bs, Error **errp)
{
+ ERRP_GUARD();
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);
@@ -1562,9 +1594,9 @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
}
}
-static int coroutine_fn bdrv_qed_co_check(BlockDriverState *bs,
- BdrvCheckResult *result,
- BdrvCheckMode fix)
+static int coroutine_fn GRAPH_RDLOCK
+bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result,
+ BdrvCheckMode fix)
{
BDRVQEDState *s = bs->opaque;
int ret;
@@ -1611,34 +1643,34 @@ static QemuOptsList qed_create_opts = {
};
static BlockDriver bdrv_qed = {
- .format_name = "qed",
- .instance_size = sizeof(BDRVQEDState),
- .create_opts = &qed_create_opts,
- .is_format = true,
- .supports_backing = true,
-
- .bdrv_probe = bdrv_qed_probe,
- .bdrv_open = bdrv_qed_open,
- .bdrv_close = bdrv_qed_close,
- .bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
- .bdrv_child_perm = bdrv_default_perms,
- .bdrv_co_create = bdrv_qed_co_create,
- .bdrv_co_create_opts = bdrv_qed_co_create_opts,
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
- .bdrv_co_block_status = bdrv_qed_co_block_status,
- .bdrv_co_readv = bdrv_qed_co_readv,
- .bdrv_co_writev = bdrv_qed_co_writev,
- .bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
- .bdrv_co_truncate = bdrv_qed_co_truncate,
- .bdrv_getlength = bdrv_qed_getlength,
- .bdrv_get_info = bdrv_qed_get_info,
- .bdrv_refresh_limits = bdrv_qed_refresh_limits,
- .bdrv_change_backing_file = bdrv_qed_change_backing_file,
- .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
- .bdrv_co_check = bdrv_qed_co_check,
- .bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
- .bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
- .bdrv_co_drain_begin = bdrv_qed_co_drain_begin,
+ .format_name = "qed",
+ .instance_size = sizeof(BDRVQEDState),
+ .create_opts = &qed_create_opts,
+ .is_format = true,
+ .supports_backing = true,
+
+ .bdrv_probe = bdrv_qed_probe,
+ .bdrv_open = bdrv_qed_open,
+ .bdrv_close = bdrv_qed_close,
+ .bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
+ .bdrv_child_perm = bdrv_default_perms,
+ .bdrv_co_create = bdrv_qed_co_create,
+ .bdrv_co_create_opts = bdrv_qed_co_create_opts,
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
+ .bdrv_co_block_status = bdrv_qed_co_block_status,
+ .bdrv_co_readv = bdrv_qed_co_readv,
+ .bdrv_co_writev = bdrv_qed_co_writev,
+ .bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
+ .bdrv_co_truncate = bdrv_qed_co_truncate,
+ .bdrv_co_getlength = bdrv_qed_co_getlength,
+ .bdrv_co_get_info = bdrv_qed_co_get_info,
+ .bdrv_refresh_limits = bdrv_qed_refresh_limits,
+ .bdrv_co_change_backing_file = bdrv_qed_co_change_backing_file,
+ .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
+ .bdrv_co_check = bdrv_qed_co_check,
+ .bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
+ .bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
+ .bdrv_drain_begin = bdrv_qed_drain_begin,
};
static void bdrv_qed_init(void)