qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Max Reitz <mreitz@redhat.com>
To: Fam Zheng <famz@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
	qemu-block@nongnu.org, qemu-devel@nongnu.org,
	Markus Armbruster <armbru@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v3 05/11] block: Move BDS close notifiers into BB
Date: Wed, 25 Feb 2015 09:12:22 -0500	[thread overview]
Message-ID: <54EDD846.5030509@redhat.com> (raw)
In-Reply-To: <20150225075232.GH5293@ad.nay.redhat.com>

On 2015-02-25 at 02:52, Fam Zheng wrote:
> On Tue, 02/24 10:35, Max Reitz wrote:
>> The only remaining user of the BDS close notifiers is NBD which uses
>> them to determine when a BDS tree is being ejected. This patch removes
>> the BDS-level close notifiers and adds a notifier list to the
>> BlockBackend structure that is invoked whenever a BDS is removed.
>>
>> Symmetrically to that, another notifier list is added that is invoked
>> whenever a BDS is inserted. The dataplane implementations for virtio-blk
>> and virtio-scsi use both notifier types for setting up and removing op
>> blockers. This is not only important for setting up the op blockers on
>> insertion, but also for removing them on ejection since bdrv_delete()
>> asserts that there are no op blockers set up.
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   block.c                         |  7 ----
>>   block/block-backend.c           | 19 +++++++--
>>   blockdev-nbd.c                  | 36 +---------------
>>   hw/block/dataplane/virtio-blk.c | 93 +++++++++++++++++++++++++++++++++--------
>>   hw/scsi/virtio-scsi.c           | 64 ++++++++++++++++++++++++----
>>   include/block/block.h           |  1 -
>>   include/block/block_int.h       |  2 -
>>   include/hw/virtio/virtio-scsi.h |  8 ++++
>>   include/sysemu/block-backend.h  |  3 +-
>>   nbd.c                           | 35 ++++++++++++++++
>>   10 files changed, 193 insertions(+), 75 deletions(-)
>>
>> diff --git a/block.c b/block.c
>> index 7b912c6..41a9d24 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -371,7 +371,6 @@ BlockDriverState *bdrv_new(void)
>>       for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
>>           QLIST_INIT(&bs->op_blockers[i]);
>>       }
>> -    notifier_list_init(&bs->close_notifiers);
>>       notifier_with_return_list_init(&bs->before_write_notifiers);
>>       qemu_co_queue_init(&bs->throttled_reqs[0]);
>>       qemu_co_queue_init(&bs->throttled_reqs[1]);
>> @@ -381,11 +380,6 @@ BlockDriverState *bdrv_new(void)
>>       return bs;
>>   }
>>   
>> -void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify)
>> -{
>> -    notifier_list_add(&bs->close_notifiers, notify);
>> -}
>> -
>>   BlockDriver *bdrv_find_format(const char *format_name)
>>   {
>>       BlockDriver *drv1;
>> @@ -1898,7 +1892,6 @@ void bdrv_close(BlockDriverState *bs)
>>       bdrv_drain_all(); /* complete I/O */
>>       bdrv_flush(bs);
>>       bdrv_drain_all(); /* in case flush left pending I/O */
>> -    notifier_list_notify(&bs->close_notifiers, bs);
>>   
>>       if (bs->drv) {
>>           if (bs->backing_hd) {
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> index 82ced04..254fde4 100644
>> --- a/block/block-backend.c
>> +++ b/block/block-backend.c
>> @@ -47,6 +47,8 @@ struct BlockBackend {
>>       BlockdevOnError on_read_error, on_write_error;
>>       bool iostatus_enabled;
>>       BlockDeviceIoStatus iostatus;
>> +
>> +    NotifierList remove_bs_notifiers, insert_bs_notifiers;
>
>>   };
>>   
>>   typedef struct BlockBackendAIOCB {
>> @@ -97,6 +99,8 @@ BlockBackend *blk_new(const char *name, Error **errp)
>>       blk = g_new0(BlockBackend, 1);
>>       blk->name = g_strdup(name);
>>       blk->refcnt = 1;
>> +    notifier_list_init(&blk->remove_bs_notifiers);
>> +    notifier_list_init(&blk->insert_bs_notifiers);
>>       QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
>>       return blk;
>>   }
>> @@ -320,6 +324,8 @@ void blk_remove_bs(BlockBackend *blk)
>>           return;
>>       }
>>   
>> +    notifier_list_notify(&blk->remove_bs_notifiers, blk);
>> +
>>       blk_update_root_state(blk);
>>   
>>       bdrv_unref(blk->bs);
>> @@ -345,6 +351,8 @@ void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
>>       }
>>   
>>       bs->blk = blk;
>> +
>> +    notifier_list_notify(&blk->insert_bs_notifiers, blk);
>>   }
>>   
>>   /*
>> @@ -1067,11 +1075,14 @@ void blk_remove_aio_context_notifier(BlockBackend *blk,
>>       }
>>   }
>>   
>> -void blk_add_close_notifier(BlockBackend *blk, Notifier *notify)
>> +void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
>>   {
>> -    if (blk->bs) {
>> -        bdrv_add_close_notifier(blk->bs, notify);
>> -    }
>> +    notifier_list_add(&blk->remove_bs_notifiers, notify);
>> +}
>> +
>> +void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
>> +{
>> +    notifier_list_add(&blk->insert_bs_notifiers, notify);
>>   }
>>   
>>   void blk_io_plug(BlockBackend *blk)
>> diff --git a/blockdev-nbd.c b/blockdev-nbd.c
>> index 22e95d1..eb5f9a0 100644
>> --- a/blockdev-nbd.c
>> +++ b/blockdev-nbd.c
>> @@ -47,36 +47,11 @@ void qmp_nbd_server_start(SocketAddress *addr, Error **errp)
>>       }
>>   }
>>   
>> -/* Hook into the BlockDriverState notifiers to close the export when
>> - * the file is closed.
>> - */
>> -typedef struct NBDCloseNotifier {
>> -    Notifier n;
>> -    NBDExport *exp;
>> -    QTAILQ_ENTRY(NBDCloseNotifier) next;
>> -} NBDCloseNotifier;
>> -
>> -static QTAILQ_HEAD(, NBDCloseNotifier) close_notifiers =
>> -    QTAILQ_HEAD_INITIALIZER(close_notifiers);
>> -
>> -static void nbd_close_notifier(Notifier *n, void *data)
>> -{
>> -    NBDCloseNotifier *cn = DO_UPCAST(NBDCloseNotifier, n, n);
>> -
>> -    notifier_remove(&cn->n);
>> -    QTAILQ_REMOVE(&close_notifiers, cn, next);
>> -
>> -    nbd_export_close(cn->exp);
>> -    nbd_export_put(cn->exp);
>> -    g_free(cn);
>> -}
>> -
>>   void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
>>                           Error **errp)
>>   {
>>       BlockBackend *blk;
>>       NBDExport *exp;
>> -    NBDCloseNotifier *n;
>>   
>>       if (server_fd == -1) {
>>           error_setg(errp, "NBD server not running");
>> @@ -108,20 +83,11 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
>>       exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL);
>>   
>>       nbd_export_set_name(exp, device);
>> -
>> -    n = g_new0(NBDCloseNotifier, 1);
>> -    n->n.notify = nbd_close_notifier;
>> -    n->exp = exp;
>> -    blk_add_close_notifier(blk, &n->n);
>> -    QTAILQ_INSERT_TAIL(&close_notifiers, n, next);
>>   }
>>   
>>   void qmp_nbd_server_stop(Error **errp)
>>   {
>> -    while (!QTAILQ_EMPTY(&close_notifiers)) {
>> -        NBDCloseNotifier *cn = QTAILQ_FIRST(&close_notifiers);
>> -        nbd_close_notifier(&cn->n, nbd_export_get_blockdev(cn->exp));
>> -    }
>> +    nbd_export_close_all();
>>   
>>       if (server_fd != -1) {
>>           qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL);
>> diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
>> index cd41478..4cd1e45 100644
>> --- a/hw/block/dataplane/virtio-blk.c
>> +++ b/hw/block/dataplane/virtio-blk.c
>> @@ -26,6 +26,8 @@
>>   #include "hw/virtio/virtio-bus.h"
>>   #include "qom/object_interfaces.h"
>>   
>> +typedef struct DataPlaneBlkChangeNotifier DataPlaneBlkChangeNotifier;
>> +
>>   struct VirtIOBlockDataPlane {
>>       bool started;
>>       bool starting;
>> @@ -39,6 +41,8 @@ struct VirtIOBlockDataPlane {
>>       EventNotifier *guest_notifier;  /* irq */
>>       QEMUBH *bh;                     /* bh for guest notification */
>>   
>> +    DataPlaneBlkChangeNotifier *insert_notifier, *remove_notifier;
>> +
> Bikeshedding, but why not just embed these fields?

Because I need a Notifier pointer to give to 
blk_add_{insert,remove}_bs_notifier(), and most importantly because the 
only "opaque" object the callbacks will receive is that Notifier pointer 
(which in this case is actually a DataPlaneBlkChangeNotifier pointer). I 
cannot influence the @data parameter, and I cannot (easily) identify the 
VirtIOBlockDataPlane object from the BlockBackend (which is @data) alone.

>>       /* Note that these EventNotifiers are assigned by value.  This is
>>        * fine as long as you do not call event_notifier_cleanup on them
>>        * (because you don't own the file descriptor or handle; you just
>> @@ -55,6 +59,11 @@ struct VirtIOBlockDataPlane {
>>                                      unsigned char status);
>>   };
>>   
>> +struct DataPlaneBlkChangeNotifier {
>> +    Notifier n;
>> +    VirtIOBlockDataPlane *s;
>> +};
>> +
>>   /* Raise an interrupt to signal guest, if necessary */
>>   static void notify_guest(VirtIOBlockDataPlane *s)
>>   {
>> @@ -138,6 +147,54 @@ static void handle_notify(EventNotifier *e)
>>       blk_io_unplug(s->conf->conf.blk);
>>   }
>>   
>> +static void data_plane_set_up_op_blockers(VirtIOBlockDataPlane *s)
>> +{
>> +    assert(!s->blocker);
>> +    error_setg(&s->blocker, "block device is in use by data plane");
>> +    blk_op_block_all(s->conf->conf.blk, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_SOURCE, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_TARGET, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
>> +                   s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT,
>> +                   s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
>> +                   s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_MIRROR, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker);
>> +    blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker);
>> +}
>> +
>> +static void data_plane_remove_op_blockers(VirtIOBlockDataPlane *s)
>> +{
>> +    if (s->blocker) {
>> +        blk_op_unblock_all(s->conf->conf.blk, s->blocker);
>> +        error_free(s->blocker);
>> +        s->blocker = NULL;
>> +    }
>> +}
>> +
>> +static void data_plane_blk_insert_notifier(Notifier *n, void *data)
>> +{
>> +    DataPlaneBlkChangeNotifier *cn = DO_UPCAST(DataPlaneBlkChangeNotifier,
>> +                                               n, n);
>> +    assert(cn->s->conf->conf.blk == data);
>> +    data_plane_set_up_op_blockers(cn->s);
>> +}
>> +
>> +static void data_plane_blk_remove_notifier(Notifier *n, void *data)
>> +{
>> +    DataPlaneBlkChangeNotifier *cn = DO_UPCAST(DataPlaneBlkChangeNotifier,
>> +                                               n, n);
>> +    assert(cn->s->conf->conf.blk == data);
>> +    data_plane_remove_op_blockers(cn->s);
>> +}
>> +
>>   /* Context: QEMU global mutex held */
>>   void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
>>                                     VirtIOBlockDataPlane **dataplane,
>> @@ -194,22 +251,17 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
>>       s->ctx = iothread_get_aio_context(s->iothread);
>>       s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
>>   
>> -    error_setg(&s->blocker, "block device is in use by data plane");
>> -    blk_op_block_all(conf->conf.blk, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT_SOURCE, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT_TARGET, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
>> -                   s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_MIRROR, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker);
>> -    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker);
>> +    s->insert_notifier = g_new0(DataPlaneBlkChangeNotifier, 1);
>> +    s->insert_notifier->n.notify = data_plane_blk_insert_notifier;
>> +    s->insert_notifier->s = s;
>> +    blk_add_insert_bs_notifier(conf->conf.blk, &s->insert_notifier->n);
>> +
>> +    s->remove_notifier = g_new0(DataPlaneBlkChangeNotifier, 1);
>> +    s->remove_notifier->n.notify = data_plane_blk_remove_notifier;
>> +    s->remove_notifier->s = s;
>> +    blk_add_remove_bs_notifier(conf->conf.blk, &s->remove_notifier->n);
>> +
>> +    data_plane_set_up_op_blockers(s);
>>   
>>       *dataplane = s;
>>   }
>> @@ -222,10 +274,15 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
>>       }
>>   
>>       virtio_blk_data_plane_stop(s);
>> -    blk_op_unblock_all(s->conf->conf.blk, s->blocker);
>> -    error_free(s->blocker);
>> +    data_plane_remove_op_blockers(s);
>>       object_unref(OBJECT(s->iothread));
>>       qemu_bh_delete(s->bh);
>> +
>> +    notifier_remove(&s->insert_notifier->n);
>> +    notifier_remove(&s->remove_notifier->n);
>> +    g_free(s->insert_notifier);
>> +    g_free(s->remove_notifier);
>> +
>>       g_free(s);
>>   }
>>   
>> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
>> index 5469bad..0033862 100644
>> --- a/hw/scsi/virtio-scsi.c
>> +++ b/hw/scsi/virtio-scsi.c
>> @@ -755,6 +755,38 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
>>       }
>>   }
>>   
>> +static void virtio_scsi_set_up_op_blockers(VirtIOSCSI *s, SCSIDevice *sd)
>> +{
>> +    assert(!s->blocker);
>> +    error_setg(&s->blocker, "block device is in use by data plane");
>> +    blk_op_block_all(sd->conf.blk, s->blocker);
>> +}
>> +
>> +static void virtio_scsi_remove_op_blockers(VirtIOSCSI *s, SCSIDevice *sd)
>> +{
>> +    if (s->blocker) {
>> +        blk_op_unblock_all(sd->conf.blk, s->blocker);
>> +        error_free(s->blocker);
>> +        s->blocker = NULL;
>> +    }
>> +}
>> +
>> +static void virtio_scsi_blk_insert_notifier(Notifier *n, void *data)
>> +{
>> +    VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
>> +                                                n, n);
>> +    assert(cn->sd->conf.blk == data);
>> +    virtio_scsi_set_up_op_blockers(cn->s, cn->sd);
>> +}
>> +
>> +static void virtio_scsi_blk_remove_notifier(Notifier *n, void *data)
>> +{
>> +    VirtIOSCSIBlkChangeNotifier *cn = DO_UPCAST(VirtIOSCSIBlkChangeNotifier,
>> +                                                n, n);
>> +    assert(cn->sd->conf.blk == data);
>> +    virtio_scsi_remove_op_blockers(cn->s, cn->sd);
>> +}
>> +
>>   static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
>>                                   Error **errp)
>>   {
>> @@ -763,12 +795,22 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
>>       SCSIDevice *sd = SCSI_DEVICE(dev);
>>   
>>       if (s->ctx && !s->dataplane_disabled) {
>> +        s->insert_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
> We leak the first s->insert_notifier when a second device is plugged. Probably
> you can just embed these in SCSIDevice.

Won't virtio_scsi_hotunplug() (which frees s->{insert,remove}_notifier) 
be called before a second device is plugged?

>> +        s->insert_notifier->n.notify = virtio_scsi_blk_insert_notifier;
>> +        s->insert_notifier->s = s;
>> +        s->insert_notifier->sd = sd;
>> +        blk_add_insert_bs_notifier(sd->conf.blk, &s->insert_notifier->n);
>> +
>> +        s->remove_notifier = g_new0(VirtIOSCSIBlkChangeNotifier, 1);
>> +        s->remove_notifier->n.notify = virtio_scsi_blk_remove_notifier;
>> +        s->remove_notifier->s = s;
>> +        s->remove_notifier->sd = sd;
>> +        blk_add_remove_bs_notifier(sd->conf.blk, &s->remove_notifier->n);
>> +
>>           if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
>>               return;
>>           }
>> -        assert(!s->blocker);
>> -        error_setg(&s->blocker, "block device is in use by data plane");
>> -        blk_op_block_all(sd->conf.blk, s->blocker);
>> +        virtio_scsi_set_up_op_blockers(s, sd);
>>       }
>>   
>>       if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
>> @@ -791,10 +833,18 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
>>                                  VIRTIO_SCSI_EVT_RESET_REMOVED);
>>       }
>>   
>> -    if (s->ctx && s->blocker) {
>> -        blk_op_unblock_all(sd->conf.blk, s->blocker);
>> -        error_free(s->blocker);
>> -        s->blocker = NULL;
>> +    if (s->ctx) {
>> +        virtio_scsi_remove_op_blockers(s, sd);
>> +    }
>> +    if (s->insert_notifier) {
>> +        notifier_remove(&s->insert_notifier->n);
>> +        g_free(s->insert_notifier);
>> +        s->insert_notifier = NULL;
>> +    }
>> +    if (s->remove_notifier) {
>> +        notifier_remove(&s->remove_notifier->n);
>> +        g_free(s->remove_notifier);
>> +        s->remove_notifier = NULL;
>>       }
>>       qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
>>   }
>> diff --git a/include/block/block.h b/include/block/block.h
>> index 1422f01..dc94084 100644
>> --- a/include/block/block.h
>> +++ b/include/block/block.h
>> @@ -207,7 +207,6 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
>>   void bdrv_reopen_commit(BDRVReopenState *reopen_state);
>>   void bdrv_reopen_abort(BDRVReopenState *reopen_state);
>>   void bdrv_close(BlockDriverState *bs);
>> -void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify);
>>   int bdrv_read(BlockDriverState *bs, int64_t sector_num,
>>                 uint8_t *buf, int nb_sectors);
>>   int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
>> diff --git a/include/block/block_int.h b/include/block/block_int.h
>> index 8fcfc29..b2c1d87 100644
>> --- a/include/block/block_int.h
>> +++ b/include/block/block_int.h
>> @@ -367,8 +367,6 @@ struct BlockDriverState {
>>       BlockDriverState *backing_hd;
>>       BlockDriverState *file;
>>   
>> -    NotifierList close_notifiers;
>> -
>>       /* Callback before write request is processed */
>>       NotifierWithReturnList before_write_notifiers;
>>   
>> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
>> index bf17cc9..723cc42 100644
>> --- a/include/hw/virtio/virtio-scsi.h
>> +++ b/include/hw/virtio/virtio-scsi.h
>> @@ -176,6 +176,12 @@ typedef struct VirtIOSCSICommon {
>>       VirtQueue **cmd_vqs;
>>   } VirtIOSCSICommon;
>>   
>> +typedef struct VirtIOSCSIBlkChangeNotifier {
>> +    Notifier n;
>> +    struct VirtIOSCSI *s;
>> +    SCSIDevice *sd;
>> +} VirtIOSCSIBlkChangeNotifier;
>> +
>>   typedef struct VirtIOSCSI {
>>       VirtIOSCSICommon parent_obj;
>>   
>> @@ -186,6 +192,8 @@ typedef struct VirtIOSCSI {
>>       /* Fields for dataplane below */
>>       AioContext *ctx; /* one iothread per virtio-scsi-pci for now */
>>   
>> +    VirtIOSCSIBlkChangeNotifier *insert_notifier, *remove_notifier;
>> +
>>       /* Vring is used instead of vq in dataplane code, because of the underlying
>>        * memory layer thread safety */
>>       VirtIOSCSIVring *ctrl_vring;
>> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
>> index 3aad010..e0a2749 100644
>> --- a/include/sysemu/block-backend.h
>> +++ b/include/sysemu/block-backend.h
>> @@ -158,7 +158,8 @@ void blk_remove_aio_context_notifier(BlockBackend *blk,
>>                                                                     void *),
>>                                        void (*detach_aio_context)(void *),
>>                                        void *opaque);
>> -void blk_add_close_notifier(BlockBackend *blk, Notifier *notify);
>> +void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify);
>> +void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify);
>>   void blk_io_plug(BlockBackend *blk);
>>   void blk_io_unplug(BlockBackend *blk);
>>   BlockAcctStats *blk_get_stats(BlockBackend *blk);
>> diff --git a/nbd.c b/nbd.c
>> index 71159af..5d50f22 100644
>> --- a/nbd.c
>> +++ b/nbd.c
>> @@ -964,9 +964,25 @@ static void blk_aio_detach(void *opaque)
>>       exp->ctx = NULL;
>>   }
>>   
>> +typedef struct NBDEjectNotifier {
>> +    Notifier n;
>> +    NBDExport *exp;
>> +    QTAILQ_ENTRY(NBDEjectNotifier) next;
>> +} NBDEjectNotifier;
> The same question here: will embedding the Notifier into NBDExport simplify
> memory management?

Maybe, but I don't think it works.

Max

> Fam
>
>> +
>> +static QTAILQ_HEAD(, NBDEjectNotifier) eject_notifiers =
>> +    QTAILQ_HEAD_INITIALIZER(eject_notifiers);
>> +
>> +static void nbd_eject_notifier(Notifier *n, void *data)
>> +{
>> +    NBDEjectNotifier *cn = DO_UPCAST(NBDEjectNotifier, n, n);
>> +    nbd_export_close(cn->exp);
>> +}
>> +
>>   NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
>>                             uint32_t nbdflags, void (*close)(NBDExport *))
>>   {
>> +    NBDEjectNotifier *n = g_new0(NBDEjectNotifier, 1);
>>       NBDExport *exp = g_malloc0(sizeof(NBDExport));
>>       exp->refcount = 1;
>>       QTAILQ_INIT(&exp->clients);
>> @@ -978,6 +994,13 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
>>       exp->ctx = blk_get_aio_context(blk);
>>       blk_ref(blk);
>>       blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
>> +
>> +    n->n.notify = nbd_eject_notifier;
>> +    n->exp = exp;
>> +    QTAILQ_INSERT_TAIL(&eject_notifiers, n, next);
>> +
>> +    blk_add_remove_bs_notifier(blk, &n->n);
>> +
>>       /*
>>        * NBD exports are used for non-shared storage migration.  Make sure
>>        * that BDRV_O_INCOMING is cleared and the image is ready for write
>> @@ -1022,6 +1045,7 @@ void nbd_export_set_name(NBDExport *exp, const char *name)
>>   
>>   void nbd_export_close(NBDExport *exp)
>>   {
>> +    NBDEjectNotifier *n;
>>       NBDClient *client, *next;
>>   
>>       nbd_export_get(exp);
>> @@ -1031,6 +1055,17 @@ void nbd_export_close(NBDExport *exp)
>>       nbd_export_set_name(exp, NULL);
>>       nbd_export_put(exp);
>>       if (exp->blk) {
>> +        QTAILQ_FOREACH(n, &eject_notifiers, next) {
>> +            if (n->exp == exp) {
>> +                break;
>> +            }
>> +        }
>> +        assert(n);
>> +
>> +        notifier_remove(&n->n);
>> +        QTAILQ_REMOVE(&eject_notifiers, n, next);
>> +        g_free(n);
>> +
>>           blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
>>                                           blk_aio_detach, exp);
>>           blk_unref(exp->blk);
>> -- 
>> 2.1.0
>>
>>

  reply	other threads:[~2015-02-25 14:12 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-24 15:35 [Qemu-devel] [PATCH v3 00/11] block: Rework bdrv_close_all() Max Reitz
2015-02-24 15:35 ` [Qemu-devel] [PATCH v3 01/11] iotests: Move _filter_nbd into common.filter Max Reitz
2015-02-25  6:46   ` Fam Zheng
2015-02-25 13:53     ` Max Reitz
2015-02-24 15:35 ` [Qemu-devel] [PATCH v3 02/11] iotests: Do not redirect qemu's stderr Max Reitz
2015-02-25  7:04   ` Fam Zheng
2015-02-25 14:01     ` Max Reitz
2015-02-26  2:29       ` Fam Zheng
2015-02-26 14:03         ` Max Reitz
2015-02-24 15:35 ` [Qemu-devel] [PATCH v3 03/11] iotests: Add test for eject under NBD server Max Reitz
2015-02-24 15:35 ` [Qemu-devel] [PATCH v3 04/11] quorum: Fix close path Max Reitz
2015-02-25  7:12   ` Fam Zheng
2015-02-25 14:08     ` Max Reitz
2015-02-24 15:35 ` [Qemu-devel] [PATCH v3 05/11] block: Move BDS close notifiers into BB Max Reitz
2015-02-25  7:52   ` Fam Zheng
2015-02-25 14:12     ` Max Reitz [this message]
2015-02-26  2:19       ` Fam Zheng
2015-02-26 13:59         ` Max Reitz
2015-02-24 15:35 ` [Qemu-devel] [PATCH v3 06/11] block: Use blk_remove_bs() in blk_delete() Max Reitz
2015-02-24 15:36 ` [Qemu-devel] [PATCH v3 07/11] blockdev: Use blk_remove_bs() in do_drive_del() Max Reitz
2015-02-24 15:36 ` [Qemu-devel] [PATCH v3 08/11] block: Make bdrv_close() static Max Reitz
2015-02-24 15:36 ` [Qemu-devel] [PATCH v3 09/11] blockdev: Keep track of monitor-owned BDS Max Reitz
2015-02-24 15:36 ` [Qemu-devel] [PATCH v3 10/11] block: Eject BDS tree from BB at bdrv_close_all() Max Reitz
2015-02-24 15:36 ` [Qemu-devel] [PATCH v3 11/11] iotests: Add test for multiple BB on BDS tree Max Reitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54EDD846.5030509@redhat.com \
    --to=mreitz@redhat.com \
    --cc=armbru@redhat.com \
    --cc=famz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).