summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvmallika <vmallika@redhat.com>2015-04-15 17:35:07 +0530
committerVijay Bellur <vbellur@redhat.com>2015-05-04 03:46:08 -0700
commit821b1fdc893c0dd603d4c43a0b31f1ea495a46c9 (patch)
treea8593c6bc0b1ecbd58350b071b7ae4b5658ea57d
parent40df2ed4d098d4cd2c6abbed23e497ac3e2e5804 (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.c3
-rw-r--r--cli/src/cli-cmd-volume.c81
-rw-r--r--cli/src/cli-cmd.h2
-rw-r--r--cli/src/cli-rpc-ops.c22
-rw-r--r--libglusterfs/src/common-utils.c45
-rw-r--r--libglusterfs/src/common-utils.h6
-rw-r--r--libglusterfs/src/glusterfs.h1
-rw-r--r--libglusterfs/src/quota-common-utils.c154
-rw-r--r--libglusterfs/src/quota-common-utils.h27
-rw-r--r--tests/bugs/quota/bug-1202244-support-inode-quota.t41
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quota.c167
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c118
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h6
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