[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH] openvz: fixed an config file parsing error



Resend the email below.


On Mon, Sep 1, 2014 at 8:28 PM, Hongbin Lu <hongbin034 gmail com> wrote:
The OpenVZ driver reported an error on parsing some OpenVZ config
parameters (e.g. diskspace). This issue is due to the driver made
two incorrect assumptions about the value of the parameters:
1. Assume paramaeter is just a number (e.g. 1024).
2. Assume the number is an integer.
Actually, an OpenVZ config parameter may consists of a scalar and
a unit, and the scalar is not necessary an integer (e.g. 2.2G).
This patch is for fixing this issue.
---
 src/openvz/openvz_conf.c |   99 ++++++++++++++++++++++++++++++++++++++++++++-
 src/openvz/openvz_conf.h |    6 +++
 2 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
index 856c9f5..7dba925 100644
--- a/src/openvz/openvz_conf.c
+++ b/src/openvz/openvz_conf.c
@@ -127,6 +127,42 @@ int openvzExtractVersion(struct openvz_driver *driver)
 }


+static int
+openvzParseParamUnit(char* str, openvzParamUnit *unit)
+{
+    int len = strlen(str);
+    if (len == 0)
+        return -1;
+
+    switch (str[len - 1]) {
+    case 'G':
+    case 'g':
+        str[len - 1] = '\0';
+        if (unit != NULL)
+            *unit = OPENVZ_PARAM_UNIT_GIGABYTE;
+        break;
+    case 'M':
+    case 'm':
+        str[len - 1] = '\0';
+        if (unit != NULL)
+            *unit = OPENVZ_PARAM_UNIT_MEGABYTE;
+        break;
+    case 'K':
+    case 'k':
+        str[len - 1] = '\0';
+        if (unit != NULL)
+            *unit = OPENVZ_PARAM_UNIT_KILOBYTE;
+        break;
+    case 'P':
+    case 'p':
+        str[len - 1] = '\0';
+        break;
+    }
+
+    return 0;
+}
+
+
 /* Parse config values of the form barrier:limit into barrier and limit */
 static int
 openvzParseBarrierLimit(const char* value,
@@ -146,7 +182,10 @@ openvzParseBarrierLimit(const char* value,
         goto error;
     } else {
         if (barrier != NULL) {
-            if (virStrToLong_ull(token, NULL, 10, barrier))
+            if (openvzParseParamUnit(token, NULL) < 0)
+                goto error;
+
+            if (virStrToLong_ull(token, NULL, 10, barrier) < 0)
                 goto error;
         }
     }
@@ -155,7 +194,10 @@ openvzParseBarrierLimit(const char* value,
         goto error;
     } else {
         if (limit != NULL) {
-            if (virStrToLong_ull(token, NULL, 10, limit))
+            if (openvzParseParamUnit(token, NULL) < 0)
+                goto error;
+
+            if (virStrToLong_ull(token, NULL, 10, limit) < 0)
                 goto error;
         }
     }
@@ -166,6 +208,57 @@ openvzParseBarrierLimit(const char* value,
 }


+static int
+openvzParseBarrierLimit2(const char* value,
+                         unsigned long long *barrier,
+                         unsigned long long *limit,
+                         openvzParamUnit targetunit)
+{
+    char *token;
+    char *saveptr = NULL;
+    char *str;
+    double dbarrier, dlimit;
+    openvzParamUnit unit = OPENVZ_PARAM_UNIT_KILOBYTE;
+    int ret = -1;
+
+    if (VIR_STRDUP(str, value) < 0)
+        goto error;
+
+    token = strtok_r(str, ":", &saveptr);
+    if (token == NULL)
+        goto error;
+
+    if (barrier != NULL) {
+        if (openvzParseParamUnit(token, &unit) < 0)
+            goto error;
+
+        if (virStrToDouble(token, NULL, &dbarrier) < 0)
+            goto error;
+
+        *barrier = (unsigned long long)(dbarrier * unit / targetunit);
+    }
+
+    token = strtok_r(NULL, ":", &saveptr);
+    if (token == NULL)
+        goto error;
+
+    if (limit != NULL) {
+        if (openvzParseParamUnit(token, &unit) < 0)
+            goto error;
+
+        if (virStrToDouble(token, NULL, &dlimit) < 0)
+            goto error;
+
+        *limit = (unsigned long long)(dlimit * unit / targetunit);
+    }
+
+    ret = 0;
+ error:
+    VIR_FREE(str);
+    return ret;
+}
+
+
 virCapsPtr openvzCapsInit(void)
 {
     virCapsPtr caps;
@@ -396,7 +489,7 @@ openvzReadFSConf(virDomainDefPtr def,
     param = "DISKSPACE";
     ret = openvzReadVPSConfigParam(veid, param, &temp);
     if (ret > 0) {
-        if (openvzParseBarrierLimit(temp, &barrier, &limit)) {
+        if (openvzParseBarrierLimit2(temp, &barrier, &limit, OPENVZ_PARAM_UNIT_KILOBYTE)) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Could not read '%s' from config for container %d"),
                            param, veid);
diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h
index a7de7d2..788dae9 100644
--- a/src/openvz/openvz_conf.h
+++ b/src/openvz/openvz_conf.h
@@ -41,6 +41,12 @@

 # define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)

+typedef enum {
+    OPENVZ_PARAM_UNIT_KILOBYTE = 1,
+    OPENVZ_PARAM_UNIT_MEGABYTE = 1024,
+    OPENVZ_PARAM_UNIT_GIGABYTE = 1024 * 1024,
+} openvzParamUnit;
+
 struct openvz_driver {
     virMutex lock;

--
1.7.1



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]