aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2014-06-20 21:57:33 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2014-08-29 10:48:45 +0100
commit33384421b3abe74555baeaf788b17204cd8c6080 (patch)
tree15a02040c856cabb6d1916d4d2d4bff6f0916a74 /block.c
parent958c717df97ea9ca47a2253b8371130fe5f22980 (diff)
block: Add AIO context notifiers
If a long-running operation on a BDS wants to always remain in the same AIO context, it somehow needs to keep track of the BDS changing its context. This adds a function for registering callbacks on a BDS which are called whenever the BDS is attached or detached from an AIO context. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block.c')
-rw-r--r--block.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/block.c b/block.c
index 1df13ac1c7..9c5566b55b 100644
--- a/block.c
+++ b/block.c
@@ -1819,6 +1819,8 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
void bdrv_close(BlockDriverState *bs)
{
+ BdrvAioNotifier *ban, *ban_next;
+
if (bs->job) {
block_job_cancel_sync(bs->job);
}
@@ -1863,6 +1865,11 @@ void bdrv_close(BlockDriverState *bs)
if (bs->io_limits_enabled) {
bdrv_io_limits_disable(bs);
}
+
+ QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
+ g_free(ban);
+ }
+ QLIST_INIT(&bs->aio_notifiers);
}
void bdrv_close_all(void)
@@ -5729,10 +5736,16 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
void bdrv_detach_aio_context(BlockDriverState *bs)
{
+ BdrvAioNotifier *baf;
+
if (!bs->drv) {
return;
}
+ QLIST_FOREACH(baf, &bs->aio_notifiers, list) {
+ baf->detach_aio_context(baf->opaque);
+ }
+
if (bs->io_limits_enabled) {
throttle_detach_aio_context(&bs->throttle_state);
}
@@ -5752,6 +5765,8 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
void bdrv_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
+ BdrvAioNotifier *ban;
+
if (!bs->drv) {
return;
}
@@ -5770,6 +5785,10 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
if (bs->io_limits_enabled) {
throttle_attach_aio_context(&bs->throttle_state, new_context);
}
+
+ QLIST_FOREACH(ban, &bs->aio_notifiers, list) {
+ ban->attached_aio_context(new_context, ban->opaque);
+ }
}
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
@@ -5786,6 +5805,43 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
aio_context_release(new_context);
}
+void bdrv_add_aio_context_notifier(BlockDriverState *bs,
+ void (*attached_aio_context)(AioContext *new_context, void *opaque),
+ void (*detach_aio_context)(void *opaque), void *opaque)
+{
+ BdrvAioNotifier *ban = g_new(BdrvAioNotifier, 1);
+ *ban = (BdrvAioNotifier){
+ .attached_aio_context = attached_aio_context,
+ .detach_aio_context = detach_aio_context,
+ .opaque = opaque
+ };
+
+ QLIST_INSERT_HEAD(&bs->aio_notifiers, ban, list);
+}
+
+void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
+ void (*attached_aio_context)(AioContext *,
+ void *),
+ void (*detach_aio_context)(void *),
+ void *opaque)
+{
+ BdrvAioNotifier *ban, *ban_next;
+
+ QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
+ if (ban->attached_aio_context == attached_aio_context &&
+ ban->detach_aio_context == detach_aio_context &&
+ ban->opaque == opaque)
+ {
+ QLIST_REMOVE(ban, list);
+ g_free(ban);
+
+ return;
+ }
+ }
+
+ abort();
+}
+
void bdrv_add_before_write_notifier(BlockDriverState *bs,
NotifierWithReturn *notifier)
{