Signed-off-by: Claudio Fontana <cfont...@suse.de>
---
 docs/manpages/virsh.rst | 23 ++++++++++++++-----
 tools/virsh-domain.c    | 49 +++++++++++++++++++++++++++++++++--------
 2 files changed, 57 insertions(+), 15 deletions(-)

diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index e8568559fa..2bce701057 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -3801,15 +3801,18 @@ save
 ::
 
    save domain state-file [--bypass-cache] [--xml file]
+      [--parallel] [--parallel-connections connections]
       [{--running | --paused}] [--verbose]
 
-Saves a running domain (RAM, but not disk state) to a state file so that
-it can be restored
-later.  Once saved, the domain will no longer be running on the
-system, thus the memory allocated for the domain will be free for
-other domains to use.  ``virsh restore`` restores from this state file.
+Saves a paused or running domain (RAM, but not disk state) to one or more
+state files, so that it can be restored later.
+Once saved, the domain will no longer be running on the system,
+thus the memory allocated for the domain will be free for
+other domains to use.  ``virsh restore`` restores from state file/s.
+
 If *--bypass-cache* is specified, the save will avoid the file system
-cache, although this may slow down the operation.
+cache; depending on the specific scenario this may slow down or speed up
+the operation.
 
 The progress may be monitored using ``domjobinfo`` virsh command and canceled
 with ``domjobabort`` command (sent by another virsh instance). Another option
@@ -3831,6 +3834,14 @@ based on the state the domain was in when the save was 
done; passing
 either the *--running* or *--paused* flag will allow overriding which
 state the ``restore`` should use.
 
+*--parallel* option will cause the save data to be sent over multiple
+parallel connections to multiple files. The main save file is specified
+with ``state-file``, and a number of additional connections can be
+set using *--parallel-connections*, which will save to files named
+``state-file``.1 , ``state-file``.2 ... up to ``connections``.
+
+Parallel connections may help in speeding up the save operation.
+
 Domain saved state files assume that disk images will be unchanged
 between the creation and restore point.  For a more complete system
 restore point, where the disk state is saved alongside the memory
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index df8df9c2f3..1e3adaa1be 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -4164,6 +4164,14 @@ static const vshCmdOptDef opts_save[] = {
      .type = VSH_OT_BOOL,
      .help = N_("avoid file system cache when saving")
     },
+    {.name = "parallel",
+     .type = VSH_OT_BOOL,
+     .help = N_("enable parallel save to files")
+    },
+    {.name = "parallel-connections",
+     .type = VSH_OT_INT,
+     .help = N_("number of connections/files for parallel save")
+    },
     {.name = "xml",
      .type = VSH_OT_STRING,
      .completer = virshCompletePathLocalExisting,
@@ -4193,6 +4201,11 @@ doSave(void *opaque)
     g_autoptr(virshDomain) dom = NULL;
     const char *name = NULL;
     const char *to = NULL;
+    virTypedParameterPtr params = NULL;
+    int nparams = 0;
+    int maxparams = 0;
+    int intOpt = 0;
+    int rv = -1;
     unsigned int flags = 0;
     const char *xmlfile = NULL;
     g_autofree char *xml = NULL;
@@ -4206,29 +4219,46 @@ doSave(void *opaque)
         goto out_sig;
 #endif /* !WIN32 */
 
-    if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0)
+    if ((rv = vshCommandOptStringReq(ctl, cmd, "file", &to)) < 0) {
         goto out;
-
+    } else {
+        if (virTypedParamsAddString(&params, &nparams, &maxparams,
+                                    VIR_SAVE_PARAM_FILE, to) < 0)
+            goto out;
+    }
     if (vshCommandOptBool(cmd, "bypass-cache"))
         flags |= VIR_DOMAIN_SAVE_BYPASS_CACHE;
+    if (vshCommandOptBool(cmd, "parallel"))
+        flags |= VIR_DOMAIN_SAVE_PARALLEL;
+    if ((rv = vshCommandOptInt(ctl, cmd, "parallel-connections", &intOpt)) < 
0) {
+        goto out;
+    } else if (rv > 0) {
+        if (virTypedParamsAddInt(&params, &nparams, &maxparams,
+                                 VIR_SAVE_PARAM_PARALLEL_CONNECTIONS, intOpt) 
< 0)
+            goto out;
+    }
     if (vshCommandOptBool(cmd, "running"))
         flags |= VIR_DOMAIN_SAVE_RUNNING;
     if (vshCommandOptBool(cmd, "paused"))
         flags |= VIR_DOMAIN_SAVE_PAUSED;
 
-    if (vshCommandOptStringReq(ctl, cmd, "xml", &xmlfile) < 0)
+    if ((rv = vshCommandOptStringReq(ctl, cmd, "xml", &xmlfile)) < 0)
         goto out;
 
     if (!(dom = virshCommandOptDomain(ctl, cmd, &name)))
         goto out;
 
-    if (xmlfile &&
-        virFileReadAll(xmlfile, VSH_MAX_XML_FILE, &xml) < 0) {
-        vshReportError(ctl);
-        goto out;
+    if (xmlfile) {
+        if (virFileReadAll(xmlfile, VSH_MAX_XML_FILE, &xml) < 0) {
+            vshReportError(ctl);
+            goto out;
+        } else if (virTypedParamsAddString(&params, &nparams, &maxparams,
+                                           VIR_SAVE_PARAM_DXML, xml) < 0)
+            goto out;
     }
-
-    if (flags || xml) {
+    if (flags & VIR_DOMAIN_SAVE_PARALLEL) {
+        rc = virDomainSaveParametersFlags(dom, params, nparams, flags);
+    } else if (flags || xml) {
         rc = virDomainSaveFlags(dom, to, xml, flags);
     } else {
         rc = virDomainSave(dom, to);
@@ -4242,6 +4272,7 @@ doSave(void *opaque)
     data->ret = 0;
 
  out:
+    virTypedParamsFree(params, nparams);
 #ifndef WIN32
     pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
  out_sig:
-- 
2.34.1

Reply via email to