Only supported with completion-mode 'grouped', since it relies on a
JobTxn to exist. This means that for now it is only available for
{drive,blockdev}-backup transactions.

Since only one job will be running at a time, bandwidth-limits can be
applied effectively. It can also prevent overloading a host's IO
capabilities in general.

Signed-off-by: Stefan Reiter <s.rei...@proxmox.com>
---
 blockdev.c            | 25 ++++++++++++++++++++++---
 qapi/transaction.json |  6 +++++-
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 3848a9c8ab..3691e5e791 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1826,7 +1826,10 @@ static void drive_backup_commit(BlkActionState *common)
     aio_context_acquire(aio_context);
 
     assert(state->job);
-    job_start(&state->job->job);
+
+    if (!common->txn_props->sequential) {
+        job_start(&state->job->job);
+    }
 
     aio_context_release(aio_context);
 }
@@ -1927,7 +1930,9 @@ static void blockdev_backup_commit(BlkActionState *common)
     aio_context_acquire(aio_context);
 
     assert(state->job);
-    job_start(&state->job->job);
+    if (!common->txn_props->sequential) {
+        job_start(&state->job->job);
+    }
 
     aio_context_release(aio_context);
 }
@@ -2303,6 +2308,11 @@ static TransactionProperties *get_transaction_properties(
         props->completion_mode = ACTION_COMPLETION_MODE_INDIVIDUAL;
     }
 
+    if (!props->has_sequential) {
+        props->has_sequential = true;
+        props->sequential = false;
+    }
+
     return props;
 }
 
@@ -2328,7 +2338,11 @@ void qmp_transaction(TransactionActionList *dev_list,
      */
     props = get_transaction_properties(props);
     if (props->completion_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
-        block_job_txn = job_txn_new();
+        block_job_txn = props->sequential ? job_txn_new_seq() : job_txn_new();
+    } else if (props->sequential) {
+        error_setg(errp, "Sequential transaction mode is not supported with "
+                         "completion-mode = individual");
+        return;
     }
 
     /* drain all i/o before any operations */
@@ -2367,6 +2381,11 @@ void qmp_transaction(TransactionActionList *dev_list,
         }
     }
 
+    /* jobs in sequential txns don't start themselves on commit */
+    if (block_job_txn && props->sequential) {
+        job_txn_start_seq(block_job_txn);
+    }
+
     /* success */
     goto exit;
 
diff --git a/qapi/transaction.json b/qapi/transaction.json
index 15ddebdbc3..4808383088 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -84,11 +84,15 @@
 #                   Actions will complete or fail as a group.
 #                   See @ActionCompletionMode for details.
 #
+# @sequential: Run the jobs in the transaction one after the other, instead
+#              of all at once. Not supported for completion-mode 'individual'.
+#
 # Since: 2.5
 ##
 { 'struct': 'TransactionProperties',
   'data': {
-       '*completion-mode': 'ActionCompletionMode'
+       '*completion-mode': 'ActionCompletionMode',
+       '*sequential': 'bool'
   }
 }
 
-- 
2.20.1



Reply via email to