summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/features/quota/src/quota.c180
-rw-r--r--xlators/features/quota/src/quota.h10
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 (&quota_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 (&quota_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;