quota/cli: validate quota hard-limit option
authorvmallika <vmallika@redhat.com>
Wed, 1 Apr 2015 11:26:00 +0000 (16:56 +0530)
committerVijay Bellur <vbellur@redhat.com>
Fri, 10 Apr 2015 11:21:48 +0000 (11:21 +0000)
Quota hard-limit is supported only upto: 9223372036854775807 (int 64)

In CLI, it is allowed to set the value upto 16384PB (unsigned int 64),
this is not a valid value as the xattrop for quota accounting and
the quota enforcer operates on a signed int64 limit value.

This patches fixes the problem in CLI and allows user to set
the hard-limit value only from range 0 - 9223372036854775807

Change-Id: Ifce6e509e1832ef21d3278bacfa5bd71040c8cba
BUG: 1206432
Signed-off-by: vmallika <vmallika@redhat.com>
Reviewed-on: http://review.gluster.org/10022
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Kaushal M <kaushal@redhat.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
cli/src/cli-cmd-parser.c
libglusterfs/src/common-utils.c
libglusterfs/src/common-utils.h
xlators/mgmt/glusterd/src/glusterd-quota.c

index da60cde66d9b150bf41ea492b6b625d408c02be4..a8e09a466315c384600a0e375c4a938553318444 100644 (file)
@@ -906,7 +906,7 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
         int              ret     = -1;
         int              i       = -1;
         char             key[20] = {0, };
-        uint64_t         value   = 0;
+        int64_t          value   = 0;
         gf_quota_type    type    = GF_QUOTA_OPTION_TYPE_NONE;
         char           *opwords[] = { "enable", "disable", "limit-usage",
                                       "remove", "list", "alert-time",
@@ -1004,11 +1004,12 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
                 }
 
                 if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) {
-                        ret = gf_string2bytesize_uint64 (words[5], &value);
-                        if (ret != 0) {
-                                if (errno == ERANGE)
-                                        cli_err ("Value too large: %s",
-                                                 words[5]);
+                        ret = gf_string2bytesize_int64 (words[5], &value);
+                        if (ret != 0 || value < 0) {
+                                if (errno == ERANGE || value < 0)
+                                        cli_err ("Value out of range "
+                                                 "(0 - %"PRId64 "): %s",
+                                                 INT64_MAX, words[5]);
                                 else
                                         cli_err ("Please enter a correct "
                                                  "value");
index 6c5f65f6987ed228b1cad74893e4daef70b29212..b57066d41da257982bf2eb09daeda02954b52730 100644 (file)
@@ -1450,13 +1450,17 @@ err:
 int
 gf_string2bytesize_range (const char *str, uint64_t *n, uint64_t max)
 {
-        double value = 0.0;
-        char *tail = NULL;
-        int old_errno = 0;
-        const char *s = NULL;
+        double        value      = 0.0;
+        uint64_t      int_value  = 0;
+        uint64_t      unit       = 0;
+        char         *tail       = NULL;
+        int           old_errno  = 0;
+        const char   *s          = NULL;
+        gf_boolean_t  fraction   = _gf_false;
 
         if (str == NULL || n == NULL) {
-                gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid");
+                gf_log_callingfn (THIS->name, GF_LOG_WARNING,
+                                  "argument invalid");
                 errno = EINVAL;
                 return -1;
         }
@@ -1469,9 +1473,16 @@ gf_string2bytesize_range (const char *str, uint64_t *n, uint64_t max)
                 break;
         }
 
+        if (strrchr (str, '.'))
+                fraction = _gf_true;
+
         old_errno = errno;
         errno = 0;
-        value = strtod (str, &tail);
+        if (fraction)
+                value = strtod (str, &tail);
+        else
+                int_value = strtoll (str, &tail, 10);
+
         if (str == tail)
                 errno = EINVAL;
 
@@ -1484,25 +1495,39 @@ gf_string2bytesize_range (const char *str, uint64_t *n, uint64_t max)
         if (tail[0] != '\0')
         {
                 if (strcasecmp (tail, GF_UNIT_KB_STRING) == 0)
-                        value *= GF_UNIT_KB;
+                        unit = GF_UNIT_KB;
                 else if (strcasecmp (tail, GF_UNIT_MB_STRING) == 0)
-                        value *= GF_UNIT_MB;
+                        unit = GF_UNIT_MB;
                 else if (strcasecmp (tail, GF_UNIT_GB_STRING) == 0)
-                        value *= GF_UNIT_GB;
+                        unit = GF_UNIT_GB;
                 else if (strcasecmp (tail, GF_UNIT_TB_STRING) == 0)
-                        value *= GF_UNIT_TB;
+                        unit = GF_UNIT_TB;
                 else if (strcasecmp (tail, GF_UNIT_PB_STRING) == 0)
-                        value *= GF_UNIT_PB;
+                        unit = GF_UNIT_PB;
                 else if (strcasecmp (tail, GF_UNIT_B_STRING) != 0)
                         return -1;
-        }
 
-        if ((max - value) < 0) {
-                errno = ERANGE;
-                return -1;
+                if (unit > 0) {
+                        if (fraction)
+                                value *= unit;
+                        else
+                                int_value *= unit;
+                }
         }
 
-        *n = (uint64_t) value;
+        if (fraction) {
+                if ((max - value) < 0) {
+                        errno = ERANGE;
+                        return -1;
+                }
+                *n = (uint64_t) value;
+        } else {
+                if ((max - int_value) < 0) {
+                        errno = ERANGE;
+                        return -1;
+                }
+                *n = int_value;
+        }
 
         return 0;
 }
@@ -1529,6 +1554,17 @@ gf_string2bytesize_uint64 (const char *str, uint64_t *n)
         return gf_string2bytesize_range(str, n, UINT64_MAX);
 }
 
+int
+gf_string2bytesize_int64 (const char *str, int64_t *n)
+{
+        uint64_t u64 = 0;
+        int      ret = 0;
+
+        ret = gf_string2bytesize_range(str, &u64, INT64_MAX);
+        *n = (int64_t) u64;
+        return ret;
+}
+
 int
 gf_string2percent_or_bytesize (const char *str, double *n,
                               gf_boolean_t *is_percent)
index ec7e772e6cba43d4be9e1996e13b0f2d11b44ddd..a93c6233a4eb8c5fe0eecd2de41fea4920639c63 100644 (file)
@@ -604,6 +604,7 @@ int gf_string2uint64_base10 (const char *str, uint64_t *n);
 int gf_string2bytesize (const char *str, uint64_t *n);
 int gf_string2bytesize_size (const char *str, size_t *n);
 int gf_string2bytesize_uint64 (const char *str, uint64_t *n);
+int gf_string2bytesize_int64 (const char *str, int64_t *n);
 int gf_string2percent_or_bytesize (const char *str, double *n,
                                   gf_boolean_t *is_percent);
 
index 08e5d97a26b3cf8637911fc5b46b3108176d07cf..a137e82b230d8163a825bd7b31667c8757db1580 100644 (file)
@@ -500,7 +500,7 @@ glusterd_set_quota_limit (char *volname, char *path, char *hard_limit,
 
         new_limit.sl = hton64 (new_limit.sl);
 
-        ret = gf_string2bytesize_uint64 (hard_limit, (uint64_t*)&new_limit.hl);
+        ret = gf_string2bytesize_int64 (hard_limit, &new_limit.hl);
         if (ret)
                 goto out;
 
@@ -1370,8 +1370,8 @@ glusterd_op_stage_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
         glusterd_conf_t    *priv           = NULL;
         glusterd_volinfo_t *volinfo        = NULL;
         char               *hard_limit_str = NULL;
-        uint64_t           hard_limit      = 0;
-        gf_boolean_t       get_gfid        = _gf_false;
+        int64_t             hard_limit     = 0;
+        gf_boolean_t        get_gfid       = _gf_false;
 
         this = THIS;
         GF_ASSERT (this);
@@ -1460,20 +1460,16 @@ glusterd_op_stage_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
                                 "Faild to get hard-limit from dict");
                         goto out;
                 }
-                ret = gf_string2bytesize_uint64 (hard_limit_str, &hard_limit);
+                ret = gf_string2bytesize_int64 (hard_limit_str, &hard_limit);
                 if (ret) {
-                        gf_log (this->name, GF_LOG_ERROR,
-                                "Failed to convert hard-limit string to value");
-                        goto out;
-                }
-                if (hard_limit > UINT64_MAX) {
-                        ret = -1;
-                        ret = gf_asprintf (op_errstr, "Hard-limit %s is greater"
-                                           " than %"PRId64"bytes. Please set a "
-                                           "smaller limit.", hard_limit_str,
-                                           INT64_MAX);
-                        gf_log (this->name, GF_LOG_ERROR, "hard-limit %s "
-                                "greater than INT64_MAX", hard_limit_str);
+                        if (errno == ERANGE || hard_limit < 0)
+                                gf_asprintf (op_errstr, "Hard-limit "
+                                        "value out of range (0 - %"PRId64
+                                        "): %s", hard_limit_str);
+                        else
+                                gf_log (this->name, GF_LOG_ERROR,
+                                        "Failed to convert hard-limit "
+                                        "from string to bytes");
                         goto out;
                 }
                 get_gfid = _gf_true;