[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 20/22] block/export: Add block-export-del
From: |
Kevin Wolf |
Subject: |
[RFC PATCH 20/22] block/export: Add block-export-del |
Date: |
Thu, 13 Aug 2020 18:29:33 +0200 |
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>
---
qapi/block-export.json | 30 +++++++++++++++----
include/block/nbd.h | 1 -
block/export/export.c | 54 ++++++++++++++++++++++++++++++++++
block/monitor/block-hmp-cmds.c | 2 +-
blockdev-nbd.c | 28 ------------------
nbd/server.c | 14 ---------
6 files changed, 79 insertions(+), 50 deletions(-)
diff --git a/qapi/block-export.json b/qapi/block-export.json
index 0d0db9ca1b..a067de2ba3 100644
--- a/qapi/block-export.json
+++ b/qapi/block-export.json
@@ -111,9 +111,9 @@
'data': 'NbdServerAddOptions', 'boxed': true }
##
-# @NbdServerRemoveMode:
+# @BlockExportRemoveMode:
#
-# Mode for removing an NBD export.
+# Mode for removing a block export.
#
# @safe: Remove export if there are no existing connections, fail otherwise.
#
@@ -129,16 +129,16 @@
#
# Since: 2.12
##
-{'enum': 'NbdServerRemoveMode', 'data': ['safe', 'hard']}
+{'enum': 'BlockExportRemoveMode', 'data': ['safe', 'hard']}
##
# @nbd-server-remove:
#
# Remove NBD export by name.
#
-# @name: Export name.
+# @name: Block export id.
#
-# @mode: Mode of command operation. See @NbdServerRemoveMode description.
+# @mode: Mode of command operation. See @BlockExportRemoveMode description.
# Default is 'safe'.
#
# Returns: error if
@@ -149,7 +149,7 @@
# Since: 2.12
##
{ 'command': 'nbd-server-remove',
- 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} }
+ 'data': {'name': 'str', '*mode': 'BlockExportRemoveMode'} }
##
# @nbd-server-stop:
@@ -208,3 +208,21 @@
##
{ 'command': 'block-export-add',
'data': 'BlockExportOptions', 'boxed': true }
+
+##
+# @block-export-del:
+#
+# Remove a block export.
+#
+# @id: Block export id.
+#
+# @mode: Mode of command operation. See @BlockExportRemoveMode description.
+# Default is 'safe'.
+#
+# Returns: Error if the export is not found or @mode is 'safe' and the export
+# is still in use (e.g. by existing client connections)
+#
+# Since: 5.2
+##
+{ 'command': 'block-export-del',
+ 'data': { 'id': 'str', '*mode': 'BlockExportRemoveMode' } }
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 91a9d4f96d..7982a63f96 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -335,7 +335,6 @@ int nbd_export_new(BlockExport *blk_exp, BlockDriverState
*bs,
const char *bitmap, bool readonly, bool shared,
bool writethrough, Error **errp);
void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk);
-void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp);
AioContext *nbd_export_aio_context(NBDExport *exp);
NBDExport *nbd_export_find(const char *name);
diff --git a/block/export/export.c b/block/export/export.c
index f94a81258a..1255f3fc80 100644
--- a/block/export/export.c
+++ b/block/export/export.c
@@ -115,6 +115,15 @@ void blk_exp_request_shutdown(BlockExport *exp)
{
AioContext *aio_context = exp->ctx;
+ /*
+ * 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) {
+ return;
+ }
+
aio_context_acquire(aio_context);
exp->drv->request_shutdown(exp);
aio_context_release(aio_context);
@@ -215,3 +224,48 @@ void qmp_nbd_server_add(NbdServerAddOptions *arg, Error
**errp)
fail:
qapi_free_BlockExportOptions(export_opts);
}
+
+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);
+}
+
+void qmp_nbd_server_remove(const char *name,
+ bool has_mode, BlockExportRemoveMode mode,
+ Error **errp)
+{
+ BlockExport *exp;
+
+ exp = blk_exp_find(name);
+ if (exp && exp->drv->type != BLOCK_EXPORT_TYPE_NBD) {
+ error_setg(errp, "Block export '%s' is not an NBD export", name);
+ return;
+ }
+
+ qmp_block_export_del(name, has_mode, mode, errp);
+}
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 6c823234a9..10165252cf 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -477,7 +477,7 @@ void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict)
Error *err = NULL;
/* Rely on NBD_SERVER_REMOVE_MODE_SAFE being the default */
- qmp_nbd_server_remove(name, force, NBD_SERVER_REMOVE_MODE_HARD, &err);
+ qmp_nbd_server_remove(name, force, BLOCK_EXPORT_REMOVE_MODE_HARD, &err);
hmp_handle_error(mon, err);
}
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 40013b7d64..5ec21045a8 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -237,34 +237,6 @@ int nbd_export_create(BlockExport *exp, BlockExportOptions
*exp_args,
return ret;
}
-void qmp_nbd_server_remove(const char *name,
- bool has_mode, NbdServerRemoveMode mode,
- Error **errp)
-{
- NBDExport *exp;
- AioContext *aio_context;
-
- if (!nbd_server) {
- error_setg(errp, "NBD server not running");
- return;
- }
-
- exp = nbd_export_find(name);
- if (exp == NULL) {
- error_setg(errp, "Export '%s' is not found", name);
- return;
- }
-
- if (!has_mode) {
- mode = NBD_SERVER_REMOVE_MODE_SAFE;
- }
-
- aio_context = nbd_export_aio_context(exp);
- aio_context_acquire(aio_context);
- nbd_export_remove(exp, mode, errp);
- aio_context_release(aio_context);
-}
-
void qmp_nbd_server_stop(Error **errp)
{
if (!nbd_server) {
diff --git a/nbd/server.c b/nbd/server.c
index e3ac7f548b..899d00782f 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -1669,20 +1669,6 @@ static void nbd_export_request_shutdown(BlockExport
*blk_exp)
blk_exp_unref(&exp->common);
}
-void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp)
-{
- ERRP_GUARD();
- if (mode == NBD_SERVER_REMOVE_MODE_HARD || QTAILQ_EMPTY(&exp->clients)) {
- nbd_export_request_shutdown(&exp->common);
- return;
- }
-
- assert(mode == NBD_SERVER_REMOVE_MODE_SAFE);
-
- error_setg(errp, "export '%s' still in use", exp->name);
- error_append_hint(errp, "Use mode='hard' to force client disconnect\n");
-}
-
static void nbd_export_delete(BlockExport *blk_exp)
{
NBDExport *exp = container_of(blk_exp, NBDExport, common);
--
2.25.4
[RFC PATCH 16/22] block/export: Allocate BlockExport in blk_exp_add(), Kevin Wolf, 2020/08/13
[RFC PATCH 18/22] block/export: Add 'id' option to block-export-add, Kevin Wolf, 2020/08/13
[RFC PATCH 17/22] block/export: Add blk_exp_close_all(_type), Kevin Wolf, 2020/08/13
[RFC PATCH 20/22] block/export: Add block-export-del,
Kevin Wolf <=
[RFC PATCH 19/22] block/export: Move strong user reference to block_exports, Kevin Wolf, 2020/08/13
[RFC PATCH 22/22] block/export: Add query-block-exports, Kevin Wolf, 2020/08/13
[RFC PATCH 21/22] block/export: Move blk to BlockExport, Kevin Wolf, 2020/08/13