diff options
| -rw-r--r-- | cli/src/cli-cmd-parser.c | 3 | ||||
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 81 | ||||
| -rw-r--r-- | cli/src/cli-cmd.h | 2 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 22 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.c | 45 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.h | 6 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/quota-common-utils.c | 154 | ||||
| -rw-r--r-- | libglusterfs/src/quota-common-utils.h | 27 | ||||
| -rw-r--r-- | tests/bugs/quota/bug-1202244-support-inode-quota.t | 41 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-quota.c | 167 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 118 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 6 | 
13 files changed, 515 insertions, 158 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 592df914d1b..65ccfcdcc5f 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1031,7 +1031,8 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)                  } else {                          errno = 0;                          limit = strtol (words[5], &end_ptr, 10); -                        if (errno == ERANGE || errno == EINVAL || limit <= 0) { +                        if (errno == ERANGE || errno == EINVAL || limit <= 0 +                                            || strcmp (end_ptr, "") != 0) {                                  ret = -1;                                  cli_err ("Please enter an interger value in "                                           "the range 1 - %"PRId64, INT64_MAX); diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index f73cb8bc3db..5e1cb75cbed 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1094,28 +1094,20 @@ out:          return ret;  } -#define QUOTA_CONF_HEADER                                                \ -        "GlusterFS Quota conf | version: v%d.%d\n" -int -cli_cmd_quota_conf_skip_header (int fd) -{ -        char buf[PATH_MAX] = {0,}; - -        snprintf (buf, sizeof(buf)-1, QUOTA_CONF_HEADER, 1, 1); -        return gf_skip_header_section (fd, strlen (buf)); -} -  /* Checks if at least one limit has been set on the volume   *   * Returns true if at least one limit is set. Returns false otherwise.   */  gf_boolean_t -_limits_set_on_volume (char *volname) { -        gf_boolean_t    limits_set = _gf_false; -        int             ret = -1; +_limits_set_on_volume (char *volname, int type) { +        gf_boolean_t    limits_set                = _gf_false; +        int             ret                       = -1;          char            quota_conf_file[PATH_MAX] = {0,}; -        int             fd = -1; -        char            buf[16] = {0,}; +        int             fd                        = -1; +        char            buf[16]                   = {0,}; +        float           version                   = 0.0f; +        char            gfid_type_stored          = 0; +        char            gfid_type                 = 0;          /* TODO: fix hardcoding; Need to perform an RPC call to glusterd           * to fetch working directory @@ -1127,17 +1119,31 @@ _limits_set_on_volume (char *volname) {          if (fd == -1)                  goto out; -        ret = cli_cmd_quota_conf_skip_header (fd); +        ret = quota_conf_read_version (fd, &version);          if (ret)                  goto out; -        /* Try to read atleast one gfid */ -        ret = read (fd, (void *)buf, 16); -        if (ret == 16) -                limits_set = _gf_true; +        if (type == GF_QUOTA_OPTION_TYPE_LIST) +                gfid_type = GF_QUOTA_CONF_TYPE_USAGE; +        else +                gfid_type = GF_QUOTA_CONF_TYPE_OBJECTS; + +        /* Try to read atleast one gfid  of type 'gfid_type' */ +        while (1) { +                ret = quota_conf_read_gfid (fd, buf, &gfid_type_stored, +                                            version); +                if (ret <= 0) +                        break; + +                if (gfid_type_stored == gfid_type) { +                        limits_set = _gf_true; +                        break; +                } +        }  out:          if (fd != -1)                  close (fd); +          return limits_set;  } @@ -1196,6 +1202,8 @@ cli_cmd_quota_handle_list_all (const char **words, dict_t *options)          gf_boolean_t             xml_err_flag   = _gf_false;          char                     err_str[NAME_MAX] = {0,};          int32_t                  type       = 0; +        char                     gfid_type  = 0; +        float                    version    = 0.0f;          xdata = dict_new ();          if (!xdata) { @@ -1231,9 +1239,11 @@ cli_cmd_quota_handle_list_all (const char **words, dict_t *options)          /* Check if at least one limit is set on volume. No need to check for           * quota enabled as cli_get_soft_limit() handles that           */ -        if (!_limits_set_on_volume (volname)) { -                snprintf (err_str, sizeof (err_str), "No quota configured on " -                          "volume %s", volname); +        if (!_limits_set_on_volume (volname, type)) { +                snprintf (err_str, sizeof (err_str), "No%s quota configured on" +                          " volume %s", +                          (type == GF_QUOTA_OPTION_TYPE_LIST) ? "" : " inode", +                          volname);                  if (global_state->mode & GLUSTER_MODE_XML) {                          xml_err_flag = _gf_true;                  } else { @@ -1282,10 +1292,10 @@ cli_cmd_quota_handle_list_all (const char **words, dict_t *options)                  goto out;           } -        ret = cli_cmd_quota_conf_skip_header (fd); -        if (ret) { +        ret = quota_conf_read_version (fd, &version); +        if (ret)                  goto out; -        } +          CLI_LOCAL_INIT (local, words, frame, xdata);          proc = &cli_quotad_clnt.proctable[GF_AGGREGATOR_GETLIMIT]; @@ -1307,18 +1317,21 @@ cli_cmd_quota_handle_list_all (const char **words, dict_t *options)                  goto out;          }          for (count = 0;; count++) { -                ret = read (fd, (void*) buf, 16); -                if (ret <= 0) { -                        //Finished reading all entries in the conf file +                ret = quota_conf_read_gfid (fd, buf, &gfid_type, version); +                if (ret == 0) {                          break; -                } -                if (ret < 16) { -                        //This should never happen. We must have a multiple of -                        //entry_sz bytes in our configuration file. +                } else if (ret < 0) {                          gf_log (THIS->name, GF_LOG_CRITICAL, "Quota "                                  "configuration store may be corrupt.");                          goto out;                  } + +                if ((type == GF_QUOTA_OPTION_TYPE_LIST && +                     gfid_type == GF_QUOTA_CONF_TYPE_OBJECTS) || +                    (type == GF_QUOTA_OPTION_TYPE_LIST_OBJECTS && +                     gfid_type == GF_QUOTA_CONF_TYPE_USAGE)) +                        continue; +                  uuid_utoa_r (buf, gfid_str);                  ret = dict_set_str (xdata, "gfid", gfid_str);                  if (ret) { diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h index d39c8b38f7f..94fa3e9c671 100644 --- a/cli/src/cli-cmd.h +++ b/cli/src/cli-cmd.h @@ -113,7 +113,7 @@ cli_cmd_get_confirmation (struct cli_state *state, const char *question);  int cli_cmd_sent_status_get (int *status);  gf_boolean_t -_limits_set_on_volume (char *volname); +_limits_set_on_volume (char *volname, int type);  gf_boolean_t  _quota_aux_mount_online (char *volname); diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 6bf03312afc..091608d8881 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -2675,7 +2675,7 @@ print_quota_list_object_output (cli_local_t *local, char *path, int64_t avail,                  goto out;          } -        cli_out ("%-40s %9"PRIu64" %9s %15"PRIu64" %10"PRIu64" %7"PRIu64 +        cli_out ("%-40s %9"PRIu64" %9s %10"PRIu64" %10"PRIu64" %11"PRIu64                   " %15s %20s", path, limits->hl, sl_str,                   used_space->file_count, used_space->dir_count,                   avail, sl ? "Yes" : "No", hl ? "Yes" : "No"); @@ -2847,12 +2847,20 @@ gf_cli_print_limit_list_from_dict (cli_local_t *local, char *volname,          if (!dict|| count <= 0)                  goto out; +        ret = dict_get_int32 (dict, "type", &type); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get quota type"); +                goto out; +        } +          /* Need to check if any quota limits are set on the volume before trying           * to list them           */ -        if (!_limits_set_on_volume (volname)) { -                snprintf (err_str, sizeof (err_str), "No quota configured on " -                          "volume %s", volname); +        if (!_limits_set_on_volume (volname, type)) { +                snprintf (err_str, sizeof (err_str), "No%s quota configured on " +                          "volume %s", +                          (type == GF_QUOTA_OPTION_TYPE_LIST) ? "" : " inode", +                          volname);                  if (global_state->mode & GLUSTER_MODE_XML) {                          xml_err_flag = _gf_true;                  } else { @@ -2868,12 +2876,6 @@ gf_cli_print_limit_list_from_dict (cli_local_t *local, char *volname,                  goto out;          } -        ret = dict_get_int32 (dict, "type", &type); -        if (ret) { -                gf_log ("cli", GF_LOG_ERROR, "Failed to get quota type"); -                goto out; -        } -          if (global_state->mode & GLUSTER_MODE_XML) {                  ret = cli_xml_output_vol_quota_limit_list_begin                                  (local, op_ret, op_errno, op_errstr); diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index b57066d41da..fc4ae123916 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -3939,3 +3939,48 @@ glusterfs_is_local_pathinfo (char *pathinfo, gf_boolean_t *is_local)  out:          return ret;  } + +ssize_t +gf_nread (int fd, void *buf, size_t count) +{ +        ssize_t  ret           = 0; +        ssize_t  read_bytes    = 0; + +        for (read_bytes = 0; read_bytes < count; read_bytes += ret) { +                ret = read (fd, buf + read_bytes, count - read_bytes); +                if (ret == 0) { +                        break; +                } else if (ret < 0) { +                        if (errno == EINTR) +                                ret = 0; +                        else +                                goto out; +                } +        } + +        ret = read_bytes; +out: +        return ret; +} + +ssize_t +gf_nwrite (int fd, const void *buf, size_t count) +{ +        ssize_t  ret        = 0; +        ssize_t  written    = 0; + +        for (written = 0; written != count; written += ret) { +                ret = write (fd, buf + written, count - written); +                if (ret < 0) { +                        if (errno == EINTR) +                                ret = 0; +                        else +                                goto out; +                } +        } + +        ret = written; +out: +        return ret; +} + diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 235db5fe34b..e8b5fc83591 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -719,4 +719,10 @@ glusterfs_is_local_pathinfo (char *pathinfo, gf_boolean_t *local);  int  gf_thread_cleanup_xint (pthread_t thread); +ssize_t +gf_nread (int fd, void *buf, size_t count); + +ssize_t +gf_nwrite (int fd, const void *buf, size_t count); +  #endif /* _COMMON_UTILS_H */ diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 9926d314874..50c86d91467 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -370,7 +370,6 @@ typedef enum {          GF_XATTROP_AND_ARRAY  } gf_xattrop_flags_t; -  typedef enum {          GF_UPCALL_EVENT_NULL,          GF_UPCALL_CACHE_INVALIDATION, diff --git a/libglusterfs/src/quota-common-utils.c b/libglusterfs/src/quota-common-utils.c index ab153209d0d..97965b09947 100644 --- a/libglusterfs/src/quota-common-utils.c +++ b/libglusterfs/src/quota-common-utils.c @@ -13,6 +13,7 @@  #include "logging.h"  #include "byte-order.h"  #include "quota-common-utils.h" +#include "common-utils.h"  int32_t  quota_data_to_meta (data_t *data, char *key, quota_meta_t *meta) @@ -112,3 +113,156 @@ out:          return ret;  } +int32_t +quota_conf_read_header (int fd, char *buf) +{ +        int    header_len      = 0; +        int    ret             = 0; + +        header_len = strlen (QUOTA_CONF_HEADER); + +        ret = gf_nread (fd, buf, header_len); +        if (ret <= 0) { +                goto out; +        } else if (ret > 0 && ret != header_len) { +                ret = -1; +                goto out; +        } + +        buf[header_len-1] = 0; + +out: +        if (ret < 0) +                gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to read " +                                  "header from a quota conf"); + +        return ret; +} + +int32_t +quota_conf_read_version (int fd, float *version) +{ +        int    ret             = 0; +        char   buf[PATH_MAX]   = ""; +        char  *tail            = NULL; +        float  value           = 0.0f; + +        ret = quota_conf_read_header (fd, buf); +        if (ret == 0) { +                /* quota.conf is empty */ +                value = GF_QUOTA_CONF_VERSION; +                goto out; +        } else if (ret < 0) { +                goto out; +        } + +        value = strtof ((buf + strlen(buf) - 3), &tail); +        if (tail[0] != '\0') { +                ret = -1; +                gf_log_callingfn ("quota", GF_LOG_ERROR, "invalid quota conf " +                                  "version"); +                goto out; +        } + +        ret = 0; + +out: +        if (ret >= 0) +                *version = value; +        else +                gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to read " +                                  "version from a quota conf header"); + +        return ret; +} + +int32_t +quota_conf_write_header (int fd) +{ +        int    header_len    = 0; +        int    ret           = 0; + +        header_len = strlen (QUOTA_CONF_HEADER); + +        ret = gf_nwrite (fd, QUOTA_CONF_HEADER, header_len); +        if (ret != header_len) { +                ret = -1; +                goto out; +        } + +        ret = 0; + +out: +        if (ret < 0) +                gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to write " +                                  "header to a quota conf"); + +        return ret; +} + +int32_t +quota_conf_write_gfid (int fd, void *buf, char type) +{ +        int ret        = 0; + +        ret = gf_nwrite (fd, buf, 16); +        if (ret != 16) { +                ret = -1; +                goto out; +        } + +        ret = gf_nwrite (fd, &type, 1); +        if (ret != 1) { +                ret = -1; +                goto out; +        } + +        ret = 0; + +out: +        if (ret < 0) +                gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to write " +                                  "gfid %s to a quota conf", uuid_utoa (buf)); + +        return ret; +} + +int32_t +quota_conf_read_gfid (int fd, void *buf, char *type, float version) +{ +        int           ret         = 0; + +        ret = gf_nread (fd, buf, 16); +        if (ret <= 0) +                goto out; + +        if (ret != 16) { +                ret = -1; +                goto out; +        } + +        if (version >= 1.2f) { +                ret = gf_nread (fd, type, 1); +                if (ret != 1) { +                        ret = -1; +                        goto out; +                } +                ret = 17; +        } else { +                *type = GF_QUOTA_CONF_TYPE_USAGE; +        } + +out: +        if (ret < 0) +                gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to read " +                                  "gfid from a quota conf"); + +        return ret; +} + +int32_t +quota_conf_skip_header (int fd) +{ +        return gf_skip_header_section (fd, strlen (QUOTA_CONF_HEADER)); +} + diff --git a/libglusterfs/src/quota-common-utils.h b/libglusterfs/src/quota-common-utils.h index eff86850dd5..e80c74cba72 100644 --- a/libglusterfs/src/quota-common-utils.h +++ b/libglusterfs/src/quota-common-utils.h @@ -13,6 +13,15 @@  #include "iatt.h" +#define GF_QUOTA_CONF_VERSION 1.2 +#define QUOTA_CONF_HEADER                           \ +        "GlusterFS Quota conf | version: v1.2\n" + +typedef enum { +        GF_QUOTA_CONF_TYPE_USAGE = 1, +        GF_QUOTA_CONF_TYPE_OBJECTS +} gf_quota_conf_type_t; +  struct _quota_limits {          int64_t hl;          int64_t sl; @@ -36,4 +45,22 @@ int32_t  quota_dict_set_meta (dict_t *dict, char *key, const quota_meta_t *meta,                       ia_type_t ia_type); +int32_t +quota_conf_read_header (int fd, char *buf); + +int32_t +quota_conf_read_version (int fd, float *version); + +int32_t +quota_conf_write_header (int fd); + +int32_t +quota_conf_write_gfid (int fd, void *buf, char type); + +int32_t +quota_conf_read_gfid (int fd, void *buf, char *type, float version); + +int32_t +quota_conf_skip_header (int fd); +  #endif /* _QUOTA_COMMON_UTILS_H */ diff --git a/tests/bugs/quota/bug-1202244-support-inode-quota.t b/tests/bugs/quota/bug-1202244-support-inode-quota.t new file mode 100644 index 00000000000..cd8fa94b643 --- /dev/null +++ b/tests/bugs/quota/bug-1202244-support-inode-quota.t @@ -0,0 +1,41 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +function get_quota_value() +{ +        local LIST_TYPE=$1 +        local LIMIT_PATH=$2; +        $CLI volume quota $V0 $LIST_TYPE $LIMIT_PATH | grep "$LIMIT_PATH"\ +                                                     | awk '{print $2}' +} + +cleanup; + +TEST glusterd; +TEST pidof glusterd; + +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2}; +TEST $CLI volume start $V0; +TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0; + +TEST $CLI volume quota $V0 enable; +EXPECT "on" volinfo_field $V0 'features.quota' +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" quotad_up_status; + +TEST mkdir $M0/dir; + +TEST $CLI volume quota $V0 limit-usage /dir 10MB; +EXPECT "10.0MB" get_quota_value "list" "/dir" + +TEST $CLI volume quota $V0 limit-objects /dir 10; +EXPECT "10" get_quota_value "list-objects" "/dir" + +TEST $CLI volume quota $V0 remove /dir; +EXPECT "" get_quota_value "list" "/dir" + +TEST $CLI volume quota $V0 remove-objects /dir; +EXPECT "" get_quota_value "list-objects" "/dir" + +cleanup; diff --git a/xlators/mgmt/glusterd/src/glusterd-quota.c b/xlators/mgmt/glusterd/src/glusterd-quota.c index 97fa4380656..9f2aa8ec9de 100644 --- a/xlators/mgmt/glusterd/src/glusterd-quota.c +++ b/xlators/mgmt/glusterd/src/glusterd-quota.c @@ -578,28 +578,33 @@ glusterd_update_quota_conf_version (glusterd_volinfo_t *volinfo)   * and continue the search.   */  static gf_boolean_t -glusterd_find_gfid_match (uuid_t gfid, unsigned char *buf, size_t bytes_read, -                          int opcode, size_t *write_byte_count) +glusterd_find_gfid_match (uuid_t gfid, char gfid_type, unsigned char *buf, +                          size_t bytes_read, int opcode, +                          size_t *write_byte_count)  {          int           gfid_index  = 0;          int           shift_count = 0;          unsigned char tmp_buf[17] = {0,}; +        char          type        = 0;          while (gfid_index != bytes_read) {                  memcpy ((void *)tmp_buf, (void *)&buf[gfid_index], 16); -                if (!gf_uuid_compare (gfid, tmp_buf)) { -                        if (opcode == GF_QUOTA_OPTION_TYPE_REMOVE) { -                                shift_count = bytes_read - (gfid_index + 16); +                type = buf[gfid_index + 16]; + +                if (!gf_uuid_compare (gfid, tmp_buf) && type == gfid_type) { +                        if (opcode == GF_QUOTA_OPTION_TYPE_REMOVE || +                            opcode == GF_QUOTA_OPTION_TYPE_REMOVE_OBJECTS) { +                                shift_count = bytes_read - (gfid_index + 17);                                  memmove ((void *)&buf[gfid_index], -                                         (void *)&buf[gfid_index+16], +                                         (void *)&buf[gfid_index + 17],                                           shift_count); -                                *write_byte_count = bytes_read - 16; +                                *write_byte_count = bytes_read - 17;                          } else {                                  *write_byte_count = bytes_read;                          }                          return _gf_true;                  } else { -                        gfid_index+=16; +                        gfid_index += 17;                  }          }          if (gfid_index == bytes_read) @@ -647,15 +652,91 @@ out:  }  int +glusterd_store_quota_conf_upgrade (glusterd_volinfo_t *volinfo) +{ +        int                ret                   = -1; +        int                fd                    = -1; +        int                conf_fd               = -1; +        unsigned char      gfid[17]              = {0,}; +        xlator_t          *this                  = NULL; +        char               type                  = 0; + +        this = THIS; +        GF_ASSERT (this); + +        fd = gf_store_mkstemp (volinfo->quota_conf_shandle); +        if (fd < 0) { +                ret = -1; +                goto out; +        } + +        conf_fd = open (volinfo->quota_conf_shandle->path, O_RDONLY); +        if (conf_fd == -1) { +                ret = -1; +                goto out; +        } + +        ret = quota_conf_skip_header (conf_fd); +        if (ret) +                goto out; + +        ret = quota_conf_write_header (fd); +        if (ret) +                goto out; + +        while (1) { +                ret = quota_conf_read_gfid (conf_fd, gfid, &type, 1.1); +                if (ret == 0) +                        break; +                else if (ret < 0) +                        goto out; + +                ret = quota_conf_write_gfid (fd, gfid, +                                             GF_QUOTA_CONF_TYPE_USAGE); +                if (ret < 0) +                        goto out; +        } + +out: +        if (conf_fd != -1) +                close (conf_fd); + +        if (ret && (fd > 0)) { +                gf_store_unlink_tmppath (volinfo->quota_conf_shandle); +        } else if (!ret) { +                ret = gf_store_rename_tmppath (volinfo->quota_conf_shandle); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to rename " +                                "quota conf file"); +                        return ret; +                } + +                ret = glusterd_compute_cksum (volinfo, _gf_true); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                "compute cksum for quota conf file"); +                        return ret; +                } + +                ret = glusterd_store_save_quota_version_and_cksum (volinfo); +                if (ret) +                        gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                "store quota version and cksum"); +        } + +        return ret; +} + +int  glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,                               char *gfid_str, int opcode, char **op_errstr)  {          int                ret                   = -1;          int                fd                    = -1;          int                conf_fd               = -1; -        size_t             entry_sz              = 131072; +        size_t             entry_sz              = 139264;          ssize_t            bytes_read            = 0; -        size_t            bytes_to_write         = 0; +        size_t             bytes_to_write        = 0;          unsigned char      buf[131072]           = {0,};          uuid_t             gfid                  = {0,};          xlator_t          *this                  = NULL; @@ -664,6 +745,8 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,          gf_boolean_t       is_file_empty         = _gf_false;          gf_boolean_t       is_first_read         = _gf_true;          glusterd_conf_t   *conf                  = NULL; +        float              version               = 0.0f; +        char               type                  = 0;          this = THIS;          GF_ASSERT (this); @@ -672,30 +755,43 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,          glusterd_store_create_quota_conf_sh_on_absence (volinfo); -        fd = gf_store_mkstemp (volinfo->quota_conf_shandle); -        if (fd < 0) { -                ret = -1; -                goto out; -        } -          conf_fd = open (volinfo->quota_conf_shandle->path, O_RDONLY);          if (conf_fd == -1) {                  ret = -1;                  goto out;          } -        ret = glusterd_store_quota_conf_skip_header (this, conf_fd); -        if (ret) { +        ret = quota_conf_read_version (conf_fd, &version); +        if (ret)                  goto out; + +        if (version < 1.2f) { +                close (conf_fd); +                ret = glusterd_store_quota_conf_upgrade(volinfo); +                if (ret) +                        goto out; + +                conf_fd = open (volinfo->quota_conf_shandle->path, O_RDONLY); +                if (conf_fd == -1) { +                        ret = -1; +                        goto out; +                } + +                ret = quota_conf_skip_header (conf_fd); +                if (ret) +                        goto out;          } -        ret = glusterd_store_quota_conf_stamp_header (this, fd); -        if (ret) { -                gf_log (this->name, GF_LOG_ERROR, "Failed to add header to tmp " -                        "file."); +        fd = gf_store_mkstemp (volinfo->quota_conf_shandle); +        if (fd < 0) { +                ret = -1;                  goto out;          } +        ret = quota_conf_write_header (fd); +        if (ret) +                goto out; +          /* Just create empty quota.conf file if create */          if (GF_QUOTA_OPTION_TYPE_ENABLE == opcode) {                  modified = _gf_true; @@ -709,6 +805,11 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,          }          gf_uuid_parse (gfid_str, gfid); +        if (opcode > GF_QUOTA_OPTION_TYPE_VERSION_OBJECTS) +                type = GF_QUOTA_CONF_TYPE_OBJECTS; +        else +                type = GF_QUOTA_CONF_TYPE_USAGE; +          for (;;) {                  bytes_read = read (conf_fd, (void*)&buf, entry_sz);                  if (bytes_read <= 0) { @@ -724,14 +825,14 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,                                  is_file_empty = _gf_true;                          break;                  } -                if ((bytes_read % 16) != 0) { +                if ((bytes_read % 17) != 0) {                          gf_log (this->name, GF_LOG_ERROR, "quota.conf "                                  "corrupted");                          ret = -1;                          goto out;                  } -                found = glusterd_find_gfid_match (gfid, buf, bytes_read, opcode, -                                                  &bytes_to_write); +                found = glusterd_find_gfid_match (gfid, type, buf, bytes_read, +                                                  opcode, &bytes_to_write);                  ret = write (fd, (void *) buf, bytes_to_write);                  if (ret == -1) { @@ -756,9 +857,23 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path,          switch (opcode) {          case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE: +                if (!found) { +                        ret = quota_conf_write_gfid (fd, gfid, +                                                     GF_QUOTA_CONF_TYPE_USAGE); +                        if (ret == -1) { +                                gf_log (this->name, GF_LOG_ERROR, +                                        "write into quota.conf failed. " +                                        "Reason : %s", +                                        strerror (errno)); +                                goto out; +                        } +                        modified = _gf_true; +                } +                break;          case GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS:                  if (!found) { -                        ret = write (fd, gfid, 16); +                        ret = quota_conf_write_gfid (fd, gfid, +                                                   GF_QUOTA_CONF_TYPE_OBJECTS);                          if (ret == -1) {                                  gf_log (this->name, GF_LOG_ERROR,                                          "write into quota.conf failed. " diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index c72c7266f16..31aabaf41d0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -61,6 +61,7 @@  #include "glusterd-quotad-svc.h"  #include "glusterd-snapd-svc.h"  #include "glusterd-bitd-svc.h" +#include "quota-common-utils.h"  #include "xdr-generic.h"  #include <sys/resource.h> @@ -2396,13 +2397,14 @@ int  glusterd_vol_add_quota_conf_to_dict (glusterd_volinfo_t *volinfo, dict_t* load,                                       int vol_idx, char *prefix)  { -        int   fd                    = -1; -        char  *gfid_str             = NULL; -        unsigned char  buf[16]      = {0}; -        char  key[PATH_MAX]         = {0}; -        int   gfid_idx              = 0; -        int   ret                   = -1; -        xlator_t *this              = NULL; +        int            fd                    = -1; +        unsigned char  buf[16]               = {0}; +        char           key[PATH_MAX]         = {0}; +        int            gfid_idx              = 0; +        int            ret                   = -1; +        xlator_t      *this                  = NULL; +        char           type                  = 0; +        float          version               = 0.0f;          this = THIS;          GF_ASSERT (this); @@ -2418,40 +2420,31 @@ glusterd_vol_add_quota_conf_to_dict (glusterd_volinfo_t *volinfo, dict_t* load,                  goto out;          } -        ret = glusterd_store_quota_conf_skip_header (this, fd); +        ret = quota_conf_read_version (fd, &version);          if (ret)                  goto out;          for (gfid_idx=0; ; gfid_idx++) { - -                ret = read (fd, (void*)&buf, 16) ; -                if (ret <= 0) { -                        //Finished reading all entries in the conf file +                ret = quota_conf_read_gfid (fd, buf, &type, version); +                if (ret == 0) {                          break; -                } -                if (ret != 16) { -                        //This should never happen. We must have a multiple of -                        //entry_sz bytes in our configuration file. +                } else if (ret < 0) {                          gf_log (this->name, GF_LOG_CRITICAL, "Quota "                                  "configuration store may be corrupt.");                          goto out;                  } -                gfid_str = gf_strdup (uuid_utoa (buf)); -                if (!gfid_str) { -                        ret = -1; -                        goto out; -                } -                  snprintf (key, sizeof(key)-1, "%s%d.gfid%d", prefix,                            vol_idx, gfid_idx); -                key[sizeof(key)-1] = '\0'; -                ret = dict_set_dynstr (load, key, gfid_str); -                if (ret) { +                ret = dict_set_dynstr_with_alloc (load, key, uuid_utoa (buf)); +                if (ret)                          goto out; -                } -                gfid_str = NULL; +                snprintf (key, sizeof(key)-1, "%s%d.gfid-type%d", prefix, +                          vol_idx, gfid_idx); +                ret = dict_set_int8 (load, key, type); +                if (ret) +                        goto out;          }          snprintf (key, sizeof(key)-1, "%s%d.gfid-count", prefix, vol_idx); @@ -2476,7 +2469,6 @@ glusterd_vol_add_quota_conf_to_dict (glusterd_volinfo_t *volinfo, dict_t* load,  out:          if (fd != -1)                  close (fd); -        GF_FREE (gfid_str);          return ret;  } @@ -2935,14 +2927,15 @@ glusterd_import_quota_conf (dict_t *peer_data, int vol_idx,                              glusterd_volinfo_t *new_volinfo,                              char *prefix)  { -        int     gfid_idx         = 0; -        int     gfid_count       = 0; -        int     ret              = -1; -        int     fd               = -1; -        char    key[PATH_MAX]    = {0}; -        char    *gfid_str        = NULL; -        uuid_t   gfid            = {0,}; -        xlator_t *this           = NULL; +        int       gfid_idx         = 0; +        int       gfid_count       = 0; +        int       ret              = -1; +        int       fd               = -1; +        char      key[PATH_MAX]    = {0}; +        char     *gfid_str         = NULL; +        uuid_t    gfid             = {0,}; +        xlator_t *this             = NULL; +        int8_t    gfid_type        = 0;          this = THIS;          GF_ASSERT (this); @@ -2984,33 +2977,34 @@ glusterd_import_quota_conf (dict_t *peer_data, int vol_idx,          if (ret)                  goto out; -        ret = glusterd_store_quota_conf_stamp_header (this, fd); -        if (ret) { -                gf_log (this->name, GF_LOG_ERROR, "Failed to add header to tmp " -                        "file"); +        ret = quota_conf_write_header (fd); +        if (ret)                  goto out; -        }          gfid_idx = 0;          for (gfid_idx = 0; gfid_idx < gfid_count; gfid_idx++) {                  snprintf (key, sizeof (key)-1, "%s%d.gfid%d",                            prefix, vol_idx, gfid_idx); -                key[sizeof(key)-1] = '\0';                  ret = dict_get_str (peer_data, key, &gfid_str);                  if (ret)                          goto out; +                snprintf (key, sizeof (key)-1, "%s%d.gfid-type%d", +                          prefix, vol_idx, gfid_idx); +                ret = dict_get_int8 (peer_data, key, &gfid_type); +                if (ret) +                        gfid_type = GF_QUOTA_CONF_TYPE_USAGE; +                  gf_uuid_parse (gfid_str, gfid); -                ret = write (fd, (void*)gfid, 16); -                if (ret != 16) { +                ret = quota_conf_write_gfid (fd, gfid, (char)gfid_type); +                if (ret < 0) {                          gf_log (this->name, GF_LOG_CRITICAL, "Unable to write "                                  "gfid %s into quota.conf for %s", gfid_str,                                  new_volinfo->volname);                          ret = -1;                          goto out;                  } -          }          ret = gf_store_rename_tmppath (new_volinfo->quota_conf_shandle); @@ -8952,40 +8946,6 @@ glusterd_clean_up_quota_store (glusterd_volinfo_t *volinfo)  } -#define QUOTA_CONF_HEADER                                                \ -        "GlusterFS Quota conf | version: v%d.%d\n" - -int -glusterd_store_quota_conf_skip_header (xlator_t *this, int fd) -{ -        char buf[PATH_MAX] = {0,}; - -        snprintf (buf, sizeof(buf)-1, QUOTA_CONF_HEADER, 1, 1); -        return gf_skip_header_section (fd, strlen (buf)); -} - -int -glusterd_store_quota_conf_stamp_header (xlator_t *this, int fd) -{ -        char buf[PATH_MAX]  = {0,}; -        int  buf_len        = 0; -        ssize_t  ret        = -1; -        ssize_t  written    = 0; - -        snprintf (buf, sizeof(buf)-1, QUOTA_CONF_HEADER, 1, 1); -        buf_len = strlen (buf); -        for (written = 0; written != buf_len; written += ret) { -                ret = write (fd, buf + written, buf_len - written); -                if (ret == -1) { -                        goto out; -                } -        } - -        ret = 0; -out: -        return ret; -} -  int  glusterd_remove_auxiliary_mount (char *volname)  { diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 59a07bacc1c..39c4442b72b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -536,12 +536,6 @@ void  glusterd_clean_up_quota_store (glusterd_volinfo_t *volinfo);  int -glusterd_store_quota_conf_skip_header (xlator_t *this, int fd); - -int -glusterd_store_quota_conf_stamp_header (xlator_t *this, int fd); - -int  glusterd_remove_auxiliary_mount (char *volname);  gf_boolean_t  | 
