[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 02/62] block: Add AIO context notifiers
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PULL 02/62] block: Add AIO context notifiers |
Date: |
Fri, 8 Aug 2014 19:39:03 +0200 |
From: Max Reitz <address@hidden>
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 <address@hidden>
Reviewed-by: Stefan Hajnoczi <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
---
block.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
include/block/block_int.h | 41 ++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+)
diff --git a/block.c b/block.c
index 8cf519b..9fa58fd 100644
--- a/block.c
+++ b/block.c
@@ -1814,6 +1814,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);
}
@@ -1856,6 +1858,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)
@@ -5658,10 +5665,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);
}
@@ -5681,6 +5694,8 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
void bdrv_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
+ BdrvAioNotifier *ban;
+
if (!bs->drv) {
return;
}
@@ -5699,6 +5714,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)
@@ -5715,6 +5734,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)
{
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 7b541a0..b916769 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -291,6 +291,15 @@ typedef struct BlockLimits {
typedef struct BdrvOpBlocker BdrvOpBlocker;
+typedef struct BdrvAioNotifier {
+ void (*attached_aio_context)(AioContext *new_context, void *opaque);
+ void (*detach_aio_context)(void *opaque);
+
+ void *opaque;
+
+ QLIST_ENTRY(BdrvAioNotifier) list;
+} BdrvAioNotifier;
+
/*
* Note: the function bdrv_append() copies and swaps contents of
* BlockDriverStates, so if you add new fields to this struct, please
@@ -317,6 +326,10 @@ struct BlockDriverState {
void *dev_opaque;
AioContext *aio_context; /* event loop used for fd handlers, timers, etc */
+ /* long-running tasks intended to always use the same AioContext as this
+ * BDS may register themselves in this list to be notified of changes
+ * regarding this BDS's context */
+ QLIST_HEAD(, BdrvAioNotifier) aio_notifiers;
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
@@ -431,6 +444,34 @@ void bdrv_detach_aio_context(BlockDriverState *bs);
void bdrv_attach_aio_context(BlockDriverState *bs,
AioContext *new_context);
+/**
+ * bdrv_add_aio_context_notifier:
+ *
+ * If a long-running job intends to be always run in the same AioContext as a
+ * certain BDS, it may use this function to be notified of changes regarding
the
+ * association of the BDS to an AioContext.
+ *
+ * attached_aio_context() is called after the target BDS has been attached to a
+ * new AioContext; detach_aio_context() is called before the target BDS is
being
+ * detached from its old AioContext.
+ */
+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);
+
+/**
+ * bdrv_remove_aio_context_notifier:
+ *
+ * Unsubscribe of change notifications regarding the BDS's AioContext. The
+ * parameters given here have to be the same as those given to
+ * bdrv_add_aio_context_notifier().
+ */
+void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
+ void (*aio_context_attached)(AioContext
*,
+ void *),
+ void (*aio_context_detached)(void *),
+ void *opaque);
+
#ifdef _WIN32
int is_windows_drive(const char *filename);
#endif
--
1.8.3.1
- [Qemu-devel] [PULL 00/62] Block patches, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 01/62] nbd: Drop nbd_can_read(), Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 04/62] block: New bdrv_nb_sectors(), Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 02/62] block: Add AIO context notifiers,
Kevin Wolf <=
- [Qemu-devel] [PULL 05/62] block: Use bdrv_nb_sectors() in bdrv_make_zero(), Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 06/62] block: Use bdrv_nb_sectors() in bdrv_aligned_preadv(), Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 03/62] nbd: Follow the BDS' AIO context, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 07/62] block: Use bdrv_nb_sectors() in bdrv_co_get_block_status(), Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 08/62] block: Use bdrv_nb_sectors() in img_convert(), Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 09/62] block: Use bdrv_nb_sectors() where sectors, not bytes are wanted, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 10/62] block: Drop superfluous aligning of bdrv_getlength()'s value, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 11/62] qemu-img: Make img_convert() get image size just once per image, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 12/62] block: Avoid bdrv_get_geometry() where errors should be detected, Kevin Wolf, 2014/08/08
- [Qemu-devel] [PULL 14/62] configure: explicitly state version requirements to devel packages, Kevin Wolf, 2014/08/08