Factor out qemuDomainBlockPullCommon, reuse its code in
qemuDomainBlockRebaseParams and call it from older API.

Add qemuDomainBlockRebasePrepareParams to ease params list
preparation.

Now bandwidth unit of messurement is passed as param
VIR_DOMAIN_BLOCK_REBASE_PARAM_BANDWIDTH in Bytes/s.

Signed-off-by: Nikolai Barybin <nikolai.bary...@virtuozzo.com>
---
 src/qemu/qemu_driver.c | 327 ++++++++++++++++++++++++++---------------
 1 file changed, 205 insertions(+), 122 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ac72ea5cb0..8133925ee1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13747,113 +13747,6 @@ qemuDomainOpenChannel(virDomainPtr dom,
 }
 
 
-/* bandwidth in MiB/s per public API. Caller must lock vm beforehand,
- * and not access it afterwards.  */
-static int
-qemuDomainBlockPullCommon(virDomainObj *vm,
-                          const char *path,
-                          const char *base,
-                          unsigned long bandwidth,
-                          unsigned int flags)
-{
-    qemuDomainObjPrivate *priv = vm->privateData;
-    virDomainDiskDef *disk;
-    virStorageSource *baseSource = NULL;
-    g_autofree char *backingPath = NULL;
-    unsigned long long speed = bandwidth;
-    qemuBlockJobData *job = NULL;
-    const char *nodebase = NULL;
-    int ret = -1;
-
-    if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
-        virReportError(VIR_ERR_INVALID_ARG, "%s",
-                       _("flag VIR_DOMAIN_BLOCK_REBASE_RELATIVE is valid only 
with non-null base"));
-        goto cleanup;
-    }
-
-    if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
-        goto cleanup;
-
-    if (virDomainObjCheckActive(vm) < 0)
-        goto endjob;
-
-    if (!(disk = qemuDomainDiskByName(vm->def, path)))
-        goto endjob;
-
-    if (qemuDomainDiskBlockJobIsActive(disk))
-        goto endjob;
-
-    if (!qemuDomainDiskBlockJobIsSupported(disk))
-        goto endjob;
-
-    if (base &&
-        !(baseSource = virStorageSourceChainLookup(disk->src, disk->src,
-                                                   base, disk->dst, NULL)))
-        goto endjob;
-
-    if (baseSource) {
-        if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
-            if (qemuBlockUpdateRelativeBacking(vm, disk->src, disk->src) < 0)
-                goto endjob;
-
-            if (virStorageSourceGetRelativeBackingPath(disk->src->backingStore,
-                                                       baseSource,
-                                                       &backingPath) < 0)
-                goto endjob;
-
-            if (!backingPath) {
-                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                               _("can't keep relative backing relationship"));
-                goto endjob;
-            }
-        }
-    }
-
-    /* Convert bandwidth MiB to bytes, if needed */
-    if (!(flags & VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES)) {
-        if (speed > LLONG_MAX >> 20) {
-            virReportError(VIR_ERR_OVERFLOW,
-                           _("bandwidth must be less than %1$llu"),
-                           LLONG_MAX >> 20);
-            goto endjob;
-        }
-        speed <<= 20;
-    }
-
-    if (!(job = qemuBlockJobDiskNewPull(vm, disk, baseSource, flags)))
-        goto endjob;
-
-    if (baseSource) {
-        nodebase = qemuBlockStorageSourceGetEffectiveNodename(baseSource);
-        if (!backingPath &&
-            !(backingPath = qemuBlockGetBackingStoreString(baseSource, false)))
-            goto endjob;
-    }
-
-    qemuDomainObjEnterMonitor(vm);
-    ret = qemuMonitorBlockStream(priv->mon,
-                                 
qemuBlockStorageSourceGetEffectiveNodename(disk->src),
-                                 job->name,
-                                 nodebase,
-                                 backingPath,
-                                 speed);
-    qemuDomainObjExitMonitor(vm);
-
-    if (ret < 0)
-        goto endjob;
-
-    qemuBlockJobStarted(job, vm);
-
- endjob:
-    virDomainObjEndJob(vm);
-
- cleanup:
-    qemuBlockJobStartupFinalize(vm, job);
-    virDomainObjEndAPI(&vm);
-    return ret;
-}
-
-
 static int
 qemuDomainBlockJobAbort(virDomainPtr dom,
                         const char *path,
@@ -14239,6 +14132,179 @@ 
qemuDomainBlockCopyCommonValidateUserMirrorBackingStore(virStorageSource *mirror
 }
 
 
+static int
+qemuDomainBlockRebasePrepareParams(const char *base,
+                                   unsigned long bandwidth,
+                                   unsigned int flags,
+                                   int *nparams,
+                                   virTypedParameterPtr *params,
+                                   unsigned int *rebaseFlags)
+{
+    int maxparams = 0;
+
+    /* Legacy support: convert bandwidth MiB to bytes, if needed */
+    if (!(flags & VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES)) {
+        if (bandwidth > LLONG_MAX >> 20) {
+            virReportError(VIR_ERR_OVERFLOW,
+                           _("bandwidth must be less than %1$llu"),
+                           LLONG_MAX >> 20);
+            return -1;
+        }
+        bandwidth <<= 20;
+    }
+
+    if (base &&
+        virTypedParamsAddString(params, nparams, &maxparams,
+                                VIR_DOMAIN_BLOCK_REBASE_PARAM_BASE,
+                                base) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to add param %1$s:%2$s to params list"),
+                       VIR_DOMAIN_BLOCK_REBASE_PARAM_BASE, base);
+        return -1;
+    }
+
+    if (bandwidth > 0 &&
+        virTypedParamsAddULLong(params, nparams, &maxparams,
+                                VIR_DOMAIN_BLOCK_REBASE_PARAM_BANDWIDTH,
+                                bandwidth) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to add param %1$s:%2$lu to params list"),
+                       VIR_DOMAIN_BLOCK_REBASE_PARAM_BANDWIDTH, bandwidth);
+        return -1;
+    }
+
+    if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE)
+        *rebaseFlags |= VIR_DOMAIN_BLOCK_REBASE_PARAMS_RELATIVE;
+
+    return 0;
+}
+
+
+static int
+qemuDomainBlockRebaseParams(virDomainPtr dom,
+                            const char *path,
+                            virTypedParameterPtr params,
+                            int nparams,
+                            unsigned int flags)
+{
+    virDomainObj *vm = NULL;
+    size_t i = 0;
+    unsigned long long bandwidth = 0;
+    const char *base = NULL;
+    virDomainDiskDef *disk;
+    virStorageSource *baseSource = NULL;
+    qemuDomainObjPrivate *priv = NULL;
+    g_autofree char *backingPath = NULL;
+    qemuBlockJobData *job = NULL;
+    const char *nodebase = NULL;
+    int ret = -1;
+
+    virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_PARAMS_RELATIVE, -1);
+
+    if (virTypedParamsValidate(params, nparams,
+                               VIR_DOMAIN_BLOCK_REBASE_PARAM_BASE,
+                               VIR_TYPED_PARAM_STRING,
+                               VIR_DOMAIN_BLOCK_REBASE_PARAM_BANDWIDTH,
+                               VIR_TYPED_PARAM_ULLONG,
+                               NULL) < 0)
+        return -1;
+
+    if (!(vm = qemuDomainObjFromDomain(dom)))
+        return -1;
+
+    priv = vm->privateData;
+
+    if (virDomainBlockRebaseParamsEnsureACL(dom->conn, vm->def) < 0)
+        return -1;
+
+    for (i = 0; i < nparams; i++) {
+        virTypedParameterPtr param = &params[i];
+
+        if (STREQ(param->field, VIR_DOMAIN_BLOCK_REBASE_PARAM_BANDWIDTH)) {
+            bandwidth = param->value.ul;
+        } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_REBASE_PARAM_BASE)) {
+            base = param->value.s;
+        }
+    }
+
+    if (flags & VIR_DOMAIN_BLOCK_REBASE_PARAMS_RELATIVE  && !base) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("flag VIR_DOMAIN_BLOCK_REBASE_PARAMS_RELATIVE  is 
valid only with non-null base"));
+        goto cleanup;
+    }
+
+    if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (virDomainObjCheckActive(vm) < 0)
+        goto endjob;
+
+    if (!(disk = qemuDomainDiskByName(vm->def, path)))
+        goto endjob;
+
+    if (qemuDomainDiskBlockJobIsActive(disk))
+        goto endjob;
+
+    if (!qemuDomainDiskBlockJobIsSupported(disk))
+        goto endjob;
+
+    if (base &&
+        !(baseSource = virStorageSourceChainLookup(disk->src, disk->src,
+                                                   base, disk->dst, NULL)))
+        goto endjob;
+
+    if (baseSource) {
+        if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
+            if (qemuBlockUpdateRelativeBacking(vm, disk->src, disk->src) < 0)
+                goto endjob;
+
+            if (virStorageSourceGetRelativeBackingPath(disk->src->backingStore,
+                                                       baseSource,
+                                                       &backingPath) < 0)
+                goto endjob;
+
+            if (!backingPath) {
+                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                               _("can't keep relative backing relationship"));
+                goto endjob;
+            }
+        }
+    }
+
+    if (!(job = qemuBlockJobDiskNewPull(vm, disk, baseSource, flags)))
+        goto endjob;
+
+    if (baseSource) {
+        nodebase = qemuBlockStorageSourceGetEffectiveNodename(baseSource);
+        if (!backingPath &&
+            !(backingPath = qemuBlockGetBackingStoreString(baseSource, false)))
+            goto endjob;
+    }
+
+    qemuDomainObjEnterMonitor(vm);
+    ret = qemuMonitorBlockStream(priv->mon,
+                                 
qemuBlockStorageSourceGetEffectiveNodename(disk->src),
+                                 job->name,
+                                 nodebase,
+                                 backingPath,
+                                 bandwidth);
+    qemuDomainObjExitMonitor(vm);
+
+    if (ret < 0)
+        goto endjob;
+
+    qemuBlockJobStarted(job, vm);
+
+ endjob:
+    virDomainObjEndJob(vm);
+
+ cleanup:
+    qemuBlockJobStartupFinalize(vm, job);
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
+
+
 /* bandwidth in bytes/s.  Caller must lock vm beforehand, and not
  * access mirror afterwards.  */
 static int
@@ -14579,17 +14645,30 @@ qemuDomainBlockRebase(virDomainPtr dom,
                   VIR_DOMAIN_BLOCK_REBASE_COPY_DEV |
                   VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES, -1);
 
+    /* For normal rebase (enhanced blockpull), the common code handles
+     * everything, including vm cleanup. */
+    if (!(flags & VIR_DOMAIN_BLOCK_REBASE_COPY)) {
+        virTypedParameterPtr params = NULL;
+        int nparams = 0;
+        unsigned int rebaseFlags = 0;
+
+        ret = qemuDomainBlockRebasePrepareParams(base, bandwidth, flags,
+                                                 &nparams, &params, 
&rebaseFlags);
+        if (ret == 0)
+            ret = qemuDomainBlockRebaseParams(dom, path, params, nparams, 
rebaseFlags);
+
+        virTypedParamsFree(params, nparams);
+        params = NULL;
+        nparams = 0;
+        return ret;
+    }
+
     if (!(vm = qemuDomainObjFromDomain(dom)))
         return -1;
 
     if (virDomainBlockRebaseEnsureACL(dom->conn, vm->def) < 0)
         goto cleanup;
 
-    /* For normal rebase (enhanced blockpull), the common code handles
-     * everything, including vm cleanup. */
-    if (!(flags & VIR_DOMAIN_BLOCK_REBASE_COPY))
-        return qemuDomainBlockPullCommon(vm, path, base, bandwidth, flags);
-
     /* If we got here, we are doing a block copy rebase. */
     dest = virStorageSourceNew();
     if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_DEV)
@@ -14722,19 +14801,22 @@ qemuDomainBlockPull(virDomainPtr dom,
                     unsigned long bandwidth,
                     unsigned int flags)
 {
-    virDomainObj *vm;
-    virCheckFlags(VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES, -1);
+    virTypedParameterPtr params = NULL;
+    int nparams = 0;
+    unsigned int rebaseFlags = 0;
+    int ret = 0;
 
-    if (!(vm = qemuDomainObjFromDomain(dom)))
-        return -1;
+    virCheckFlags(VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES, -1);
 
-    if (virDomainBlockPullEnsureACL(dom->conn, vm->def) < 0) {
-        virDomainObjEndAPI(&vm);
-        return -1;
-    }
+    ret = qemuDomainBlockRebasePrepareParams(NULL, bandwidth, flags,
+                                             &nparams, &params, &rebaseFlags);
+    if (ret == 0)
+        ret = qemuDomainBlockRebaseParams(dom, path, params, nparams, 
rebaseFlags);
 
-    /* qemuDomainBlockPullCommon consumes the reference on @vm */
-    return qemuDomainBlockPullCommon(vm, path, NULL, bandwidth, flags);
+    virTypedParamsFree(params, nparams);
+    params = NULL;
+    nparams = 0;
+    return ret;
 }
 
 
@@ -20579,6 +20661,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
     .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
     .domainBlockRebase = qemuDomainBlockRebase, /* 0.9.10 */
+    .domainBlockRebaseParams = qemuDomainBlockRebaseParams, /* 11.8.0 */
     .domainBlockCopy = qemuDomainBlockCopy, /* 1.2.9 */
     .domainBlockCommit = qemuDomainBlockCommit, /* 1.0.0 */
     .connectIsAlive = qemuConnectIsAlive, /* 0.9.8 */
-- 
2.43.5

Reply via email to