mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 05:20:50 +00:00
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: Eric Blake <eblake@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
5dae8e5fb8
commit
d616b22474
23
block.c
23
block.c
@ -305,6 +305,7 @@ BlockDriverState *bdrv_new(const char *device_name)
|
||||
}
|
||||
bdrv_iostatus_disable(bs);
|
||||
notifier_list_init(&bs->close_notifiers);
|
||||
notifier_with_return_list_init(&bs->before_write_notifiers);
|
||||
|
||||
return bs;
|
||||
}
|
||||
@ -1840,16 +1841,6 @@ int bdrv_commit_all(void)
|
||||
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
|
||||
*
|
||||
@ -2620,7 +2611,11 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
|
||||
|
||||
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);
|
||||
} else {
|
||||
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
|
||||
@ -4581,3 +4576,9 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
|
||||
/* Currently BlockDriverState always uses the main loop AioContext */
|
||||
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 @@
|
||||
#define BLOCK_OPT_LAZY_REFCOUNTS "lazy_refcounts"
|
||||
#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 {
|
||||
int64_t bps[3];
|
||||
@ -248,6 +257,9 @@ struct BlockDriverState {
|
||||
|
||||
NotifierList close_notifiers;
|
||||
|
||||
/* Callback before write request is processed */
|
||||
NotifierWithReturnList before_write_notifiers;
|
||||
|
||||
/* number of in-flight copy-on-read requests */
|
||||
unsigned int copy_on_read_in_flight;
|
||||
|
||||
@ -298,6 +310,15 @@ int get_tmp_filename(char *filename, int size);
|
||||
void bdrv_set_io_limits(BlockDriverState *bs,
|
||||
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:
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user