diff options
author | vmallika <vmallika@redhat.com> | 2015-04-15 17:35:07 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2015-05-04 03:46:08 -0700 |
commit | 821b1fdc893c0dd603d4c43a0b31f1ea495a46c9 (patch) | |
tree | a8593c6bc0b1ecbd58350b071b7ae4b5658ea57d | |
parent | 40df2ed4d098d4cd2c6abbed23e497ac3e2e5804 (diff) |
quota: support for inode quota in quota.conf
Currently when quota limit is set, corresponding gfid
is set in quota.conf. This patch supports storing
inode-quota limits in quota.conf and also stores
additional byte for each gfid to differentiate
between usage quota limit and inode quota limit.
Change-Id: I444d7399407594edd280e640681679a784d4c46a
BUG: 1202244
Signed-off-by: vmallika <vmallika@redhat.com>
Signed-off-by: Sachin Pandit <spandit@redhat.com>
Reviewed-on: http://review.gluster.org/10069
Tested-by: NetBSD Build System
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-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 |