[libvirt] [PATCH 3/6] virsh: blockjob: Support --bytes and scaled integers as bandwidth

Peter Krempa pkrempa at redhat.com
Fri Mar 18 08:57:02 UTC 2016


Allow specifying sizes in bytes or as scaled integers for user
convenience.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1288000
---
 tools/virsh-domain.c | 17 ++++++++++-------
 tools/virsh.pod      | 11 ++++++++---
 tools/vsh.c          | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/vsh.h          |  4 ++++
 4 files changed, 74 insertions(+), 10 deletions(-)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 854823e..5ea39f7 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -2492,7 +2492,7 @@ static const vshCmdOptDef opts_block_job[] = {
     },
     {.name = "bytes",
      .type = VSH_OT_BOOL,
-     .help = N_("with --info, get bandwidth in bytes rather than MiB/s")
+     .help = N_("get/set bandwidth in bytes rather than MiB/s")
     },
     {.name = "raw",
      .type = VSH_OT_BOOL,
@@ -2611,14 +2611,19 @@ static bool
 virshBlockJobSetSpeed(vshControl *ctl,
                       const vshCmd *cmd,
                       virDomainPtr dom,
-                      const char *path)
+                      const char *path,
+                      bool bytes)
 {
     unsigned long bandwidth;
+    unsigned int flags = 0;

-    if (vshCommandOptULWrap(ctl, cmd, "bandwidth", &bandwidth) < 0)
+    if (bytes)
+        flags |= VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES;
+
+    if (vshBlockJobOptionBandwidth(ctl, cmd, bytes, &bandwidth) < 0)
         return false;

-    if (virDomainBlockJobSetSpeed(dom, path, bandwidth, 0) < 0)
+    if (virDomainBlockJobSetSpeed(dom, path, bandwidth, flags) < 0)
         return false;

     return true;
@@ -2672,8 +2677,6 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
     VSH_EXCLUSIVE_OPTIONS("bytes", "abort");
     VSH_EXCLUSIVE_OPTIONS_VAR(bytes, pivot);
     VSH_EXCLUSIVE_OPTIONS_VAR(bytes, async);
-    /* XXX also support --bytes with bandwidth mode */
-    VSH_EXCLUSIVE_OPTIONS_VAR(bytes, bandwidth);

     if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
         goto cleanup;
@@ -2683,7 +2686,7 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd)
         goto cleanup;

     if (bandwidth)
-        ret = virshBlockJobSetSpeed(ctl, cmd, dom, path);
+        ret = virshBlockJobSetSpeed(ctl, cmd, dom, path, bytes);
     else if (abortMode || pivot || async)
         ret = virshBlockJobAbort(dom, path, pivot, async);
     else
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 1e2c6a6..edb9ce5 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1152,10 +1152,15 @@ not supply bytes/s resolution; when omitting the flag, raw output is
 listed in MiB/s and human-readable output automatically selects the
 best resolution supported by the server.

-I<bandwidth> can be used to set bandwidth limit for the active job.
-Specifying a negative value is interpreted as an unsigned long long
+I<bandwidth> can be used to set bandwidth limit for the active job in MiB/s.
+If I<--bytes> is specified then the bandwidth value is interpreted in
+bytes/s. Specifying a negative value is interpreted as an unsigned long
 value or essentially unlimited. The hypervisor can choose whether to
-reject the value or convert it to the maximum value allowed.
+reject the value or convert it to the maximum value allowed. Optionally a
+scaled positive number may be used as bandwidth (see B<NOTES> above). Using
+I<--bytes> with a scaled value allows to use finer granularity. A scaled value
+used without I<--bytes> will be rounded down to MiB/s. Note that the
+I<--bytes> may be unsupported by the hypervisor.

 =item B<blockresize> I<domain> I<path> I<size>

diff --git a/tools/vsh.c b/tools/vsh.c
index cbe8189..f90619d 100644
--- a/tools/vsh.c
+++ b/tools/vsh.c
@@ -1201,6 +1201,58 @@ vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd,
 }


+/**
+ * vshBlockJobOptionBandwidth
+ * @ctl: virsh control data
+ * @cmd: virsh command description
+ * @bytes: return bandwidth in bytes/s instead of MiB/s
+ * @bandwidth: return value
+ *
+ * Extracts the value of --bandwidth either as a wrappable number without scale
+ * or as a scaled integer. The returned value is checked to fit into a unsigned
+ * long data type. This is a legacy compatibility function and it should not
+ * be used for things other the block job APIs.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+vshBlockJobOptionBandwidth(vshControl *ctl,
+                           const vshCmd *cmd,
+                           bool bytes,
+                           unsigned long *bandwidth)
+{
+    vshCmdOpt *arg;
+    char *end;
+    unsigned long long bw;
+    int ret;
+
+    if ((ret = vshCommandOpt(cmd, "bandwidth", &arg, true)) <= 0)
+        return ret;
+
+    /* due to historical reasons we declare to parse negative numbers and wrap
+     * them to the unsigned data type. */
+    if (virStrToLong_ul(arg->data, NULL, 10, bandwidth) < 0) {
+        /* try to parse the number as scaled size in this cas we don't accept
+         * wrapping since it would be ridiculous. In case of a 32 bit host,
+         * limit the value to ULONG_MAX */
+        if (virStrToLong_ullp(arg->data, &end, 10, &bw) < 0 ||
+            virScaleInteger(&bw, end, 1, ULONG_MAX) < 0) {
+            vshError(ctl,
+                     _("Scaled numeric value '%s' for <--bandwidth> option is "
+                       "malformed or out of range"), arg->data);
+            return -1;
+        }
+
+        if (!bytes)
+            bw >>= 20;
+
+        *bandwidth = bw;
+    }
+
+    return 0;
+}
+
+
 /*
  * Executes command(s) and returns return code from last command
  */
diff --git a/tools/vsh.h b/tools/vsh.h
index f6e40e6..f738a6f 100644
--- a/tools/vsh.h
+++ b/tools/vsh.h
@@ -291,6 +291,10 @@ int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd,
                            const char *name, unsigned long long *value,
                            int scale, unsigned long long max)
     ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+int vshBlockJobOptionBandwidth(vshControl *ctl,
+                               const vshCmd *cmd,
+                               bool bytes,
+                               unsigned long *bandwidth);
 bool vshCommandOptBool(const vshCmd *cmd, const char *name);
 bool vshCommandRun(vshControl *ctl, const vshCmd *cmd);
 bool vshCommandStringParse(vshControl *ctl, char *cmdstr);
-- 
2.7.3




More information about the libvir-list mailing list