summaryrefslogtreecommitdiffstats
path: root/block/export
diff options
context:
space:
mode:
authorKevin Wolf2020-09-24 17:27:06 +0200
committerKevin Wolf2020-10-02 15:46:40 +0200
commit3c3bc462adeb561f5dfdcbb84ae691c95ccef916 (patch)
treebc3fa25c7189db287349b4fe4dd922207b76194f /block/export
parentblock/export: Move strong user reference to block_exports (diff)
downloadqemu-3c3bc462adeb561f5dfdcbb84ae691c95ccef916.tar.gz
qemu-3c3bc462adeb561f5dfdcbb84ae691c95ccef916.tar.xz
qemu-3c3bc462adeb561f5dfdcbb84ae691c95ccef916.zip
block/export: Add block-export-del
Implement a new QMP command block-export-del and make nbd-server-remove a wrapper around it. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-Id: <20200924152717.287415-21-kwolf@redhat.com> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/export')
-rw-r--r--block/export/export.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/block/export/export.c b/block/export/export.c
index 62699dfa05..d186beffe9 100644
--- a/block/export/export.c
+++ b/block/export/export.c
@@ -29,7 +29,7 @@ static const BlockExportDriver *blk_exp_drivers[] = {
static QLIST_HEAD(, BlockExport) block_exports =
QLIST_HEAD_INITIALIZER(block_exports);
-static BlockExport *blk_exp_find(const char *id)
+BlockExport *blk_exp_find(const char *id)
{
BlockExport *exp;
@@ -143,12 +143,23 @@ void blk_exp_request_shutdown(BlockExport *exp)
AioContext *aio_context = exp->ctx;
aio_context_acquire(aio_context);
+
+ /*
+ * If the user doesn't own the export any more, it is already shutting
+ * down. We must not call .request_shutdown and decrease the refcount a
+ * second time.
+ */
+ if (!exp->user_owned) {
+ goto out;
+ }
+
exp->drv->request_shutdown(exp);
assert(exp->user_owned);
exp->user_owned = false;
blk_exp_unref(exp);
+out:
aio_context_release(aio_context);
}
@@ -199,3 +210,33 @@ void qmp_block_export_add(BlockExportOptions *export, Error **errp)
{
blk_exp_add(export, errp);
}
+
+void qmp_block_export_del(const char *id,
+ bool has_mode, BlockExportRemoveMode mode,
+ Error **errp)
+{
+ ERRP_GUARD();
+ BlockExport *exp;
+
+ exp = blk_exp_find(id);
+ if (exp == NULL) {
+ error_setg(errp, "Export '%s' is not found", id);
+ return;
+ }
+ if (!exp->user_owned) {
+ error_setg(errp, "Export '%s' is already shutting down", id);
+ return;
+ }
+
+ if (!has_mode) {
+ mode = BLOCK_EXPORT_REMOVE_MODE_SAFE;
+ }
+ if (mode == BLOCK_EXPORT_REMOVE_MODE_SAFE && exp->refcount > 1) {
+ error_setg(errp, "export '%s' still in use", exp->id);
+ error_append_hint(errp, "Use mode='hard' to force client "
+ "disconnect\n");
+ return;
+ }
+
+ blk_exp_request_shutdown(exp);
+}