diff options
author | vmallika <vmallika@redhat.com> | 2015-03-18 23:17:23 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2015-03-18 18:24:12 -0700 |
commit | 3e18f093974c85ac92a4c48f0cd13aa9ff9c5cac (patch) | |
tree | 6bbdd814492a3e7dcf6e9a06f49a373926f970dd /xlators/cluster/dht/src | |
parent | fa50fcb6dddf4d7d0094c26cee802fd942f62727 (diff) |
features/quota : Introducing inode quota
==========================================================================
Inode quota
==========================================================================
= Currently, the only way to retrieve the number of files/objects in a =
= directory or volume is to do a crawl of the entire directory/volume. =
= This is expensive and is not scalable. =
= =
= The proposed mechanism will provide an easier alternative to determine =
= the count of files/objects in a directory or volume. =
= =
= The new mechanism proposes to store count of objects/files as part of =
= an extended attribute of a directory. Each directory's extended =
= attribute value will indicate the number of files/objects present =
= in a tree with the directory being considered as the root of the tree. =
= =
= The count value can be accessed by performing a getxattr(). =
= Cluster translators like afr, dht and stripe will perform aggregation =
= of count values from various bricks when getxattr() happens on the key =
= associated with file/object count. =
A new interface is introduced:
------------------------------
limit-objects : limit the number of inodes at directory level
list-objects : list the directories where the limit is set
remove-objects : remove the limit from the directory
==========================================================================
CLI COMMAND:
gluster volume quota <volname> limit-objects <path> <number> [<percent>]
* <number> is a hard-limit for number of objects limitation for path "<path>"
If hard-limit is exceeded, creation of file/directory is no longer
permitted.
* <percent> is a soft-limit for number of objects creation for path "<path>"
If soft-limit is exceeded, a warning is issued for each creation.
CLI COMMAND:
gluster volume quota <volname> remove-objects [path]
==========================================================================
CLI COMMAND:
gluster volume quota <volname> list-objects [path] ...
Sample output:
------------------
Path Hard-limit Soft-limit Used Available
Soft-limit exceeded?
Hard-limit exceeded?
------------------------------------------------------------------------
--------------------------------------
/dir 10 80% 10 0
Yes
Yes
==========================================================================
[root@snapshot-28 dir]# ls
a b file11 file12 file13 file14 file15 file16 file17
[root@snapshot-28 dir]# touch a1
touch: cannot touch `a1': Disk quota exceeded
* Nine files are created in directory "dir" and directory is included in
* the
count too. Hence the limit "10" is reached and further file creation
fails
==========================================================================
Note: We have also done some re-factoring in cli for volume name
validation. New function cli_validate_volname is created
==========================================================================
Change-Id: I1823497de4f790a2a20ebb1770293472ea33ee2b
BUG: 1190108
Signed-off-by: Sachin Pandit <spandit@redhat.com>
Signed-off-by: vmallika <vmallika@redhat.com>
Reviewed-on: http://review.gluster.org/9769
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators/cluster/dht/src')
-rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 115 |
1 files changed, 81 insertions, 34 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index 729ab30e672..9fda4aa07d6 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -23,6 +23,7 @@ #include "defaults.h" #include "byte-order.h" #include "glusterfs-acl.h" +#include "quota-common-utils.h" #include <sys/time.h> #include <libgen.h> @@ -31,47 +32,90 @@ int dht_link2 (xlator_t *this, call_frame_t *frame, int op_ret); int -dht_aggregate (dict_t *this, char *key, data_t *value, void *data) +dht_aggregate_quota_xattr (dict_t *dst, char *key, data_t *value) { - dict_t *dst = NULL; - int64_t *ptr = 0, *size = NULL; - int32_t ret = -1; - data_t *dict_data = NULL; - - dst = data; + int ret = -1; + quota_meta_t *meta_dst = NULL; + quota_meta_t *meta_src = NULL; + int64_t *size = NULL; + int64_t dst_dir_count = 0; + int64_t src_dir_count = 0; + + if (value == NULL) { + gf_log ("dht", GF_LOG_WARNING, "data value is NULL"); + ret = -1; + goto out; + } - if (strcmp (key, GF_XATTR_QUOTA_SIZE_KEY) == 0) { - ret = dict_get_bin (dst, key, (void **)&size); + ret = dict_get_bin (dst, key, (void **)&meta_dst); + if (ret < 0) { + meta_dst = GF_CALLOC (1, sizeof (quota_meta_t), + gf_common_quota_meta_t); + if (meta_dst == NULL) { + gf_msg ("dht", GF_LOG_WARNING, 0, DHT_MSG_NO_MEMORY, + "Memory allocation failed"); + ret = -1; + goto out; + } + ret = dict_set_bin (dst, key, meta_dst, + sizeof (quota_meta_t)); if (ret < 0) { - size = GF_CALLOC (1, sizeof (int64_t), - gf_common_mt_char); - if (size == NULL) { - gf_msg ("dht", GF_LOG_WARNING, 0, - DHT_MSG_NO_MEMORY, - "Memory allocation failed"); - return -1; - } - ret = dict_set_bin (dst, key, size, sizeof (int64_t)); - if (ret < 0) { - gf_log ("dht", GF_LOG_WARNING, - "dht aggregate dict set failed"); - GF_FREE (size); - return -1; - } + gf_log ("dht", GF_LOG_WARNING, + "dht aggregate dict set failed"); + GF_FREE (meta_dst); + ret = -1; + goto out; } + } + + if (value->len > sizeof (int64_t)) { + meta_src = data_to_bin (value); + + meta_dst->size = hton64 (ntoh64 (meta_dst->size) + + ntoh64 (meta_src->size)); + meta_dst->file_count = hton64 (ntoh64 (meta_dst->file_count) + + ntoh64 (meta_src->file_count)); - ptr = data_to_bin (value); - if (ptr == NULL) { - gf_log ("dht", GF_LOG_WARNING, "data to bin failed"); - return -1; + if (value->len > (2 * sizeof (int64_t))) { + dst_dir_count = ntoh64 (meta_dst->dir_count); + src_dir_count = ntoh64 (meta_src->dir_count); + + if (src_dir_count > dst_dir_count) + meta_dst->dir_count = meta_src->dir_count; + } else { + meta_dst->dir_count = 0; } + } else { + size = data_to_bin (value); + meta_dst->size = hton64 (ntoh64 (meta_dst->size) + + ntoh64 (*size)); + } + + ret = 0; +out: + return ret; +} - *size = hton64 (ntoh64 (*size) + ntoh64 (*ptr)); +int +dht_aggregate (dict_t *this, char *key, data_t *value, void *data) +{ + dict_t *dst = NULL; + int32_t ret = -1; + data_t *dict_data = NULL; + + dst = data; + if (strcmp (key, QUOTA_SIZE_KEY) == 0) { + ret = dht_aggregate_quota_xattr (dst, key, value); + if (ret) { + gf_log ("dht", GF_LOG_WARNING, "Failed to " + "aggregate qutoa xattr"); + goto out; + } } else if (fnmatch (GF_XATTR_STIME_PATTERN, key, FNM_NOESCAPE) == 0) { ret = gf_get_min_stime (THIS, dst, key, value); if (ret < 0) - return ret; + goto out; } else { /* compare user xattrs only */ if (!strncmp (key, "user.", strlen ("user."))) { @@ -85,14 +129,17 @@ dht_aggregate (dict_t *this, char *key, data_t *value, void *data) } } ret = dict_set (dst, key, value); - if (ret) + if (ret) { gf_msg ("dht", GF_LOG_WARNING, 0, DHT_MSG_DICT_SET_FAILED, "Failed to set dictionary value: key = %s", key); + } } - return 0; + ret = 0; +out: + return ret; } @@ -255,7 +302,6 @@ selfheal: } - int dht_discover_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, int op_errno, @@ -2896,7 +2942,8 @@ dht_getxattr (call_frame_t *frame, xlator_t *this, return 0; } - if (key && !strcmp (GF_XATTR_QUOTA_LIMIT_LIST, key)) { + if (key && (!strcmp (GF_XATTR_QUOTA_LIMIT_LIST, key) || + !strcmp (GF_XATTR_QUOTA_LIMIT_LIST_OBJECT, key))) { /* quota hardlimit and aggregated size of a directory is stored * in inode contexts of each brick. Hence its good enough that * we send getxattr for this key to any brick. |