提交 d616b224 编写于 作者: S Stefan Hajnoczi 提交者: Kevin Wolf

block: add bdrv_add_before_write_notifier()

The bdrv_add_before_write_notifier() function installs a callback that
is invoked before a write request is processed.  This will be used to
implement copy-on-write point-in-time snapshots where we need to copy
out old data before overwriting it.

Note that BdrvTrackedRequest is moved to block_int.h since it is passed
to .notify() functions.
Reviewed-by: NEric Blake <eblake@redhat.com>
Reviewed-by: NKevin Wolf <kwolf@redhat.com>
Signed-off-by: NStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: NKevin Wolf <kwolf@redhat.com>
上级 5dae8e5f
...@@ -305,6 +305,7 @@ BlockDriverState *bdrv_new(const char *device_name) ...@@ -305,6 +305,7 @@ BlockDriverState *bdrv_new(const char *device_name)
} }
bdrv_iostatus_disable(bs); bdrv_iostatus_disable(bs);
notifier_list_init(&bs->close_notifiers); notifier_list_init(&bs->close_notifiers);
notifier_with_return_list_init(&bs->before_write_notifiers);
return bs; return bs;
} }
...@@ -1840,16 +1841,6 @@ int bdrv_commit_all(void) ...@@ -1840,16 +1841,6 @@ int bdrv_commit_all(void)
return 0; return 0;
} }
struct BdrvTrackedRequest {
BlockDriverState *bs;
int64_t sector_num;
int nb_sectors;
bool is_write;
QLIST_ENTRY(BdrvTrackedRequest) list;
Coroutine *co; /* owner, used for deadlock detection */
CoQueue wait_queue; /* coroutines blocked on this request */
};
/** /**
* Remove an active request from the tracked requests list * Remove an active request from the tracked requests list
* *
...@@ -2620,7 +2611,11 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, ...@@ -2620,7 +2611,11 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
tracked_request_begin(&req, bs, sector_num, nb_sectors, true); tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
if (flags & BDRV_REQ_ZERO_WRITE) { ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req);
if (ret < 0) {
/* Do nothing, write notifier decided to fail this request */
} else if (flags & BDRV_REQ_ZERO_WRITE) {
ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors); ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors);
} else { } else {
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov); ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
...@@ -4581,3 +4576,9 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs) ...@@ -4581,3 +4576,9 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
/* Currently BlockDriverState always uses the main loop AioContext */ /* Currently BlockDriverState always uses the main loop AioContext */
return qemu_get_aio_context(); return qemu_get_aio_context();
} }
void bdrv_add_before_write_notifier(BlockDriverState *bs,
NotifierWithReturn *notifier)
{
notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
}
...@@ -59,7 +59,16 @@ ...@@ -59,7 +59,16 @@
#define BLOCK_OPT_LAZY_REFCOUNTS "lazy_refcounts" #define BLOCK_OPT_LAZY_REFCOUNTS "lazy_refcounts"
#define BLOCK_OPT_ADAPTER_TYPE "adapter_type" #define BLOCK_OPT_ADAPTER_TYPE "adapter_type"
typedef struct BdrvTrackedRequest BdrvTrackedRequest; typedef struct BdrvTrackedRequest {
BlockDriverState *bs;
int64_t sector_num;
int nb_sectors;
bool is_write;
QLIST_ENTRY(BdrvTrackedRequest) list;
Coroutine *co; /* owner, used for deadlock detection */
CoQueue wait_queue; /* coroutines blocked on this request */
} BdrvTrackedRequest;
typedef struct BlockIOLimit { typedef struct BlockIOLimit {
int64_t bps[3]; int64_t bps[3];
...@@ -248,6 +257,9 @@ struct BlockDriverState { ...@@ -248,6 +257,9 @@ struct BlockDriverState {
NotifierList close_notifiers; NotifierList close_notifiers;
/* Callback before write request is processed */
NotifierWithReturnList before_write_notifiers;
/* number of in-flight copy-on-read requests */ /* number of in-flight copy-on-read requests */
unsigned int copy_on_read_in_flight; unsigned int copy_on_read_in_flight;
...@@ -298,6 +310,15 @@ int get_tmp_filename(char *filename, int size); ...@@ -298,6 +310,15 @@ int get_tmp_filename(char *filename, int size);
void bdrv_set_io_limits(BlockDriverState *bs, void bdrv_set_io_limits(BlockDriverState *bs,
BlockIOLimit *io_limits); BlockIOLimit *io_limits);
/**
* bdrv_add_before_write_notifier:
*
* Register a callback that is invoked before write requests are processed but
* after any throttling or waiting for overlapping requests.
*/
void bdrv_add_before_write_notifier(BlockDriverState *bs,
NotifierWithReturn *notifier);
/** /**
* bdrv_get_aio_context: * bdrv_get_aio_context:
* *
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册