|
@@ -32,6 +32,7 @@
|
|
#include "block/coroutines.h"
|
|
#include "block/coroutines.h"
|
|
#include "block/write-threshold.h"
|
|
#include "block/write-threshold.h"
|
|
#include "qemu/cutils.h"
|
|
#include "qemu/cutils.h"
|
|
|
|
+#include "qemu/memalign.h"
|
|
#include "qapi/error.h"
|
|
#include "qapi/error.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/main-loop.h"
|
|
#include "qemu/main-loop.h"
|
|
@@ -70,6 +71,7 @@ static void bdrv_parent_drained_end_single_no_poll(BdrvChild *c,
|
|
void bdrv_parent_drained_end_single(BdrvChild *c)
|
|
void bdrv_parent_drained_end_single(BdrvChild *c)
|
|
{
|
|
{
|
|
int drained_end_counter = 0;
|
|
int drained_end_counter = 0;
|
|
|
|
+ IO_OR_GS_CODE();
|
|
bdrv_parent_drained_end_single_no_poll(c, &drained_end_counter);
|
|
bdrv_parent_drained_end_single_no_poll(c, &drained_end_counter);
|
|
BDRV_POLL_WHILE(c->bs, qatomic_read(&drained_end_counter) > 0);
|
|
BDRV_POLL_WHILE(c->bs, qatomic_read(&drained_end_counter) > 0);
|
|
}
|
|
}
|
|
@@ -114,6 +116,7 @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
|
|
|
|
|
|
void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
|
|
void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
|
|
{
|
|
{
|
|
|
|
+ IO_OR_GS_CODE();
|
|
c->parent_quiesce_counter++;
|
|
c->parent_quiesce_counter++;
|
|
if (c->klass->drained_begin) {
|
|
if (c->klass->drained_begin) {
|
|
c->klass->drained_begin(c);
|
|
c->klass->drained_begin(c);
|
|
@@ -164,6 +167,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
|
|
BdrvChild *c;
|
|
BdrvChild *c;
|
|
bool have_limits;
|
|
bool have_limits;
|
|
|
|
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
|
|
+
|
|
if (tran) {
|
|
if (tran) {
|
|
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
|
|
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
|
|
*s = (BdrvRefreshLimitsState) {
|
|
*s = (BdrvRefreshLimitsState) {
|
|
@@ -189,10 +194,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
|
|
QLIST_FOREACH(c, &bs->children, next) {
|
|
QLIST_FOREACH(c, &bs->children, next) {
|
|
if (c->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED | BDRV_CHILD_COW))
|
|
if (c->role & (BDRV_CHILD_DATA | BDRV_CHILD_FILTERED | BDRV_CHILD_COW))
|
|
{
|
|
{
|
|
- bdrv_refresh_limits(c->bs, tran, errp);
|
|
|
|
- if (*errp) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
bdrv_merge_limits(&bs->bl, &c->bs->bl);
|
|
bdrv_merge_limits(&bs->bl, &c->bs->bl);
|
|
have_limits = true;
|
|
have_limits = true;
|
|
}
|
|
}
|
|
@@ -226,12 +227,14 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
|
|
*/
|
|
*/
|
|
void bdrv_enable_copy_on_read(BlockDriverState *bs)
|
|
void bdrv_enable_copy_on_read(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
qatomic_inc(&bs->copy_on_read);
|
|
qatomic_inc(&bs->copy_on_read);
|
|
}
|
|
}
|
|
|
|
|
|
void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
|
void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
|
{
|
|
{
|
|
int old = qatomic_fetch_dec(&bs->copy_on_read);
|
|
int old = qatomic_fetch_dec(&bs->copy_on_read);
|
|
|
|
+ IO_CODE();
|
|
assert(old >= 1);
|
|
assert(old >= 1);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -303,6 +306,7 @@ bool bdrv_drain_poll(BlockDriverState *bs, bool recursive,
|
|
BdrvChild *ignore_parent, bool ignore_bds_parents)
|
|
BdrvChild *ignore_parent, bool ignore_bds_parents)
|
|
{
|
|
{
|
|
BdrvChild *child, *next;
|
|
BdrvChild *child, *next;
|
|
|
|
+ IO_OR_GS_CODE();
|
|
|
|
|
|
if (bdrv_parent_drained_poll(bs, ignore_parent, ignore_bds_parents)) {
|
|
if (bdrv_parent_drained_poll(bs, ignore_parent, ignore_bds_parents)) {
|
|
return true;
|
|
return true;
|
|
@@ -426,6 +430,7 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
|
void bdrv_do_drained_begin_quiesce(BlockDriverState *bs,
|
|
void bdrv_do_drained_begin_quiesce(BlockDriverState *bs,
|
|
BdrvChild *parent, bool ignore_bds_parents)
|
|
BdrvChild *parent, bool ignore_bds_parents)
|
|
{
|
|
{
|
|
|
|
+ IO_OR_GS_CODE();
|
|
assert(!qemu_in_coroutine());
|
|
assert(!qemu_in_coroutine());
|
|
|
|
|
|
/* Stop things in parent-to-child order */
|
|
/* Stop things in parent-to-child order */
|
|
@@ -477,11 +482,13 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
|
|
|
|
|
void bdrv_drained_begin(BlockDriverState *bs)
|
|
void bdrv_drained_begin(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_OR_GS_CODE();
|
|
bdrv_do_drained_begin(bs, false, NULL, false, true);
|
|
bdrv_do_drained_begin(bs, false, NULL, false, true);
|
|
}
|
|
}
|
|
|
|
|
|
void bdrv_subtree_drained_begin(BlockDriverState *bs)
|
|
void bdrv_subtree_drained_begin(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_OR_GS_CODE();
|
|
bdrv_do_drained_begin(bs, true, NULL, false, true);
|
|
bdrv_do_drained_begin(bs, true, NULL, false, true);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -538,18 +545,21 @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
|
void bdrv_drained_end(BlockDriverState *bs)
|
|
void bdrv_drained_end(BlockDriverState *bs)
|
|
{
|
|
{
|
|
int drained_end_counter = 0;
|
|
int drained_end_counter = 0;
|
|
|
|
+ IO_OR_GS_CODE();
|
|
bdrv_do_drained_end(bs, false, NULL, false, &drained_end_counter);
|
|
bdrv_do_drained_end(bs, false, NULL, false, &drained_end_counter);
|
|
BDRV_POLL_WHILE(bs, qatomic_read(&drained_end_counter) > 0);
|
|
BDRV_POLL_WHILE(bs, qatomic_read(&drained_end_counter) > 0);
|
|
}
|
|
}
|
|
|
|
|
|
void bdrv_drained_end_no_poll(BlockDriverState *bs, int *drained_end_counter)
|
|
void bdrv_drained_end_no_poll(BlockDriverState *bs, int *drained_end_counter)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
bdrv_do_drained_end(bs, false, NULL, false, drained_end_counter);
|
|
bdrv_do_drained_end(bs, false, NULL, false, drained_end_counter);
|
|
}
|
|
}
|
|
|
|
|
|
void bdrv_subtree_drained_end(BlockDriverState *bs)
|
|
void bdrv_subtree_drained_end(BlockDriverState *bs)
|
|
{
|
|
{
|
|
int drained_end_counter = 0;
|
|
int drained_end_counter = 0;
|
|
|
|
+ IO_OR_GS_CODE();
|
|
bdrv_do_drained_end(bs, true, NULL, false, &drained_end_counter);
|
|
bdrv_do_drained_end(bs, true, NULL, false, &drained_end_counter);
|
|
BDRV_POLL_WHILE(bs, qatomic_read(&drained_end_counter) > 0);
|
|
BDRV_POLL_WHILE(bs, qatomic_read(&drained_end_counter) > 0);
|
|
}
|
|
}
|
|
@@ -557,6 +567,7 @@ void bdrv_subtree_drained_end(BlockDriverState *bs)
|
|
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent)
|
|
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
|
|
+ IO_OR_GS_CODE();
|
|
|
|
|
|
for (i = 0; i < new_parent->recursive_quiesce_counter; i++) {
|
|
for (i = 0; i < new_parent->recursive_quiesce_counter; i++) {
|
|
bdrv_do_drained_begin(child->bs, true, child, false, true);
|
|
bdrv_do_drained_begin(child->bs, true, child, false, true);
|
|
@@ -567,6 +578,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent)
|
|
{
|
|
{
|
|
int drained_end_counter = 0;
|
|
int drained_end_counter = 0;
|
|
int i;
|
|
int i;
|
|
|
|
+ IO_OR_GS_CODE();
|
|
|
|
|
|
for (i = 0; i < old_parent->recursive_quiesce_counter; i++) {
|
|
for (i = 0; i < old_parent->recursive_quiesce_counter; i++) {
|
|
bdrv_do_drained_end(child->bs, true, child, false,
|
|
bdrv_do_drained_end(child->bs, true, child, false,
|
|
@@ -585,6 +597,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent)
|
|
*/
|
|
*/
|
|
void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
|
|
void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_OR_GS_CODE();
|
|
assert(qemu_in_coroutine());
|
|
assert(qemu_in_coroutine());
|
|
bdrv_drained_begin(bs);
|
|
bdrv_drained_begin(bs);
|
|
bdrv_drained_end(bs);
|
|
bdrv_drained_end(bs);
|
|
@@ -592,6 +605,7 @@ void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
|
|
|
|
|
|
void bdrv_drain(BlockDriverState *bs)
|
|
void bdrv_drain(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_OR_GS_CODE();
|
|
bdrv_drained_begin(bs);
|
|
bdrv_drained_begin(bs);
|
|
bdrv_drained_end(bs);
|
|
bdrv_drained_end(bs);
|
|
}
|
|
}
|
|
@@ -612,6 +626,7 @@ static bool bdrv_drain_all_poll(void)
|
|
{
|
|
{
|
|
BlockDriverState *bs = NULL;
|
|
BlockDriverState *bs = NULL;
|
|
bool result = false;
|
|
bool result = false;
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
|
|
|
|
/* bdrv_drain_poll() can't make changes to the graph and we are holding the
|
|
/* bdrv_drain_poll() can't make changes to the graph and we are holding the
|
|
* main AioContext lock, so iterating bdrv_next_all_states() is safe. */
|
|
* main AioContext lock, so iterating bdrv_next_all_states() is safe. */
|
|
@@ -640,6 +655,7 @@ static bool bdrv_drain_all_poll(void)
|
|
void bdrv_drain_all_begin(void)
|
|
void bdrv_drain_all_begin(void)
|
|
{
|
|
{
|
|
BlockDriverState *bs = NULL;
|
|
BlockDriverState *bs = NULL;
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
|
|
|
|
if (qemu_in_coroutine()) {
|
|
if (qemu_in_coroutine()) {
|
|
bdrv_co_yield_to_drain(NULL, true, false, NULL, true, true, NULL);
|
|
bdrv_co_yield_to_drain(NULL, true, false, NULL, true, true, NULL);
|
|
@@ -682,6 +698,7 @@ void bdrv_drain_all_begin(void)
|
|
void bdrv_drain_all_end_quiesce(BlockDriverState *bs)
|
|
void bdrv_drain_all_end_quiesce(BlockDriverState *bs)
|
|
{
|
|
{
|
|
int drained_end_counter = 0;
|
|
int drained_end_counter = 0;
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
|
|
|
|
g_assert(bs->quiesce_counter > 0);
|
|
g_assert(bs->quiesce_counter > 0);
|
|
g_assert(!bs->refcnt);
|
|
g_assert(!bs->refcnt);
|
|
@@ -696,6 +713,7 @@ void bdrv_drain_all_end(void)
|
|
{
|
|
{
|
|
BlockDriverState *bs = NULL;
|
|
BlockDriverState *bs = NULL;
|
|
int drained_end_counter = 0;
|
|
int drained_end_counter = 0;
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
|
|
|
|
/*
|
|
/*
|
|
* bdrv queue is managed by record/replay,
|
|
* bdrv queue is managed by record/replay,
|
|
@@ -723,6 +741,7 @@ void bdrv_drain_all_end(void)
|
|
|
|
|
|
void bdrv_drain_all(void)
|
|
void bdrv_drain_all(void)
|
|
{
|
|
{
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
bdrv_drain_all_begin();
|
|
bdrv_drain_all_begin();
|
|
bdrv_drain_all_end();
|
|
bdrv_drain_all_end();
|
|
}
|
|
}
|
|
@@ -867,6 +886,7 @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
|
|
{
|
|
{
|
|
BdrvTrackedRequest *req;
|
|
BdrvTrackedRequest *req;
|
|
Coroutine *self = qemu_coroutine_self();
|
|
Coroutine *self = qemu_coroutine_self();
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
QLIST_FOREACH(req, &bs->tracked_requests, list) {
|
|
QLIST_FOREACH(req, &bs->tracked_requests, list) {
|
|
if (req->co == self) {
|
|
if (req->co == self) {
|
|
@@ -886,7 +906,7 @@ void bdrv_round_to_clusters(BlockDriverState *bs,
|
|
int64_t *cluster_bytes)
|
|
int64_t *cluster_bytes)
|
|
{
|
|
{
|
|
BlockDriverInfo bdi;
|
|
BlockDriverInfo bdi;
|
|
-
|
|
|
|
|
|
+ IO_CODE();
|
|
if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
|
|
if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
|
|
*cluster_offset = offset;
|
|
*cluster_offset = offset;
|
|
*cluster_bytes = bytes;
|
|
*cluster_bytes = bytes;
|
|
@@ -912,16 +932,19 @@ static int bdrv_get_cluster_size(BlockDriverState *bs)
|
|
|
|
|
|
void bdrv_inc_in_flight(BlockDriverState *bs)
|
|
void bdrv_inc_in_flight(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
qatomic_inc(&bs->in_flight);
|
|
qatomic_inc(&bs->in_flight);
|
|
}
|
|
}
|
|
|
|
|
|
void bdrv_wakeup(BlockDriverState *bs)
|
|
void bdrv_wakeup(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
aio_wait_kick();
|
|
aio_wait_kick();
|
|
}
|
|
}
|
|
|
|
|
|
void bdrv_dec_in_flight(BlockDriverState *bs)
|
|
void bdrv_dec_in_flight(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
qatomic_dec(&bs->in_flight);
|
|
qatomic_dec(&bs->in_flight);
|
|
bdrv_wakeup(bs);
|
|
bdrv_wakeup(bs);
|
|
}
|
|
}
|
|
@@ -946,6 +969,7 @@ bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
|
|
uint64_t align)
|
|
uint64_t align)
|
|
{
|
|
{
|
|
bool waited;
|
|
bool waited;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
qemu_co_mutex_lock(&req->bs->reqs_lock);
|
|
qemu_co_mutex_lock(&req->bs->reqs_lock);
|
|
|
|
|
|
@@ -1040,6 +1064,7 @@ static int bdrv_check_request32(int64_t offset, int64_t bytes,
|
|
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
|
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
|
int64_t bytes, BdrvRequestFlags flags)
|
|
int64_t bytes, BdrvRequestFlags flags)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return bdrv_pwritev(child, offset, bytes, NULL,
|
|
return bdrv_pwritev(child, offset, bytes, NULL,
|
|
BDRV_REQ_ZERO_WRITE | flags);
|
|
BDRV_REQ_ZERO_WRITE | flags);
|
|
}
|
|
}
|
|
@@ -1058,6 +1083,7 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
|
|
int ret;
|
|
int ret;
|
|
int64_t target_size, bytes, offset = 0;
|
|
int64_t target_size, bytes, offset = 0;
|
|
BlockDriverState *bs = child->bs;
|
|
BlockDriverState *bs = child->bs;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
target_size = bdrv_getlength(bs);
|
|
target_size = bdrv_getlength(bs);
|
|
if (target_size < 0) {
|
|
if (target_size < 0) {
|
|
@@ -1090,6 +1116,7 @@ int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
if (bytes < 0) {
|
|
if (bytes < 0) {
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -1111,6 +1138,7 @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
if (bytes < 0) {
|
|
if (bytes < 0) {
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -1131,6 +1159,7 @@ int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
|
|
const void *buf, int64_t count)
|
|
const void *buf, int64_t count)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
ret = bdrv_pwrite(child, offset, buf, count);
|
|
ret = bdrv_pwrite(child, offset, buf, count);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
@@ -1797,6 +1826,7 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
|
BdrvRequestFlags flags)
|
|
BdrvRequestFlags flags)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags);
|
|
return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1809,6 +1839,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
|
|
BdrvTrackedRequest req;
|
|
BdrvTrackedRequest req;
|
|
BdrvRequestPadding pad;
|
|
BdrvRequestPadding pad;
|
|
int ret;
|
|
int ret;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
|
|
trace_bdrv_co_preadv_part(bs, offset, bytes, flags);
|
|
|
|
|
|
@@ -2173,6 +2204,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
|
|
|
|
|
padding = bdrv_init_padding(bs, offset, bytes, &pad);
|
|
padding = bdrv_init_padding(bs, offset, bytes, &pad);
|
|
if (padding) {
|
|
if (padding) {
|
|
|
|
+ assert(!(flags & BDRV_REQ_NO_WAIT));
|
|
bdrv_make_request_serialising(req, align);
|
|
bdrv_make_request_serialising(req, align);
|
|
|
|
|
|
bdrv_padding_rmw_read(child, req, &pad, true);
|
|
bdrv_padding_rmw_read(child, req, &pad, true);
|
|
@@ -2230,6 +2262,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
|
int64_t offset, int64_t bytes, QEMUIOVector *qiov,
|
|
BdrvRequestFlags flags)
|
|
BdrvRequestFlags flags)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags);
|
|
return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2243,6 +2276,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
|
BdrvRequestPadding pad;
|
|
BdrvRequestPadding pad;
|
|
int ret;
|
|
int ret;
|
|
bool padded = false;
|
|
bool padded = false;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
|
|
trace_bdrv_co_pwritev_part(child->bs, offset, bytes, flags);
|
|
|
|
|
|
@@ -2307,6 +2341,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
|
|
* serialize the request to prevent interactions of the
|
|
* serialize the request to prevent interactions of the
|
|
* widened region with other transactions.
|
|
* widened region with other transactions.
|
|
*/
|
|
*/
|
|
|
|
+ assert(!(flags & BDRV_REQ_NO_WAIT));
|
|
bdrv_make_request_serialising(&req, align);
|
|
bdrv_make_request_serialising(&req, align);
|
|
bdrv_padding_rmw_read(child, &req, &pad, false);
|
|
bdrv_padding_rmw_read(child, &req, &pad, false);
|
|
}
|
|
}
|
|
@@ -2326,6 +2361,7 @@ out:
|
|
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
|
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
|
int64_t bytes, BdrvRequestFlags flags)
|
|
int64_t bytes, BdrvRequestFlags flags)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
|
|
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
|
|
|
|
|
|
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
|
|
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
|
|
@@ -2345,6 +2381,8 @@ int bdrv_flush_all(void)
|
|
BlockDriverState *bs = NULL;
|
|
BlockDriverState *bs = NULL;
|
|
int result = 0;
|
|
int result = 0;
|
|
|
|
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* bdrv queue is managed by record/replay,
|
|
* bdrv queue is managed by record/replay,
|
|
* creating new flush request for stopping
|
|
* creating new flush request for stopping
|
|
@@ -2497,8 +2535,12 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
|
|
* non-protocol nodes, and then it is never used. However, filling
|
|
* non-protocol nodes, and then it is never used. However, filling
|
|
* the cache requires an RCU update, so double check here to avoid
|
|
* the cache requires an RCU update, so double check here to avoid
|
|
* such an update if possible.
|
|
* such an update if possible.
|
|
|
|
+ *
|
|
|
|
+ * Check want_zero, because we only want to update the cache when we
|
|
|
|
+ * have accurate information about what is zero and what is data.
|
|
*/
|
|
*/
|
|
- if (ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) &&
|
|
|
|
|
|
+ if (want_zero &&
|
|
|
|
+ ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) &&
|
|
QLIST_EMPTY(&bs->children))
|
|
QLIST_EMPTY(&bs->children))
|
|
{
|
|
{
|
|
/*
|
|
/*
|
|
@@ -2635,6 +2677,7 @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
|
|
BlockDriverState *p;
|
|
BlockDriverState *p;
|
|
int64_t eof = 0;
|
|
int64_t eof = 0;
|
|
int dummy;
|
|
int dummy;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
assert(!include_base || base); /* Can't include NULL base */
|
|
assert(!include_base || base); /* Can't include NULL base */
|
|
|
|
|
|
@@ -2724,6 +2767,7 @@ int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
|
|
int64_t offset, int64_t bytes, int64_t *pnum,
|
|
int64_t offset, int64_t bytes, int64_t *pnum,
|
|
int64_t *map, BlockDriverState **file)
|
|
int64_t *map, BlockDriverState **file)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return bdrv_common_block_status_above(bs, base, false, true, offset, bytes,
|
|
return bdrv_common_block_status_above(bs, base, false, true, offset, bytes,
|
|
pnum, map, file, NULL);
|
|
pnum, map, file, NULL);
|
|
}
|
|
}
|
|
@@ -2731,6 +2775,7 @@ int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
|
|
int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
|
int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
|
int64_t *pnum, int64_t *map, BlockDriverState **file)
|
|
int64_t *pnum, int64_t *map, BlockDriverState **file)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return bdrv_block_status_above(bs, bdrv_filter_or_cow_bs(bs),
|
|
return bdrv_block_status_above(bs, bdrv_filter_or_cow_bs(bs),
|
|
offset, bytes, pnum, map, file);
|
|
offset, bytes, pnum, map, file);
|
|
}
|
|
}
|
|
@@ -2747,6 +2792,7 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
int64_t pnum = bytes;
|
|
int64_t pnum = bytes;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
if (!bytes) {
|
|
if (!bytes) {
|
|
return 1;
|
|
return 1;
|
|
@@ -2767,6 +2813,7 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
int64_t dummy;
|
|
int64_t dummy;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
ret = bdrv_common_block_status_above(bs, bs, true, false, offset,
|
|
ret = bdrv_common_block_status_above(bs, bs, true, false, offset,
|
|
bytes, pnum ? pnum : &dummy, NULL,
|
|
bytes, pnum ? pnum : &dummy, NULL,
|
|
@@ -2803,6 +2850,7 @@ int bdrv_is_allocated_above(BlockDriverState *top,
|
|
int ret = bdrv_common_block_status_above(top, base, include_base, false,
|
|
int ret = bdrv_common_block_status_above(top, base, include_base, false,
|
|
offset, bytes, pnum, NULL, NULL,
|
|
offset, bytes, pnum, NULL, NULL,
|
|
&depth);
|
|
&depth);
|
|
|
|
+ IO_CODE();
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -2819,6 +2867,7 @@ bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
|
|
BlockDriver *drv = bs->drv;
|
|
BlockDriver *drv = bs->drv;
|
|
BlockDriverState *child_bs = bdrv_primary_bs(bs);
|
|
BlockDriverState *child_bs = bdrv_primary_bs(bs);
|
|
int ret;
|
|
int ret;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
ret = bdrv_check_qiov_request(pos, qiov->size, qiov, 0, NULL);
|
|
ret = bdrv_check_qiov_request(pos, qiov->size, qiov, 0, NULL);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
@@ -2850,6 +2899,7 @@ bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos)
|
|
BlockDriver *drv = bs->drv;
|
|
BlockDriver *drv = bs->drv;
|
|
BlockDriverState *child_bs = bdrv_primary_bs(bs);
|
|
BlockDriverState *child_bs = bdrv_primary_bs(bs);
|
|
int ret;
|
|
int ret;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
ret = bdrv_check_qiov_request(pos, qiov->size, qiov, 0, NULL);
|
|
ret = bdrv_check_qiov_request(pos, qiov->size, qiov, 0, NULL);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
@@ -2880,6 +2930,7 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
|
|
{
|
|
{
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
|
|
int ret = bdrv_writev_vmstate(bs, &qiov, pos);
|
|
int ret = bdrv_writev_vmstate(bs, &qiov, pos);
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
return ret < 0 ? ret : size;
|
|
return ret < 0 ? ret : size;
|
|
}
|
|
}
|
|
@@ -2889,6 +2940,7 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
|
{
|
|
{
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
|
|
int ret = bdrv_readv_vmstate(bs, &qiov, pos);
|
|
int ret = bdrv_readv_vmstate(bs, &qiov, pos);
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
return ret < 0 ? ret : size;
|
|
return ret < 0 ? ret : size;
|
|
}
|
|
}
|
|
@@ -2898,6 +2950,7 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
|
|
|
|
|
void bdrv_aio_cancel(BlockAIOCB *acb)
|
|
void bdrv_aio_cancel(BlockAIOCB *acb)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
qemu_aio_ref(acb);
|
|
qemu_aio_ref(acb);
|
|
bdrv_aio_cancel_async(acb);
|
|
bdrv_aio_cancel_async(acb);
|
|
while (acb->refcnt > 1) {
|
|
while (acb->refcnt > 1) {
|
|
@@ -2922,6 +2975,7 @@ void bdrv_aio_cancel(BlockAIOCB *acb)
|
|
* In either case the completion callback must be called. */
|
|
* In either case the completion callback must be called. */
|
|
void bdrv_aio_cancel_async(BlockAIOCB *acb)
|
|
void bdrv_aio_cancel_async(BlockAIOCB *acb)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
if (acb->aiocb_info->cancel_async) {
|
|
if (acb->aiocb_info->cancel_async) {
|
|
acb->aiocb_info->cancel_async(acb);
|
|
acb->aiocb_info->cancel_async(acb);
|
|
}
|
|
}
|
|
@@ -2936,6 +2990,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
|
BdrvChild *child;
|
|
BdrvChild *child;
|
|
int current_gen;
|
|
int current_gen;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
bdrv_inc_in_flight(bs);
|
|
bdrv_inc_in_flight(bs);
|
|
|
|
|
|
@@ -3061,6 +3116,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
|
int64_t max_pdiscard;
|
|
int64_t max_pdiscard;
|
|
int head, tail, align;
|
|
int head, tail, align;
|
|
BlockDriverState *bs = child->bs;
|
|
BlockDriverState *bs = child->bs;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
if (!bs || !bs->drv || !bdrv_is_inserted(bs)) {
|
|
if (!bs || !bs->drv || !bdrv_is_inserted(bs)) {
|
|
return -ENOMEDIUM;
|
|
return -ENOMEDIUM;
|
|
@@ -3179,6 +3235,7 @@ int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
|
|
.coroutine = qemu_coroutine_self(),
|
|
.coroutine = qemu_coroutine_self(),
|
|
};
|
|
};
|
|
BlockAIOCB *acb;
|
|
BlockAIOCB *acb;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
bdrv_inc_in_flight(bs);
|
|
bdrv_inc_in_flight(bs);
|
|
if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) {
|
|
if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) {
|
|
@@ -3203,17 +3260,20 @@ out:
|
|
|
|
|
|
void *qemu_blockalign(BlockDriverState *bs, size_t size)
|
|
void *qemu_blockalign(BlockDriverState *bs, size_t size)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return qemu_memalign(bdrv_opt_mem_align(bs), size);
|
|
return qemu_memalign(bdrv_opt_mem_align(bs), size);
|
|
}
|
|
}
|
|
|
|
|
|
void *qemu_blockalign0(BlockDriverState *bs, size_t size)
|
|
void *qemu_blockalign0(BlockDriverState *bs, size_t size)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return memset(qemu_blockalign(bs, size), 0, size);
|
|
return memset(qemu_blockalign(bs, size), 0, size);
|
|
}
|
|
}
|
|
|
|
|
|
void *qemu_try_blockalign(BlockDriverState *bs, size_t size)
|
|
void *qemu_try_blockalign(BlockDriverState *bs, size_t size)
|
|
{
|
|
{
|
|
size_t align = bdrv_opt_mem_align(bs);
|
|
size_t align = bdrv_opt_mem_align(bs);
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
/* Ensure that NULL is never returned on success */
|
|
/* Ensure that NULL is never returned on success */
|
|
assert(align > 0);
|
|
assert(align > 0);
|
|
@@ -3227,6 +3287,7 @@ void *qemu_try_blockalign(BlockDriverState *bs, size_t size)
|
|
void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
|
|
void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
|
|
{
|
|
{
|
|
void *mem = qemu_try_blockalign(bs, size);
|
|
void *mem = qemu_try_blockalign(bs, size);
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
if (mem) {
|
|
if (mem) {
|
|
memset(mem, 0, size);
|
|
memset(mem, 0, size);
|
|
@@ -3242,6 +3303,7 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
size_t alignment = bdrv_min_mem_align(bs);
|
|
size_t alignment = bdrv_min_mem_align(bs);
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
for (i = 0; i < qiov->niov; i++) {
|
|
for (i = 0; i < qiov->niov; i++) {
|
|
if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
|
|
if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
|
|
@@ -3258,6 +3320,7 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
|
void bdrv_io_plug(BlockDriverState *bs)
|
|
void bdrv_io_plug(BlockDriverState *bs)
|
|
{
|
|
{
|
|
BdrvChild *child;
|
|
BdrvChild *child;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
QLIST_FOREACH(child, &bs->children, next) {
|
|
QLIST_FOREACH(child, &bs->children, next) {
|
|
bdrv_io_plug(child->bs);
|
|
bdrv_io_plug(child->bs);
|
|
@@ -3274,6 +3337,7 @@ void bdrv_io_plug(BlockDriverState *bs)
|
|
void bdrv_io_unplug(BlockDriverState *bs)
|
|
void bdrv_io_unplug(BlockDriverState *bs)
|
|
{
|
|
{
|
|
BdrvChild *child;
|
|
BdrvChild *child;
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
assert(bs->io_plugged);
|
|
assert(bs->io_plugged);
|
|
if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
|
|
if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
|
|
@@ -3292,6 +3356,7 @@ void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size)
|
|
{
|
|
{
|
|
BdrvChild *child;
|
|
BdrvChild *child;
|
|
|
|
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
if (bs->drv && bs->drv->bdrv_register_buf) {
|
|
if (bs->drv && bs->drv->bdrv_register_buf) {
|
|
bs->drv->bdrv_register_buf(bs, host, size);
|
|
bs->drv->bdrv_register_buf(bs, host, size);
|
|
}
|
|
}
|
|
@@ -3304,6 +3369,7 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host)
|
|
{
|
|
{
|
|
BdrvChild *child;
|
|
BdrvChild *child;
|
|
|
|
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
if (bs->drv && bs->drv->bdrv_unregister_buf) {
|
|
if (bs->drv && bs->drv->bdrv_unregister_buf) {
|
|
bs->drv->bdrv_unregister_buf(bs, host);
|
|
bs->drv->bdrv_unregister_buf(bs, host);
|
|
}
|
|
}
|
|
@@ -3324,6 +3390,8 @@ static int coroutine_fn bdrv_co_copy_range_internal(
|
|
/* TODO We can support BDRV_REQ_NO_FALLBACK here */
|
|
/* TODO We can support BDRV_REQ_NO_FALLBACK here */
|
|
assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
|
|
assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
|
|
assert(!(write_flags & BDRV_REQ_NO_FALLBACK));
|
|
assert(!(write_flags & BDRV_REQ_NO_FALLBACK));
|
|
|
|
+ assert(!(read_flags & BDRV_REQ_NO_WAIT));
|
|
|
|
+ assert(!(write_flags & BDRV_REQ_NO_WAIT));
|
|
|
|
|
|
if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) {
|
|
if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) {
|
|
return -ENOMEDIUM;
|
|
return -ENOMEDIUM;
|
|
@@ -3398,6 +3466,7 @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
|
|
BdrvRequestFlags read_flags,
|
|
BdrvRequestFlags read_flags,
|
|
BdrvRequestFlags write_flags)
|
|
BdrvRequestFlags write_flags)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
|
|
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
|
|
read_flags, write_flags);
|
|
read_flags, write_flags);
|
|
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
|
|
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
|
|
@@ -3414,6 +3483,7 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
|
|
BdrvRequestFlags read_flags,
|
|
BdrvRequestFlags read_flags,
|
|
BdrvRequestFlags write_flags)
|
|
BdrvRequestFlags write_flags)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
|
|
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
|
|
read_flags, write_flags);
|
|
read_flags, write_flags);
|
|
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
|
|
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
|
|
@@ -3425,6 +3495,7 @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
|
|
int64_t bytes, BdrvRequestFlags read_flags,
|
|
int64_t bytes, BdrvRequestFlags read_flags,
|
|
BdrvRequestFlags write_flags)
|
|
BdrvRequestFlags write_flags)
|
|
{
|
|
{
|
|
|
|
+ IO_CODE();
|
|
return bdrv_co_copy_range_from(src, src_offset,
|
|
return bdrv_co_copy_range_from(src, src_offset,
|
|
dst, dst_offset,
|
|
dst, dst_offset,
|
|
bytes, read_flags, write_flags);
|
|
bytes, read_flags, write_flags);
|
|
@@ -3457,7 +3528,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
|
|
BdrvTrackedRequest req;
|
|
BdrvTrackedRequest req;
|
|
int64_t old_size, new_bytes;
|
|
int64_t old_size, new_bytes;
|
|
int ret;
|
|
int ret;
|
|
-
|
|
|
|
|
|
+ IO_CODE();
|
|
|
|
|
|
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
|
|
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
|
|
if (!drv) {
|
|
if (!drv) {
|
|
@@ -3575,6 +3646,7 @@ out:
|
|
|
|
|
|
void bdrv_cancel_in_flight(BlockDriverState *bs)
|
|
void bdrv_cancel_in_flight(BlockDriverState *bs)
|
|
{
|
|
{
|
|
|
|
+ GLOBAL_STATE_CODE();
|
|
if (!bs || !bs->drv) {
|
|
if (!bs || !bs->drv) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -3583,3 +3655,75 @@ void bdrv_cancel_in_flight(BlockDriverState *bs)
|
|
bs->drv->bdrv_cancel_in_flight(bs);
|
|
bs->drv->bdrv_cancel_in_flight(bs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+int coroutine_fn
|
|
|
|
+bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes,
|
|
|
|
+ QEMUIOVector *qiov, size_t qiov_offset)
|
|
|
|
+{
|
|
|
|
+ BlockDriverState *bs = child->bs;
|
|
|
|
+ BlockDriver *drv = bs->drv;
|
|
|
|
+ int ret;
|
|
|
|
+ IO_CODE();
|
|
|
|
+
|
|
|
|
+ if (!drv) {
|
|
|
|
+ return -ENOMEDIUM;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!drv->bdrv_co_preadv_snapshot) {
|
|
|
|
+ return -ENOTSUP;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bdrv_inc_in_flight(bs);
|
|
|
|
+ ret = drv->bdrv_co_preadv_snapshot(bs, offset, bytes, qiov, qiov_offset);
|
|
|
|
+ bdrv_dec_in_flight(bs);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int coroutine_fn
|
|
|
|
+bdrv_co_snapshot_block_status(BlockDriverState *bs,
|
|
|
|
+ bool want_zero, int64_t offset, int64_t bytes,
|
|
|
|
+ int64_t *pnum, int64_t *map,
|
|
|
|
+ BlockDriverState **file)
|
|
|
|
+{
|
|
|
|
+ BlockDriver *drv = bs->drv;
|
|
|
|
+ int ret;
|
|
|
|
+ IO_CODE();
|
|
|
|
+
|
|
|
|
+ if (!drv) {
|
|
|
|
+ return -ENOMEDIUM;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!drv->bdrv_co_snapshot_block_status) {
|
|
|
|
+ return -ENOTSUP;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bdrv_inc_in_flight(bs);
|
|
|
|
+ ret = drv->bdrv_co_snapshot_block_status(bs, want_zero, offset, bytes,
|
|
|
|
+ pnum, map, file);
|
|
|
|
+ bdrv_dec_in_flight(bs);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int coroutine_fn
|
|
|
|
+bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
|
|
|
|
+{
|
|
|
|
+ BlockDriver *drv = bs->drv;
|
|
|
|
+ int ret;
|
|
|
|
+ IO_CODE();
|
|
|
|
+
|
|
|
|
+ if (!drv) {
|
|
|
|
+ return -ENOMEDIUM;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!drv->bdrv_co_pdiscard_snapshot) {
|
|
|
|
+ return -ENOTSUP;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bdrv_inc_in_flight(bs);
|
|
|
|
+ ret = drv->bdrv_co_pdiscard_snapshot(bs, offset, bytes);
|
|
|
|
+ bdrv_dec_in_flight(bs);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|