On 01.12.2015 14:16, Kevin Wolf wrote: > Am 30.11.2015 um 18:22 hat Max Reitz geschrieben: >> On 30.11.2015 16:36, Kevin Wolf wrote: >>> Am 09.11.2015 um 23:39 hat Max Reitz geschrieben: >>>> The NBD code uses the BDS close notifier to determine when a medium is >>>> ejected. However, now it should use the BB's BDS removal notifier for >>>> that instead of the BDS's close notifier. >>>> >>>> Signed-off-by: Max Reitz >>>> --- >>>> blockdev-nbd.c | 37 +------------------------------------ >>>> nbd.c | 13 +++++++++++++ >>>> 2 files changed, 14 insertions(+), 36 deletions(-) >>>> >>>> diff --git a/blockdev-nbd.c b/blockdev-nbd.c >>>> index bcdd18b..b28a55b 100644 >>>> --- a/blockdev-nbd.c >>>> +++ b/blockdev-nbd.c >>>> @@ -46,37 +46,11 @@ void qmp_nbd_server_start(SocketAddress *addr, Error **errp) >>>> } >>>> } >>>> >>>> -/* >>>> - * Hook into the BlockBackend notifiers to close the export when the >>>> - * backend 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); >>> >>> Here you remove a close/put pair, but in the new code you only add the >>> close call. Why is this correct? >> >> Thanks for putting so much unfounded faith in me. :-) >> >> After having put quite some time into looking into it, first I have to >> say that it's a very good question. >> >> First off, it's wrong. This is because I thought every export would have >> a refcount of one. Turns out this is wrong, they have a refcount of two: >> It is created with a refcount of one, and then it gains another by >> giving it a name and entering it into the export list. >> >> I did know about the second but I completely forgot about the former. >> And indeed I do think it is wrong. qmp_nbd_server_add() does not keep >> the reference to the export, once the function returns, it is gone. >> Therefore, it should call nbd_export_put() before returning. >> >> So in my opinion the current code is wrong and I didn't fix it enough. >> *cough* >> >> So, with the nbd_export_put() added to qmp_nbd_server_add(), every >> export will have a refcount of 1 + |clients|. The eject notifier will >> call nbd_close_notifier(), which first disconnects the clients, thus >> reducing the refcount by |clients|, and then sets the name to NULL, thus >> dropping the final refcount and destroying the export. >> >> In the old code, we needed another nbd_export_put() because of the >> superfluous reference from nbd_export_new(), which doesn't actually >> exist for blockdev-nbd (it does for qemu-nbd, though). > > Okay, that makes sense to me. So first a patch that moves the existing > nbd_export_put() call from nbd_close_notifier() to qmp_nbd_server_add() > and then this one on top? I would have put both in the same patch, but this does make more sense. I'll do so. Max