diff mbox series

[1/2] block: transaction support for blockdev-add

Message ID 20220224171328.1628047-2-vsementsov@virtuozzo.com
State New
Headers show
Series blockdev-add transaction | expand

Commit Message

Vladimir Sementsov-Ogievskiy Feb. 24, 2022, 5:13 p.m. UTC
Simply do blockdev_add() in .prepare() and bdrv_unref() in .abort() and
that's it.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
 qapi/transaction.json | 11 ++++++
 blockdev.c            | 80 +++++++++++++++++++++++++++++--------------
 2 files changed, 66 insertions(+), 25 deletions(-)
diff mbox series

Patch

diff --git a/qapi/transaction.json b/qapi/transaction.json
index 381a2df782..a938dc7d10 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -53,6 +53,7 @@ 
 # @blockdev-snapshot-internal-sync: Since 1.7
 # @blockdev-snapshot-sync: since 1.1
 # @drive-backup: Since 1.6
+# @blockdev-add: since 7.0
 #
 # Features:
 # @deprecated: Member @drive-backup is deprecated.  Use member
@@ -66,6 +67,7 @@ 
             'block-dirty-bitmap-disable', 'block-dirty-bitmap-merge',
             'blockdev-backup', 'blockdev-snapshot',
             'blockdev-snapshot-internal-sync', 'blockdev-snapshot-sync',
+            'blockdev-add',
             { 'name': 'drive-backup', 'features': [ 'deprecated' ] } ] }
 
 ##
@@ -140,6 +142,14 @@ 
 { 'struct': 'DriveBackupWrapper',
   'data': { 'data': 'DriveBackup' } }
 
+##
+# @BlockdevAddWrapper:
+#
+# Since: 7.0
+##
+{ 'struct': 'BlockdevAddWrapper',
+  'data': { 'data': 'BlockdevOptions' } }
+
 ##
 # @TransactionAction:
 #
@@ -163,6 +173,7 @@ 
        'blockdev-snapshot': 'BlockdevSnapshotWrapper',
        'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternalWrapper',
        'blockdev-snapshot-sync': 'BlockdevSnapshotSyncWrapper',
+       'blockdev-add': 'BlockdevAddWrapper',
        'drive-backup': 'DriveBackupWrapper'
    } }
 
diff --git a/blockdev.c b/blockdev.c
index 42e098b458..eb9ad9cb89 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2180,6 +2180,55 @@  static void abort_commit(BlkActionState *common)
     g_assert_not_reached(); /* this action never succeeds */
 }
 
+static BlockDriverState *blockdev_add(BlockdevOptions *options, Error **errp)
+{
+    BlockDriverState *bs = NULL;
+    QObject *obj;
+    Visitor *v = qobject_output_visitor_new(&obj);
+    QDict *qdict;
+
+    visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
+    visit_complete(v, &obj);
+    qdict = qobject_to(QDict, obj);
+
+    qdict_flatten(qdict);
+
+    if (!qdict_get_try_str(qdict, "node-name")) {
+        error_setg(errp, "'node-name' must be specified for the root node");
+        goto fail;
+    }
+
+    bs = bds_tree_init(qdict, errp);
+    if (!bs) {
+        goto fail;
+    }
+
+    bdrv_set_monitor_owned(bs);
+
+fail:
+    visit_free(v);
+    return bs;
+}
+
+typedef struct BlockdevAddState {
+    BlkActionState common;
+    BlockDriverState *bs;
+} BlockdevAddState;
+
+static void blockdev_add_prepare(BlkActionState *common, Error **errp)
+{
+    BlockdevAddState *s = DO_UPCAST(BlockdevAddState, common, common);
+
+    s->bs = blockdev_add(common->action->u.blockdev_add.data, errp);
+}
+
+static void blockdev_add_abort(BlkActionState *common)
+{
+    BlockdevAddState *s = DO_UPCAST(BlockdevAddState, common, common);
+
+    bdrv_unref(s->bs);
+}
+
 static const BlkActionOps actions[] = {
     [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = {
         .instance_size = sizeof(ExternalSnapshotState),
@@ -2253,6 +2302,11 @@  static const BlkActionOps actions[] = {
         .commit = block_dirty_bitmap_remove_commit,
         .abort = block_dirty_bitmap_remove_abort,
     },
+    [TRANSACTION_ACTION_KIND_BLOCKDEV_ADD] = {
+        .instance_size = sizeof(BlockdevAddState),
+        .prepare = blockdev_add_prepare,
+        .abort = blockdev_add_abort,
+    },
     /* Where are transactions for MIRROR, COMMIT and STREAM?
      * Although these blockjobs use transaction callbacks like the backup job,
      * these jobs do not necessarily adhere to transaction semantics.
@@ -3499,31 +3553,7 @@  out:
 
 void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 {
-    BlockDriverState *bs;
-    QObject *obj;
-    Visitor *v = qobject_output_visitor_new(&obj);
-    QDict *qdict;
-
-    visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
-    visit_complete(v, &obj);
-    qdict = qobject_to(QDict, obj);
-
-    qdict_flatten(qdict);
-
-    if (!qdict_get_try_str(qdict, "node-name")) {
-        error_setg(errp, "'node-name' must be specified for the root node");
-        goto fail;
-    }
-
-    bs = bds_tree_init(qdict, errp);
-    if (!bs) {
-        goto fail;
-    }
-
-    bdrv_set_monitor_owned(bs);
-
-fail:
-    visit_free(v);
+    blockdev_add(options, errp);
 }
 
 void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)