[libvirt] [PATCH 1/4] vcpupin: improve vcpupin definition of virsh vcpupin

Wen Congyang wency at cn.fujitsu.com
Mon Jun 20 09:18:34 UTC 2011


At 06/20/2011 02:46 PM, Daniel Veillard Write:
> On Fri, Jun 10, 2011 at 03:38:55PM +0900, Taku Izumi wrote:
>>
>> When using vcpupin command, we have to speficy comma-separated list as cpulist, 
>> but this is tedious in case the number of phsycal cpus is large.
>> This patch improves this by introducing special markup "-" and "^" which are 
>> similar to XML schema of "cpuset" attribute. 
>>
>> That is:
> 
>   The example
> 
>>  # virsh vcpupin Guest 0 0-15,^8
>>  
>>  is identical to
>>
>>  # virsh vcpupin Guest 0 0,1,2,3,4,5,6,7,9,10,11,12,13,14,15
>>
>> NOTE: The expression is sequencially evaluated, so "0-15,^8" is not identical

s/sequencially/sequentially/

>> to "^8,0-15".
> 
>   and this limitation should also be added to the virsh command doc I think
> 
>> Signed-off-by: Taku Izumi <izumi.taku at jp.fujitsu.com>
>> ---
>>  tools/virsh.c   |  125 +++++++++++++++++++++++++++++++-------------------------
>>  tools/virsh.pod |    4 +
>>  2 files changed, 73 insertions(+), 56 deletions(-)
>>
>> Index: libvirt/tools/virsh.c
>> ===================================================================
>> --- libvirt.orig/tools/virsh.c
>> +++ libvirt/tools/virsh.c
>> @@ -2946,8 +2946,9 @@ cmdVcpupin(vshControl *ctl, const vshCmd
>>      bool ret = true;
>>      unsigned char *cpumap;
>>      int cpumaplen;
>> -    int i;
>> -    enum { expect_num, expect_num_or_comma } state;
>> +    int i, cpu, lastcpu, maxcpu;
>> +    bool unuse = false;
>> +    char *cur;
>>      int config = vshCommandOptBool(cmd, "config");
>>      int live = vshCommandOptBool(cmd, "live");
>>      int current = vshCommandOptBool(cmd, "current");
>> @@ -3003,66 +3004,74 @@ cmdVcpupin(vshControl *ctl, const vshCmd
>>          return false;
>>      }
>>  
>> -    /* Check that the cpulist parameter is a comma-separated list of
>> -     * numbers and give an intelligent error message if not.
>> -     */
>> -    if (cpulist[0] == '\0') {
>> -        vshError(ctl, "%s", _("cpulist: Invalid format. Empty string."));
>> -        virDomainFree (dom);
>> -        return false;
>> -    }
>> +    maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo);
>> +    cpumaplen = VIR_CPU_MAPLEN(maxcpu);
>> +    cpumap = vshCalloc(ctl, 0, cpumaplen);
>> +
>> +    /* Parse cpulist */
>> +    cur = cpulist;
>> +    if (*cur == 0)
>> +        goto parse_error;
>> +
>> +    while (*cur != 0) {
>> +
>> +        /* the char '^' denotes exclusive */
>> +        if (*cur == '^') {
>> +            cur++;
>> +            unuse = true;
>> +        }
>> +
>> +        /* parse physical CPU number */
>> +        if (!c_isdigit(*cur))
>> +            goto parse_error;
>> +        cpu  = virParseNumber(&cur);
>> +        if (cpu < 0) {
>> +            goto parse_error;
>> +        }
>> +        if (cpu >= maxcpu) {
>> +            vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
>> +            goto parse_error;
>> +        }
>> +        virSkipSpaces(&cur);
>>  
>> -    state = expect_num;
>> -    for (i = 0; cpulist[i]; i++) {
>> -        switch (state) {
>> -        case expect_num:
>> -          if (!c_isdigit (cpulist[i])) {
>> -                vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
>> -                                "digit at position %d (near '%c')."),
>> -                         cpulist, i, cpulist[i]);
>> -                virDomainFree (dom);
>> -                return false;
>> +        if ((*cur == ',') || (*cur == 0)) {
>> +            if (unuse) {
>> +                VIR_UNUSE_CPU(cpumap, cpu);
>> +            } else {
>> +                VIR_USE_CPU(cpumap, cpu);
>>              }
>> -            state = expect_num_or_comma;
>> -            break;
>> -        case expect_num_or_comma:
>> -            if (cpulist[i] == ',')
>> -                state = expect_num;
>> -            else if (!c_isdigit (cpulist[i])) {
>> -                vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
>> -                                "digit or comma at position %d (near '%c')."),
>> -                         cpulist, i, cpulist[i]);
>> -                virDomainFree (dom);
>> -                return false;
>> +        } else if (*cur == '-') {
>> +            /* the char '-' denotes range */
>> +            if (unuse) {
>> +                goto parse_error;
>> +            }
>> +            cur++;
>> +            virSkipSpaces(&cur);
>> +            /* parse the end of range */
>> +            lastcpu = virParseNumber(&cur);
>> +            if (lastcpu < cpu) {
>> +                goto parse_error;
>> +            }
>> +            if (lastcpu >= maxcpu) {
>> +                vshError(ctl, _("Physical CPU %d doesn't exist."), maxcpu);
>> +                goto parse_error;
>> +            }
>> +            for (i = cpu; i <= lastcpu; i++) {
>> +                VIR_USE_CPU(cpumap, i);
>>              }
>> +            virSkipSpaces(&cur);
>>          }
>> -    }
>> -    if (state == expect_num) {
>> -        vshError(ctl, _("cpulist: %s: Invalid format. Trailing comma "
>> -                        "at position %d."),
>> -                 cpulist, i);
>> -        virDomainFree (dom);
>> -        return false;
>> -    }
>>  
>> -    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
>> -    cpumap = vshCalloc(ctl, 1, cpumaplen);
>> -
>> -    do {
>> -        unsigned int cpu = atoi(cpulist);
>> -
>> -        if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
>> -            VIR_USE_CPU(cpumap, cpu);
>> +        if (*cur == ',') {
>> +            cur++;
>> +            virSkipSpaces(&cur);
>> +            unuse = false;
>> +        } else if (*cur == 0) {
>> +            break;
>>          } else {
>> -            vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
>> -            VIR_FREE(cpumap);
>> -            virDomainFree(dom);
>> -            return false;
>> +            goto parse_error;
>>          }
>> -        cpulist = strchr(cpulist, ',');
>> -        if (cpulist)
>> -            cpulist++;
>> -    } while (cpulist);
>> +    }
>>  
>>      if (flags == -1) {
>>          if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
>> @@ -3074,9 +3083,15 @@ cmdVcpupin(vshControl *ctl, const vshCmd
>>          }
>>      }
>>  
>> +cleanup:
>>      VIR_FREE(cpumap);
>>      virDomainFree(dom);
>>      return ret;
>> +
>> +parse_error:
>> +    vshError(ctl, "%s", _("cpulist: Invalid format."));
>> +    ret = false;
>> +    goto cleanup;
>>  }
>>  
>>  /*
>> Index: libvirt/tools/virsh.pod
>> ===================================================================
>> --- libvirt.orig/tools/virsh.pod
>> +++ libvirt/tools/virsh.pod
>> @@ -794,7 +794,9 @@ vCPUs, the running time, the affinity to
>>  I<--current>
>>  
>>  Pin domain VCPUs to host physical CPUs. The I<vcpu> number must be provided
>> -and I<cpulist> is a comma separated list of physical CPU numbers.
>> +and I<cpulist> is a list of physical CPU numbers. Its syntax is a comma
>> +separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2') can
>> +also be allowed. The '-' denotes the range and the '^' denotes exclusive.
>>  If I<--live> is specified, affect a running guest.
>>  If I<--config> is specified, affect the next boot of a persistent guest.
>>  If I<--current> is specified, affect the current guest state.
> 
>   Okay, ACK, the point about having to generate the long comma list is
>   right and this seems like the right solution.

I have pushed it with this(add extra documentation in the virsh.pod):

>From bab581dce13850509b38beef0de329ef35e4c6d1 Mon Sep 17 00:00:00 2001
From: Taku Izumi <izumi.taku at jp.fujitsu.com>
Date: Fri, 10 Jun 2011 15:38:55 +0900
Subject: [PATCH] vcpupin: improve vcpupin definition of virsh vcpupin

When using vcpupin command, we have to speficy comma-separated list as cpulist,
but this is tedious in case the number of phsycal cpus is large.
This patch improves this by introducing special markup "-" and "^" which are
similar to XML schema of "cpuset" attribute.

The example:

 # virsh vcpupin Guest 0 0-15,^8

 is identical to

 # virsh vcpupin Guest 0 0,1,2,3,4,5,6,7,9,10,11,12,13,14,15

NOTE: The expression is sequencially evaluated, so "0-15,^8" is not identical
to "^8,0-15".

Signed-off-by: Taku Izumi <izumi.taku at jp.fujitsu.com>
---
 tools/virsh.c   |  125 +++++++++++++++++++++++++++++++------------------------
 tools/virsh.pod |    7 +++-
 2 files changed, 76 insertions(+), 56 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index b7b9552..92faffc 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -2998,8 +2998,9 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
     bool ret = true;
     unsigned char *cpumap;
     int cpumaplen;
-    int i;
-    enum { expect_num, expect_num_or_comma } state;
+    int i, cpu, lastcpu, maxcpu;
+    bool unuse = false;
+    char *cur;
     int config = vshCommandOptBool(cmd, "config");
     int live = vshCommandOptBool(cmd, "live");
     int current = vshCommandOptBool(cmd, "current");
@@ -3055,66 +3056,74 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
         return false;
     }
 
-    /* Check that the cpulist parameter is a comma-separated list of
-     * numbers and give an intelligent error message if not.
-     */
-    if (cpulist[0] == '\0') {
-        vshError(ctl, "%s", _("cpulist: Invalid format. Empty string."));
-        virDomainFree (dom);
-        return false;
-    }
+    maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo);
+    cpumaplen = VIR_CPU_MAPLEN(maxcpu);
+    cpumap = vshCalloc(ctl, 0, cpumaplen);
 
-    state = expect_num;
-    for (i = 0; cpulist[i]; i++) {
-        switch (state) {
-        case expect_num:
-          if (!c_isdigit (cpulist[i])) {
-                vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
-                                "digit at position %d (near '%c')."),
-                         cpulist, i, cpulist[i]);
-                virDomainFree (dom);
-                return false;
-            }
-            state = expect_num_or_comma;
-            break;
-        case expect_num_or_comma:
-            if (cpulist[i] == ',')
-                state = expect_num;
-            else if (!c_isdigit (cpulist[i])) {
-                vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
-                                "digit or comma at position %d (near '%c')."),
-                         cpulist, i, cpulist[i]);
-                virDomainFree (dom);
-                return false;
-            }
+    /* Parse cpulist */
+    cur = cpulist;
+    if (*cur == 0)
+        goto parse_error;
+
+    while (*cur != 0) {
+
+        /* the char '^' denotes exclusive */
+        if (*cur == '^') {
+            cur++;
+            unuse = true;
         }
-    }
-    if (state == expect_num) {
-        vshError(ctl, _("cpulist: %s: Invalid format. Trailing comma "
-                        "at position %d."),
-                 cpulist, i);
-        virDomainFree (dom);
-        return false;
-    }
 
-    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
-    cpumap = vshCalloc(ctl, 1, cpumaplen);
+        /* parse physical CPU number */
+        if (!c_isdigit(*cur))
+            goto parse_error;
+        cpu  = virParseNumber(&cur);
+        if (cpu < 0) {
+            goto parse_error;
+        }
+        if (cpu >= maxcpu) {
+            vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
+            goto parse_error;
+        }
+        virSkipSpaces(&cur);
 
-    do {
-        unsigned int cpu = atoi(cpulist);
+        if ((*cur == ',') || (*cur == 0)) {
+            if (unuse) {
+                VIR_UNUSE_CPU(cpumap, cpu);
+            } else {
+                VIR_USE_CPU(cpumap, cpu);
+            }
+        } else if (*cur == '-') {
+            /* the char '-' denotes range */
+            if (unuse) {
+                goto parse_error;
+            }
+            cur++;
+            virSkipSpaces(&cur);
+            /* parse the end of range */
+            lastcpu = virParseNumber(&cur);
+            if (lastcpu < cpu) {
+                goto parse_error;
+            }
+            if (lastcpu >= maxcpu) {
+                vshError(ctl, _("Physical CPU %d doesn't exist."), maxcpu);
+                goto parse_error;
+            }
+            for (i = cpu; i <= lastcpu; i++) {
+                VIR_USE_CPU(cpumap, i);
+            }
+            virSkipSpaces(&cur);
+        }
 
-        if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
-            VIR_USE_CPU(cpumap, cpu);
+        if (*cur == ',') {
+            cur++;
+            virSkipSpaces(&cur);
+            unuse = false;
+        } else if (*cur == 0) {
+            break;
         } else {
-            vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
-            VIR_FREE(cpumap);
-            virDomainFree(dom);
-            return false;
+            goto parse_error;
         }
-        cpulist = strchr(cpulist, ',');
-        if (cpulist)
-            cpulist++;
-    } while (cpulist);
+    }
 
     if (flags == -1) {
         if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
@@ -3126,9 +3135,15 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
         }
     }
 
+cleanup:
     VIR_FREE(cpumap);
     virDomainFree(dom);
     return ret;
+
+parse_error:
+    vshError(ctl, "%s", _("cpulist: Invalid format."));
+    ret = false;
+    goto cleanup;
 }
 
 /*
diff --git a/tools/virsh.pod b/tools/virsh.pod
index fa37442..b90f37e 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -833,13 +833,18 @@ vCPUs, the running time, the affinity to physical processors.
 I<--current>
 
 Pin domain VCPUs to host physical CPUs. The I<vcpu> number must be provided
-and I<cpulist> is a comma separated list of physical CPU numbers.
+and I<cpulist> is a list of physical CPU numbers. Its syntax is a comma
+separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2') can
+also be allowed. The '-' denotes the range and the '^' denotes exclusive.
 If I<--live> is specified, affect a running guest.
 If I<--config> is specified, affect the next boot of a persistent guest.
 If I<--current> is specified, affect the current guest state.
 Both I<--live> and I<--config> flags may be given, but I<--current> is exclusive.
 If no flag is specified, behavior is different depending on hypervisor.
 
+B<Note>: The expression is sequentially evaluated, so "0-15,^8" is not identical
+to "^8,0-15".
+
 =item B<vncdisplay> I<domain-id>
 
 Output the IP address and port number for the VNC display. If the information
-- 
1.7.1


> 
> Daniel
> 




More information about the libvir-list mailing list