aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2020-09-24 17:27:05 +0200
committerKevin Wolf <kwolf@redhat.com>2020-10-02 15:46:40 +0200
commit3859ad36f0bdf45a6610d93296b52c9604b6d6f7 (patch)
tree6f3079b4739c53840a3fe391ead09ef03847115a
parentd53be9ce55a38e430b88985f637f696bf99cbf0b (diff)
downloadqemu-3859ad36f0bdf45a6610d93296b52c9604b6d6f7.zip
qemu-3859ad36f0bdf45a6610d93296b52c9604b6d6f7.tar.gz
qemu-3859ad36f0bdf45a6610d93296b52c9604b6d6f7.tar.bz2
block/export: Move strong user reference to block_exports
The reference owned by the user/monitor that is created when adding the export and dropped when removing it was tied to the 'exports' list in nbd/server.c. Every block export will have a user reference, so move it to the block export level and tie it to the 'block_exports' list in block/export/export.c instead. This is necessary for introducing a QMP command for removing exports. Note that exports are present in block_exports even after the user has requested shutdown. This is different from NBD's exports where exports are immediately removed on a shutdown request, even if they are still in the process of shutting down. In order to avoid that the user still interacts with an export that is shutting down (and possibly removes it a second time), we need to remember if the user actually still owns it. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-Id: <20200924152717.287415-20-kwolf@redhat.com> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-rw-r--r--block/export/export.c6
-rw-r--r--blockdev-nbd.c5
-rw-r--r--include/block/export.h8
-rw-r--r--nbd/server.c2
4 files changed, 14 insertions, 7 deletions
diff --git a/block/export/export.c b/block/export/export.c
index 7a4a784..62699df 100644
--- a/block/export/export.c
+++ b/block/export/export.c
@@ -80,6 +80,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
*exp = (BlockExport) {
.drv = drv,
.refcount = 1,
+ .user_owned = true,
.id = g_strdup(export->id),
};
@@ -143,6 +144,11 @@ void blk_exp_request_shutdown(BlockExport *exp)
aio_context_acquire(aio_context);
exp->drv->request_shutdown(exp);
+
+ assert(exp->user_owned);
+ exp->user_owned = false;
+ blk_exp_unref(exp);
+
aio_context_release(aio_context);
}
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 814554d..9efbaef 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -235,11 +235,6 @@ int nbd_export_create(BlockExport *exp, BlockExportOptions *exp_args,
goto out;
}
- /* The list of named exports has a strong reference to this export now and
- * our only way of accessing it is through nbd_export_find(), so we can drop
- * the strong reference that is @exp. */
- blk_exp_unref(exp);
-
ret = 0;
out:
aio_context_release(aio_context);
diff --git a/include/block/export.h b/include/block/export.h
index cdc6e16..4833947 100644
--- a/include/block/export.h
+++ b/include/block/export.h
@@ -60,6 +60,14 @@ struct BlockExport {
*/
int refcount;
+ /*
+ * True if one of the references in refcount belongs to the user. After the
+ * user has dropped their reference, they may not e.g. remove the same
+ * export a second time (which would decrease the refcount without having
+ * it incremented first).
+ */
+ bool user_owned;
+
/* The AioContext whose lock protects this BlockExport object. */
AioContext *ctx;
diff --git a/nbd/server.c b/nbd/server.c
index 32147e4..22a1d66 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1616,7 +1616,6 @@ int nbd_export_new(BlockExport *blk_exp, BlockDriverState *bs,
blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp);
- blk_exp_ref(&exp->common);
QTAILQ_INSERT_TAIL(&exports, exp, next);
return 0;
@@ -1663,7 +1662,6 @@ static void nbd_export_request_shutdown(BlockExport *blk_exp)
client_close(client, true);
}
if (exp->name) {
- blk_exp_unref(&exp->common);
g_free(exp->name);
exp->name = NULL;
QTAILQ_REMOVE(&exports, exp, next);