Default behavior is force=true and it's unchanged. New behavior is
force=false, which makes it possible to be sure that node removal is
done successfully with no error and all metadata is stored and flushed
successfully.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
---
 qapi/block-core.json           |  6 +++++-
 block/monitor/block-hmp-cmds.c |  2 +-
 blockdev.c                     | 17 +++++++++++++++--
 hw/block/xen-block.c           |  2 +-
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 9a5a3641d0..b37d195772 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -4403,6 +4403,9 @@
 #
 # @node-name: Name of the graph node to delete.
 #
+# @force: Ignore failures when closing block-nodes, like failed IO
+#         when try to store metadata. Default true. (Since 7.0)
+#
 # Since: 2.9
 #
 # Example:
@@ -4425,7 +4428,8 @@
 # <- { "return": {} }
 #
 ##
-{ 'command': 'blockdev-del', 'data': { 'node-name': 'str' } }
+{ 'command': 'blockdev-del',
+  'data': { 'node-name': 'str', '*force': 'bool' } }
 
 ##
 # @BlockdevCreateOptionsFile:
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index bfb3c043a0..1c35aa2d6f 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -145,7 +145,7 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
 
     bs = bdrv_find_node(id);
     if (bs) {
-        qmp_blockdev_del(id, &local_err);
+        qmp_blockdev_del(id, true, true, &local_err);
         if (local_err) {
             error_report_err(local_err);
         }
diff --git a/blockdev.c b/blockdev.c
index 8197165bb5..34a195b592 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3582,11 +3582,17 @@ fail:
     g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end);
 }
 
-void qmp_blockdev_del(const char *node_name, Error **errp)
+void qmp_blockdev_del(const char *node_name, bool has_force,
+                      bool force, Error **errp)
 {
     AioContext *aio_context;
     BlockDriverState *bs;
 
+    if (!has_force) {
+        /* Historical default is force remove */
+        force = true;
+    }
+
     bs = bdrv_find_node(node_name);
     if (!bs) {
         error_setg(errp, "Failed to find node with node-name='%s'", node_name);
@@ -3616,7 +3622,14 @@ void qmp_blockdev_del(const char *node_name, Error 
**errp)
     }
 
     QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
-    bdrv_unref(bs);
+    if (force) {
+        bdrv_unref(bs);
+    } else {
+        int ret = bdrv_try_unref(bs, errp);
+        if (ret < 0) {
+            bdrv_set_monitor_owned(bs);
+        }
+    }
 
 out:
     aio_context_release(aio_context);
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index 674953f1ad..0ac9b599c0 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -649,7 +649,7 @@ static void xen_block_blockdev_del(const char *node_name, 
Error **errp)
 {
     trace_xen_block_blockdev_del(node_name);
 
-    qmp_blockdev_del(node_name, errp);
+    qmp_blockdev_del(node_name, true, true, errp);
 }
 
 static char *xen_block_blockdev_add(const char *id, QDict *qdict,
-- 
2.31.1


Reply via email to