diff options
author | Kevin Wolf | 2020-09-24 17:27:06 +0200 |
---|---|---|
committer | Kevin Wolf | 2020-10-02 15:46:40 +0200 |
commit | 3c3bc462adeb561f5dfdcbb84ae691c95ccef916 (patch) | |
tree | bc3fa25c7189db287349b4fe4dd922207b76194f /block/export | |
parent | block/export: Move strong user reference to block_exports (diff) | |
download | qemu-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.c | 43 |
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); +} |