diff options
author | Raghavendra G <raghavendra@gluster.com> | 2012-03-27 15:31:50 +0530 |
---|---|---|
committer | Vijay Bellur <vijay@gluster.com> | 2012-04-27 00:26:39 -0700 |
commit | 4213745eba97ffe1e2bdb13446fe2fd87e7c6fef (patch) | |
tree | 4a0f54d60f18a611688cf3522f8a3b50cdf9e55e /xlators | |
parent | ecb818902e4ee7491aaeae21226b62a0ab806370 (diff) |
features/quota: update inode ctx in reconfigure.
Till this patch, quota was relying on lookups after reconfigure, for
new limits to be effective. However, this might be restrictive for
users who don't want to change directories after resetting quota
limits.
Change-Id: I236aa31fdc7dcbc01d40d38c9b5b7b0a28a4d2ea
BUG: 802905
Signed-off-by: Raghavendra G <raghavendra@gluster.com>
Reviewed-on: http://review.gluster.com/3022
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Mohammed Junaid <junaid@redhat.com>
Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
Tested-by: Amar Tumballi <amarts@redhat.com>
Reviewed-by: Vijay Bellur <vijay@gluster.com>
Diffstat (limited to 'xlators')
-rw-r--r-- | xlators/features/quota/src/quota.c | 180 | ||||
-rw-r--r-- | xlators/features/quota/src/quota.h | 10 |
2 files changed, 159 insertions, 31 deletions
diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c index 436fb1b1cb1..7d5f74e9cc8 100644 --- a/xlators/features/quota/src/quota.c +++ b/xlators/features/quota/src/quota.c @@ -580,16 +580,20 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *dict, struct iatt *postparent) { - int32_t ret = -1; - char found = 0; - quota_local_t *local = NULL; - quota_inode_ctx_t *ctx = NULL; - quota_dentry_t *dentry = NULL; - int64_t *size = 0; - uint64_t value = 0; + int32_t ret = -1; + char found = 0; + quota_local_t *local = NULL; + quota_inode_ctx_t *ctx = NULL; + quota_dentry_t *dentry = NULL; + int64_t *size = 0; + uint64_t value = 0; + limits_t *limit_node = NULL; + quota_priv_t *priv = NULL; local = frame->local; + priv = this->private; + inode_ctx_get (inode, this, &value); ctx = (quota_inode_ctx_t *)(unsigned long)value; @@ -600,6 +604,18 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto unwind; } + LOCK (&priv->lock); + { + list_for_each_entry (limit_node, &priv->limit_head, + limit_list) { + if (strcmp (local->loc.path, limit_node->path) == 0) { + uuid_copy (limit_node->gfid, buf->ia_gfid); + break; + } + } + } + UNLOCK (&priv->lock); + ret = quota_inode_ctx_get (local->loc.inode, local->limit, this, dict, buf, &ctx, 1); if ((ret == -1) || (ctx == NULL)) { @@ -3012,22 +3028,23 @@ quota_forget (xlator_t *this, inode_t *inode) int -quota_parse_limits (quota_priv_t *priv, xlator_t *this, dict_t *xl_options) +quota_parse_limits (quota_priv_t *priv, xlator_t *this, dict_t *xl_options, + struct list_head *old_list) { int32_t ret = -1; char *str = NULL; char *str_val = NULL; - char *path = NULL; + char *path = NULL, *saveptr = NULL; uint64_t value = 0; - limits_t *quota_lim = NULL; + limits_t *quota_lim = NULL, *old = NULL; ret = dict_get_str (xl_options, "limit-set", &str); if (str) { - path = strtok (str, ":"); + path = strtok_r (str, ":", &saveptr); while (path) { - str_val = strtok (NULL, ","); + str_val = strtok_r (NULL, ",", &saveptr); ret = gf_string2bytesize (str_val, &value); if (ret != 0) @@ -3042,20 +3059,40 @@ quota_parse_limits (quota_priv_t *priv, xlator_t *this, dict_t *xl_options) gf_log (this->name, GF_LOG_INFO, "%s:%"PRId64, quota_lim->path, quota_lim->value); - list_add_tail ("a_lim->limit_list, - &priv->limit_head); + if (old_list != NULL) { + list_for_each_entry (old, old_list, + limit_list) { + if (strcmp (old->path, quota_lim->path) + == 0) { + uuid_copy (quota_lim->gfid, + old->gfid); + break; + } + } + } + + LOCK (&priv->lock); + { + list_add_tail ("a_lim->limit_list, + &priv->limit_head); + } + UNLOCK (&priv->lock); - path = strtok (NULL, ":"); + path = strtok_r (NULL, ":", &saveptr); } } else { gf_log (this->name, GF_LOG_INFO, "no \"limit-set\" option provided"); } - list_for_each_entry (quota_lim, &priv->limit_head, limit_list) { - gf_log (this->name, GF_LOG_INFO, "%s:%"PRId64, quota_lim->path, - quota_lim->value); + LOCK (&priv->lock); + { + list_for_each_entry (quota_lim, &priv->limit_head, limit_list) { + gf_log (this->name, GF_LOG_INFO, "%s:%"PRId64, + quota_lim->path, quota_lim->value); + } } + UNLOCK (&priv->lock); ret = 0; err: @@ -3086,9 +3123,11 @@ init (xlator_t *this) INIT_LIST_HEAD (&priv->limit_head); + LOCK_INIT (&priv->lock); + this->private = priv; - ret = quota_parse_limits (priv, this, this->options); + ret = quota_parse_limits (priv, this, this->options, NULL); if (ret) { goto err; @@ -3110,23 +3149,81 @@ err: } +void +__quota_reconfigure_inode_ctx (xlator_t *this, inode_t *inode, limits_t *limit) +{ + int ret = -1; + quota_inode_ctx_t *ctx = NULL; + + GF_VALIDATE_OR_GOTO ("quota", this, out); + GF_VALIDATE_OR_GOTO (this->name, inode, out); + GF_VALIDATE_OR_GOTO (this->name, limit, out); + + ret = quota_inode_ctx_get (inode, limit->value, this, NULL, NULL, &ctx, + 1); + if ((ret == -1) || (ctx == NULL)) { + gf_log (this->name, GF_LOG_WARNING, "cannot create quota " + "context in inode(gfid:%s)", + uuid_utoa (inode->gfid)); + goto out; + } + + LOCK (&ctx->lock); + { + ctx->limit = limit->value; + } + UNLOCK (&ctx->lock); + +out: + return; +} + + +void +__quota_reconfigure (xlator_t *this, inode_table_t *itable, limits_t *limit) +{ + inode_t *inode = NULL; + + if ((this == NULL) || (itable == NULL) || (limit == NULL)) { + goto out; + } + + if (!uuid_is_null (limit->gfid)) { + inode = inode_find (itable, limit->gfid); + } else { + inode = inode_resolve (itable, limit->path); + } + + if (inode != NULL) { + __quota_reconfigure_inode_ctx (this, inode, limit); + } + +out: + return; +} + + int reconfigure (xlator_t *this, dict_t *options) { - int32_t ret = -1; - quota_priv_t *priv = NULL; - limits_t *limit = NULL; - limits_t *next = NULL; + int32_t ret = -1; + quota_priv_t *priv = NULL; + limits_t *limit = NULL, *next = NULL, *new = NULL; + struct list_head head = {0, }; + xlator_t *top = NULL; + char found = 0; priv = this->private; - list_for_each_entry_safe (limit, next, &priv->limit_head, limit_list) { - list_del (&limit->limit_list); + INIT_LIST_HEAD (&head); - GF_FREE (limit); + LOCK (&priv->lock); + { + list_splice_init (&priv->limit_head, &head); } + UNLOCK (&priv->lock); - ret = quota_parse_limits (priv, this, options); + ret = quota_parse_limits (priv, this, options, &head); if (ret == -1) { gf_log ("quota", GF_LOG_WARNING, "quota reconfigure failed, " @@ -3134,6 +3231,35 @@ reconfigure (xlator_t *this, dict_t *options) goto out; } + LOCK (&priv->lock); + { + list_for_each_entry (limit, &priv->limit_head, limit_list) { + top = ((glusterfs_ctx_t *)this->ctx)->active->top; + + __quota_reconfigure (this, top->itable, limit); + } + + list_for_each_entry_safe (limit, next, &head, limit_list) { + found = 0; + list_for_each_entry (new, &priv->limit_head, + limit_list) { + if (strcmp (new->path, limit->path) == 0) { + found = 1; + break; + } + } + + if (!found) { + limit->value = -1; + __quota_reconfigure (this, top->itable, limit); + } + + list_del_init (&limit->limit_list); + GF_FREE (limit); + } + } + UNLOCK (&priv->lock); + GF_OPTION_RECONF ("timeout", priv->timeout, options, int64, out); ret = 0; diff --git a/xlators/features/quota/src/quota.h b/xlators/features/quota/src/quota.h index 79b4d07e351..cf9c4f9b769 100644 --- a/xlators/features/quota/src/quota.h +++ b/xlators/features/quota/src/quota.h @@ -154,16 +154,18 @@ struct quota_local { typedef struct quota_local quota_local_t; struct quota_priv { - int64_t timeout; - struct list_head limit_head; + int64_t timeout; + struct list_head limit_head; + gf_lock_t lock; }; typedef struct quota_priv quota_priv_t; struct limits { struct list_head limit_list; char *path; - int64_t value; + int64_t value; + uuid_t gfid; }; -typedef struct limits limits_t; +typedef struct limits limits_t; uint64_t cn = 1; |