diff options
| -rw-r--r-- | xlators/features/quota/src/quota.c | 1488 | ||||
| -rw-r--r-- | xlators/features/quota/src/quota.h | 44 |
2 files changed, 822 insertions, 710 deletions
diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c index 744748fd..4ea54cca 100644 --- a/xlators/features/quota/src/quota.c +++ b/xlators/features/quota/src/quota.c @@ -18,54 +18,6 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, char *name, uuid_t par); struct volume_options options[]; - -static int32_t -__quota_init_inode_ctx (inode_t *inode, int64_t hard_lim, int64_t soft_lim, - xlator_t *this, dict_t *dict, struct iatt *buf, - quota_inode_ctx_t **context) -{ - int32_t ret = -1; - int64_t *size = 0; - quota_inode_ctx_t *ctx = NULL; - - if (inode == NULL) { - goto out; - } - - QUOTA_ALLOC_OR_GOTO (ctx, quota_inode_ctx_t, out); - - ctx->hard_lim = hard_lim; - ctx->soft_lim = soft_lim; - - if (buf) - ctx->buf = *buf; - - LOCK_INIT(&ctx->lock); - - if (context != NULL) { - *context = ctx; - } - - INIT_LIST_HEAD (&ctx->parents); - - if (dict != NULL) { - ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); - if (ret == 0) { - ctx->size = ntoh64 (*size); - gettimeofday (&ctx->tv, NULL); - } - } - - ret = __inode_ctx_put (inode, this, (uint64_t )(long)ctx); - if (ret == -1) { - gf_log (this->name, GF_LOG_WARNING, - "cannot set quota context in inode (gfid:%s)", - uuid_utoa (inode->gfid)); - } -out: - return ret; -} - int quota_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) { @@ -230,16 +182,128 @@ out: return; } + +int32_t +quota_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + quota_local_t *local = NULL; + uint32_t validate_count = 0, link_count = 0; + int32_t ret = 0; + quota_inode_ctx_t *ctx = NULL; + int64_t *size = 0; + uint64_t value = 0; + call_stub_t *stub = NULL; + + local = frame->local; + + if (op_ret < 0) { + goto unwind; + } + + GF_ASSERT (local); + GF_ASSERT (frame); + GF_VALIDATE_OR_GOTO_WITH_ERROR ("quota", this, unwind, op_errno, + EINVAL); + GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, dict, unwind, op_errno, + EINVAL); + + ret = inode_ctx_get (local->validate_loc.inode, this, &value); + + ctx = (quota_inode_ctx_t *)(unsigned long)value; + if ((ret == -1) || (ctx == NULL)) { + gf_log (this->name, GF_LOG_WARNING, + "quota context is not present in inode (gfid:%s)", + uuid_utoa (local->validate_loc.inode->gfid)); + op_errno = EINVAL; + goto unwind; + } + + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "size key not present in dict"); + op_errno = EINVAL; + goto unwind; + } + + local->just_validated = 1; /* so that we don't go into infinite + * loop of validation and checking + * limit when timeout is zero. + */ + LOCK (&ctx->lock); + { + ctx->size = ntoh64 (*size); + gettimeofday (&ctx->tv, NULL); + } + UNLOCK (&ctx->lock); + + quota_check_limit (frame, local->validate_loc.inode, this, NULL, NULL); + return 0; + +unwind: + LOCK (&local->lock); + { + local->op_ret = -1; + local->op_errno = op_errno; + + validate_count = --local->validate_count; + link_count = local->link_count; + + if ((validate_count == 0) && (link_count == 0)) { + stub = local->stub; + local->stub = NULL; + } + } + UNLOCK (&local->lock); + + if (stub != NULL) { + call_resume (stub); + } + + return 0; +} + + +static inline uint64_t +quota_time_elapsed (struct timeval *now, struct timeval *then) +{ + return (now->tv_sec - then->tv_sec); +} + + +int32_t +quota_timeout (struct timeval *tv, int32_t timeout) +{ + struct timeval now = {0,}; + int32_t timed_out = 0; + + gettimeofday (&now, NULL); + + if (quota_time_elapsed (&now, tv) >= timeout) { + timed_out = 1; + } + + return timed_out; +} + + int32_t quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, char *name, uuid_t par) { + int32_t ret = -1; inode_t *_inode = NULL, *parent = NULL; quota_inode_ctx_t *ctx = NULL; + quota_priv_t *priv = NULL; quota_local_t *local = NULL; - char need_unwind = 0; + char need_validate = 0, need_unwind = 0; int64_t delta = 0; + call_stub_t *stub = NULL; + int32_t validate_count = 0, link_count = 0; uint64_t value = 0; + char just_validated = 0; uuid_t trav_uuid = {0,}; GF_VALIDATE_OR_GOTO ("quota", this, out); @@ -251,11 +315,25 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, delta = local->delta; + GF_VALIDATE_OR_GOTO (this->name, local->stub, out); + + priv = this->private; + inode_ctx_get (inode, this, &value); ctx = (quota_inode_ctx_t *)(unsigned long)value; _inode = inode_ref (inode); + LOCK (&local->lock); + { + just_validated = local->just_validated; + local->just_validated = 0; + + if (just_validated) { + local->validate_count--; + } + } + UNLOCK (&local->lock); if ( par != NULL ) { uuid_copy (trav_uuid, par); @@ -265,9 +343,13 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, if (ctx != NULL) { LOCK (&ctx->lock); { - if (ctx->hard_lim >= 0) { - if ((ctx->size + delta) - >= ctx->hard_lim) { + if (ctx->limit >= 0) { + if (!just_validated + && quota_timeout (&ctx->tv, + priv->timeout)) { + need_validate = 1; + } else if ((ctx->size + delta) + >= ctx->limit) { local->op_ret = -1; local->op_errno = EDQUOT; need_unwind = 1; @@ -276,6 +358,10 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, } UNLOCK (&ctx->lock); + if (need_validate) { + goto validate; + } + if (need_unwind) { break; } @@ -301,6 +387,7 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, inode_unref (_inode); _inode = parent; + just_validated = 0; if (_inode == NULL) { break; @@ -311,10 +398,62 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, ctx = (quota_inode_ctx_t *)(unsigned long)value; } while (1); - inode_unref (_inode); + ret = 0; + + if (_inode != NULL) { + inode_unref (_inode); + } + + LOCK (&local->lock); + { + validate_count = local->validate_count; + link_count = local->link_count; + if ((validate_count == 0) && (link_count == 0)) { + stub = local->stub; + local->stub = NULL; + } + } + UNLOCK (&local->lock); + + if (stub != NULL) { + call_resume (stub); + } out: - return local->op_ret; + return ret; + +validate: + LOCK (&local->lock); + { + loc_wipe (&local->validate_loc); + + if (just_validated) { + local->validate_count--; + } + + local->validate_count++; + ret = quota_inode_loc_fill (_inode, &local->validate_loc); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "cannot fill loc for inode (gfid:%s), hence " + "aborting quota-checks and continuing with fop", + uuid_utoa (_inode->gfid)); + local->validate_count--; + } + } + UNLOCK (&local->lock); + + if (ret < 0) { + goto loc_fill_failed; + } + + STACK_WIND (frame, quota_validate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, &local->validate_loc, + QUOTA_SIZE_KEY, NULL); + +loc_fill_failed: + inode_unref (_inode); + return 0; } @@ -343,7 +482,7 @@ quota_get_limit_value (inode_t *inode, xlator_t *this, int64_t *n) list_for_each_entry (limit_node, &priv->limit_head, limit_list) { if (strcmp (limit_node->path, path) == 0) { - *n = limit_node->hard_lim; + *n = limit_node->value; break; } } @@ -356,9 +495,55 @@ out: static int32_t -quota_inode_ctx_get (inode_t *inode, int64_t hard_lim, int64_t soft_lim, - xlator_t *this, dict_t *dict, struct iatt *buf, - quota_inode_ctx_t **ctx, char create_if_absent) +__quota_init_inode_ctx (inode_t *inode, int64_t limit, xlator_t *this, + dict_t *dict, struct iatt *buf, + quota_inode_ctx_t **context) +{ + int32_t ret = -1; + int64_t *size = 0; + quota_inode_ctx_t *ctx = NULL; + + if (inode == NULL) { + goto out; + } + + QUOTA_ALLOC_OR_GOTO (ctx, quota_inode_ctx_t, out); + + ctx->limit = limit; + if (buf) + ctx->buf = *buf; + + LOCK_INIT(&ctx->lock); + + if (context != NULL) { + *context = ctx; + } + + INIT_LIST_HEAD (&ctx->parents); + + if (dict != NULL) { + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); + if (ret == 0) { + ctx->size = ntoh64 (*size); + gettimeofday (&ctx->tv, NULL); + } + } + + ret = __inode_ctx_put (inode, this, (uint64_t )(long)ctx); + if (ret == -1) { + gf_log (this->name, GF_LOG_WARNING, + "cannot set quota context in inode (gfid:%s)", + uuid_utoa (inode->gfid)); + } +out: + return ret; +} + + +static int32_t +quota_inode_ctx_get (inode_t *inode, int64_t limit, xlator_t *this, + dict_t *dict, struct iatt *buf, quota_inode_ctx_t **ctx, + char create_if_absent) { int32_t ret = 0; uint64_t ctx_int; @@ -370,8 +555,8 @@ quota_inode_ctx_get (inode_t *inode, int64_t hard_lim, int64_t soft_lim, if ((ret == 0) && (ctx != NULL)) { *ctx = (quota_inode_ctx_t *) (unsigned long)ctx_int; } else if (create_if_absent) { - ret = __quota_init_inode_ctx (inode, hard_lim, soft_lim, - this, dict, buf, ctx); + ret = __quota_init_inode_ctx (inode, limit, this, dict, + buf, ctx); } } UNLOCK (&inode->lock); @@ -390,10 +575,10 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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; - int64_t *size = NULL; local = frame->local; @@ -403,8 +588,8 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ctx = (quota_inode_ctx_t *)(unsigned long)value; if ((op_ret < 0) || (local == NULL) - || (((ctx == NULL) || (ctx->hard_lim == local->hard_lim)) - && (local->hard_lim < 0) && !((IA_ISREG (buf->ia_type)) + || (((ctx == NULL) || (ctx->limit == local->limit)) + && (local->limit < 0) && !((IA_ISREG (buf->ia_type)) || (IA_ISLNK (buf->ia_type))))) { goto unwind; } @@ -421,8 +606,8 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } UNLOCK (&priv->lock); - ret = quota_inode_ctx_get (local->loc.inode, local->hard_lim, - local->soft_lim, this, dict, buf, &ctx, 1); + ret = quota_inode_ctx_get (local->loc.inode, local->limit, this, dict, + buf, &ctx, 1); if ((ret == -1) || (ctx == NULL)) { gf_log (this->name, GF_LOG_WARNING, "cannot create quota " "context in inode(gfid:%s)", @@ -434,17 +619,21 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, LOCK (&ctx->lock); { - ctx->hard_lim = local->hard_lim; - ctx->soft_lim = local->soft_lim; - ctx->buf = *buf; + if (dict != NULL) { + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, + (void **) &size); + if (ret == 0) { + ctx->size = ntoh64 (*size); + gettimeofday (&ctx->tv, NULL); + } + } - /* will be useful for quotad to determine whether quota xlator's - context is maintaining the correct size. - */ - size = GF_CALLOC (1, sizeof (*size), gf_quota_mt_int64_t); - *size = hton64 (ctx->size); - ret = dict_set_bin (dict, "trusted.limit.set", size, 8); + if (local->limit != ctx->limit) { + ctx->limit = local->limit; + } + + ctx->buf = *buf; if (!(IA_ISREG (buf->ia_type) || IA_ISLNK (buf->ia_type))) { goto unlock; @@ -494,23 +683,18 @@ int32_t quota_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) { - quota_priv_t *priv = NULL; int32_t ret = -1; + int64_t limit = -1; limits_t *limit_node = NULL; + gf_boolean_t dict_newed = _gf_false; + quota_priv_t *priv = NULL; quota_local_t *local = NULL; - int64_t hard_lim = -1; - int64_t soft_lim = -1; priv = this->private; - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - - list_for_each_entry (limit_node, &priv->limit_head, limit_list) { if (strcmp (limit_node->path, loc->path) == 0) { - hard_lim = limit_node->hard_lim; - soft_lim = limit_node->soft_lim; - break; + limit = limit_node->value; } } @@ -526,18 +710,25 @@ quota_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, frame->local = local; - local->hard_lim = hard_lim; - local->soft_lim = soft_lim; + local->limit = limit; - if (hard_lim < 0) { + if (limit < 0) { goto wind; } + if (xattr_req == NULL) { + xattr_req = dict_new (); + dict_newed = _gf_true; + } + + ret = dict_set_uint64 (xattr_req, QUOTA_SIZE_KEY, 0); + if (ret < 0) { + goto err; + } + wind: - STACK_WIND (frame, - priv->is_quota_on? quota_lookup_cbk: default_lookup_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, loc, - xattr_req); + STACK_WIND (frame, quota_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xattr_req); ret = 0; @@ -547,6 +738,10 @@ err: NULL, NULL, NULL, NULL); } + if (dict_newed == _gf_true) { + dict_unref (xattr_req); + } + return 0; } @@ -574,12 +769,10 @@ quota_update_size (xlator_t *this, inode_t *inode, char *name, uuid_t par, } do { - if ((ctx != NULL) && (ctx->hard_lim >= 0)) { + if ((ctx != NULL) && (ctx->limit >= 0)) { LOCK (&ctx->lock); { ctx->size += delta; - if (ctx->size < 0) - ctx->size = 0; } UNLOCK (&ctx->lock); } @@ -608,8 +801,6 @@ quota_update_size (xlator_t *this, inode_t *inode, char *name, uuid_t par, break; } - value = 0; - ctx = NULL; inode_ctx_get (_inode, this, &value); ctx = (quota_inode_ctx_t *)(unsigned long)value; } while (1); @@ -661,8 +852,8 @@ quota_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, list_for_each_entry (dentry, &ctx->parents, next) { delta = (postbuf->ia_blocks - prebuf->ia_blocks) * 512; - quota_update_size (this, local->loc.inode, dentry->name, - dentry->par, delta); + quota_update_size (this, local->loc.inode, + dentry->name, dentry->par, delta); } out: @@ -674,22 +865,49 @@ out: int32_t +quota_writev_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, + uint32_t flags, struct iobref *iobref, dict_t *xdata) +{ + quota_local_t *local = NULL; + int32_t op_errno = EINVAL; + + local = frame->local; + if (local == NULL) { + gf_log (this->name, GF_LOG_WARNING, "local is NULL"); + goto unwind; + } + + if (local->op_ret == -1) { + op_errno = local->op_errno; + goto unwind; + } + + STACK_WIND (frame, quota_writev_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, fd, vector, count, off, + flags, iobref, xdata); + return 0; + +unwind: + QUOTA_STACK_UNWIND (writev, frame, -1, op_errno, NULL, NULL, NULL); + return 0; +} + + +int32_t quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t off, uint32_t flags, struct iobref *iobref, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = -1, op_errno = EINVAL; int32_t parents = 0; uint64_t size = 0; quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; + quota_priv_t *priv = NULL; + call_stub_t *stub = NULL; quota_dentry_t *dentry = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - GF_ASSERT (frame); GF_VALIDATE_OR_GOTO ("quota", this, unwind); GF_VALIDATE_OR_GOTO (this->name, fd, unwind); @@ -702,8 +920,7 @@ quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, frame->local = local; local->loc.inode = inode_ref (fd->inode); - ret = quota_inode_ctx_get (fd->inode, -1, -1, this, NULL, NULL, &ctx, - 0); + ret = quota_inode_ctx_get (fd->inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, "quota context not set in inode (gfid:%s)", @@ -711,6 +928,13 @@ quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, goto unwind; } + stub = fop_writev_stub (frame, quota_writev_helper, fd, vector, count, + off, flags, iobref, xdata); + if (stub == NULL) { + op_errno = ENOMEM; + goto unwind; + } + priv = this->private; GF_VALIDATE_OR_GOTO (this->name, priv, unwind); @@ -724,22 +948,32 @@ quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, UNLOCK (&ctx->lock); local->delta = size; + local->stub = stub; local->link_count = parents; list_for_each_entry (dentry, &ctx->parents, next) { ret = quota_check_limit (frame, fd->inode, this, dentry->name, dentry->par); if (ret == -1) { - op_errno = EDQUOT; - goto unwind; + break; } } -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_writev_cbk: default_writev_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, - vector, count, off, flags, iobref, xdata); + stub = NULL; + + LOCK (&local->lock); + { + local->link_count = 0; + if (local->validate_count == 0) { + stub = local->stub; + local->stub = NULL; + } + } + UNLOCK (&local->lock); + + if (stub != NULL) { + call_resume (stub); + } return 0; @@ -762,16 +996,42 @@ quota_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t +quota_mkdir_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, mode_t umask, dict_t *xdata) +{ + quota_local_t *local = NULL; + int32_t op_errno = EINVAL; + + local = frame->local; + if (local == NULL) { + gf_log (this->name, GF_LOG_WARNING, "local is NULL"); + goto unwind; + } + + op_errno = local->op_errno; + + if (local->op_ret == -1) { + goto unwind; + } + + STACK_WIND (frame, quota_mkdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); + return 0; + +unwind: + QUOTA_STACK_UNWIND (mkdir, frame, -1, op_errno, NULL, NULL, + NULL, NULL, NULL); + return 0; +} + + +int32_t quota_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = 0, op_errno = 0; quota_local_t *local = NULL; - - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); + call_stub_t *stub = NULL; local = quota_local_new (); if (local == NULL) { @@ -790,19 +1050,34 @@ quota_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, goto err; } + stub = fop_mkdir_stub (frame, quota_mkdir_helper, loc, mode, umask, + xdata); + if (stub == NULL) { + op_errno = ENOMEM; + goto err; + } + + local->stub = stub; local->delta = 0; - ret = quota_check_limit (frame, loc->parent, this, NULL, NULL); - if (ret == -1) { - op_errno = EDQUOT; - goto err; + quota_check_limit (frame, loc->parent, this, NULL, NULL); + + stub = NULL; + + LOCK (&local->lock); + { + if (local->validate_count == 0) { + stub = local->stub; + local->stub = NULL; + } + + local->link_count = 0; } + UNLOCK (&local->lock); -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_mkdir_cbk: default_mkdir_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->mkdir, loc, - mode, umask, xdata); + if (stub != NULL) { + call_resume (stub); + } return 0; err: @@ -829,7 +1104,7 @@ quota_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto unwind; } - ret = quota_inode_ctx_get (inode, -1, -1, this, NULL, buf, &ctx, 1); + ret = quota_inode_ctx_get (inode, -1, this, NULL, buf, &ctx, 1); if ((ret == -1) || (ctx == NULL)) { gf_log (this->name, GF_LOG_WARNING, "cannot create quota " "context in inode(gfid:%s)", @@ -866,21 +1141,46 @@ unwind: int32_t +quota_create_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, mode_t mode, mode_t umask, fd_t *fd, + dict_t *xdata) +{ + quota_local_t *local = NULL; + int32_t op_errno = EINVAL; + + local = frame->local; + if (local == NULL) { + gf_log (this->name, GF_LOG_WARNING, "local is NULL"); + goto unwind; + } + + if (local->op_ret == -1) { + op_errno = local->op_errno; + goto unwind; + } + + STACK_WIND (frame, quota_create_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, + fd, xdata); + return 0; + +unwind: + QUOTA_STACK_UNWIND (create, frame, -1, op_errno, NULL, NULL, + NULL, NULL, NULL, NULL); + return 0; +} + + +int32_t quota_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = -1; quota_local_t *local = NULL; - int32_t op_errno = 0; - - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); + call_stub_t *stub = NULL; local = quota_local_new (); if (local == NULL) { - op_errno = ENOMEM; goto err; } @@ -889,28 +1189,41 @@ quota_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, ret = loc_copy (&local->loc, loc); if (ret) { gf_log (this->name, GF_LOG_WARNING, "loc_copy failed"); - op_errno = ENOMEM; goto err; } + stub = fop_create_stub (frame, quota_create_helper, loc, flags, mode, + umask, fd, xdata); + if (stub == NULL) { + goto err; + } + + local->link_count = 1; + local->stub = stub; local->delta = 0; - ret = quota_check_limit (frame, loc->parent, this, NULL, NULL); - if (ret == -1) { - op_errno = EDQUOT; - goto err; + quota_check_limit (frame, loc->parent, this, NULL, NULL); + + stub = NULL; + + LOCK (&local->lock); + { + local->link_count = 0; + if (local->validate_count == 0) { + stub = local->stub; + local->stub = NULL; + } } + UNLOCK (&local->lock); -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_create_cbk: default_create_cbk, - FIRST_CHILD (this), FIRST_CHILD (this)->fops->create, loc, - flags, mode, umask, fd, xdata); + if (stub != NULL) { + call_resume (stub); + } return 0; err: - QUOTA_STACK_UNWIND (create, frame, -1, op_errno, NULL, NULL, NULL, - NULL, NULL, NULL); + QUOTA_STACK_UNWIND (create, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, + NULL, NULL); return 0; } @@ -924,8 +1237,6 @@ quota_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; uint64_t value = 0; - quota_dentry_t *dentry = NULL; - quota_dentry_t *old_dentry = NULL; if (op_ret < 0) { goto out; @@ -947,21 +1258,6 @@ quota_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->loc.parent->gfid, (-(ctx->buf.ia_blocks * 512))); - LOCK (&ctx->lock); - { - list_for_each_entry (dentry, &ctx->parents, next) { - if ((strcmp (dentry->name, local->loc.name) == 0) && - (uuid_compare (local->loc.parent->gfid, - dentry->par) == 0)) { - old_dentry = dentry; - break; - } - } - if (old_dentry) - __quota_dentry_free (old_dentry); - } - UNLOCK (&ctx->lock); - out: QUOTA_STACK_UNWIND (unlink, frame, op_ret, op_errno, preparent, postparent, xdata); @@ -973,14 +1269,9 @@ int32_t quota_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = 0; quota_local_t *local = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) { goto err; @@ -994,11 +1285,8 @@ quota_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, goto err; } -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_unlink_cbk: default_unlink_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->unlink, loc, - xflag, xdata); + STACK_WIND (frame, quota_unlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); ret = 0; @@ -1032,7 +1320,7 @@ quota_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, quota_update_size (this, local->loc.parent, NULL, NULL, (buf->ia_blocks * 512)); - ret = quota_inode_ctx_get (inode, -1, -1, this, NULL, NULL, &ctx, 0); + ret = quota_inode_ctx_get (inode, -1, this, NULL, NULL, &ctx, 0); if ((ret == -1) || (ctx == NULL)) { gf_log (this->name, GF_LOG_WARNING, "cannot find quota " "context in %s (gfid:%s)", local->loc.path, @@ -1087,19 +1375,44 @@ out: int32_t +quota_link_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata) +{ + quota_local_t *local = NULL; + int32_t op_errno = EINVAL; + + local = frame->local; + if (local == NULL) { + gf_log (this->name, GF_LOG_WARNING, "local is NULL"); + goto unwind; + } + + op_errno = local->op_errno; + + if (local->op_ret == -1) { + goto unwind; + } + + STACK_WIND (frame, quota_link_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); + return 0; + +unwind: + QUOTA_STACK_UNWIND (link, frame, -1, op_errno, NULL, NULL, + NULL, NULL, NULL); + return 0; +} + + +int32_t quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = -1, op_errno = ENOMEM; quota_local_t *local = NULL; + call_stub_t *stub = NULL; quota_inode_ctx_t *ctx = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - - local = quota_local_new (); if (local == NULL) { goto err; @@ -1113,8 +1426,16 @@ quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, goto err; } - ret = quota_inode_ctx_get (oldloc->inode, -1, -1, this, NULL, NULL, - &ctx, 0); + stub = fop_link_stub (frame, quota_link_helper, oldloc, newloc, xdata); + if (stub == NULL) { + goto err; + } + + local->link_count = 1; + local->stub = stub; + + ret = quota_inode_ctx_get (oldloc->inode, -1, this, NULL, NULL, &ctx, + 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, "quota context not set in inode (gfid:%s)", @@ -1125,17 +1446,24 @@ quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, local->delta = ctx->buf.ia_blocks * 512; - ret = quota_check_limit (frame, newloc->parent, this, NULL, NULL); - if (ret == -1) { - op_errno = EDQUOT; - goto err; + quota_check_limit (frame, newloc->parent, this, NULL, NULL); + + stub = NULL; + + LOCK (&local->lock); + { + if (local->validate_count == 0) { + stub = local->stub; + local->stub = NULL; + } + + local->link_count = 0; } + UNLOCK (&local->lock); -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_link_cbk: default_link_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->link, oldloc, - newloc, xdata); + if (stub != NULL) { + call_resume (stub); + } ret = 0; err: @@ -1156,11 +1484,11 @@ quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, dict_t *xdata) { int32_t ret = -1; - int64_t size = 0; quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; quota_dentry_t *old_dentry = NULL, *dentry = NULL; char new_dentry_found = 0; + int64_t size = 0; if (op_ret < 0) { goto out; @@ -1180,10 +1508,8 @@ quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } if (local->oldloc.parent != local->newloc.parent) { - quota_update_size (this, local->oldloc.parent, NULL, NULL, - (-size)); - quota_update_size (this, local->newloc.parent, NULL, NULL, - size); + quota_update_size (this, local->oldloc.parent, NULL, NULL, (-size)); + quota_update_size (this, local->newloc.parent, NULL, NULL, size); } if (!(IA_ISREG (local->oldloc.inode->ia_type) @@ -1191,8 +1517,8 @@ quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - ret = quota_inode_ctx_get (local->oldloc.inode, -1, -1, this, NULL, - NULL, &ctx, 0); + ret = quota_inode_ctx_get (local->oldloc.inode, -1, this, NULL, NULL, + &ctx, 0); if ((ret == -1) || (ctx == NULL)) { gf_log (this->name, GF_LOG_WARNING, "quota context not" "set in inode(gfid:%s)", @@ -1244,8 +1570,7 @@ quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (dentry == NULL) { gf_log (this->name, GF_LOG_WARNING, "cannot create a new dentry (name:%s) " - "for inode(gfid:%s)", - local->newloc.name, + "for inode(gfid:%s)", local->newloc.name, uuid_utoa (local->newloc.inode->gfid)); op_ret = -1; op_errno = ENOMEM; @@ -1267,18 +1592,44 @@ out: int32_t +quota_rename_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata) +{ + quota_local_t *local = NULL; + int32_t op_errno = EINVAL; + + local = frame->local; + if (local == NULL) { + gf_log (this->name, GF_LOG_WARNING, "local is NULL"); + goto unwind; + } + + op_errno = local->op_errno; + + if (local->op_ret == -1) { + goto unwind; + } + + STACK_WIND (frame, quota_rename_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); + return 0; + +unwind: + QUOTA_STACK_UNWIND (rename, frame, -1, op_errno, NULL, NULL, + NULL, NULL, NULL, NULL); + return 0; +} + + +int32_t quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = -1, op_errno = ENOMEM; quota_local_t *local = NULL; + call_stub_t *stub = NULL; quota_inode_ctx_t *ctx = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) { goto err; @@ -1298,10 +1649,19 @@ quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, goto err; } + stub = fop_rename_stub (frame, quota_rename_helper, oldloc, newloc, + xdata); + if (stub == NULL) { + goto err; + } + + local->link_count = 1; + local->stub = stub; + if (IA_ISREG (oldloc->inode->ia_type) || IA_ISLNK (oldloc->inode->ia_type)) { - ret = quota_inode_ctx_get (oldloc->inode, -1, -1, this, NULL, - NULL, &ctx, 0); + ret = quota_inode_ctx_get (oldloc->inode, -1, this, NULL, NULL, + &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, "quota context not set in inode (gfid:%s)", @@ -1315,17 +1675,24 @@ quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, local->delta = 0; } - ret = quota_check_limit (frame, newloc->parent, this, NULL, NULL); - if (ret == -1) { - op_errno = EDQUOT; - goto err; + quota_check_limit (frame, newloc->parent, this, NULL, NULL); + + stub = NULL; + + LOCK (&local->lock); + { + if (local->validate_count == 0) { + stub = local->stub; + local->stub = NULL; + } + + local->link_count = 0; } + UNLOCK (&local->lock); -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_rename_cbk: default_rename_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->rename, oldloc, - newloc, xdata); + if (stub != NULL) { + call_resume (stub); + } ret = 0; err: @@ -1358,7 +1725,7 @@ quota_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, quota_update_size (this, local->loc.parent, NULL, NULL, size); - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 1); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -1393,18 +1760,43 @@ out: int +quota_symlink_helper (call_frame_t *frame, xlator_t *this, const char *linkpath, + loc_t *loc, mode_t umask, dict_t *xdata) +{ + quota_local_t *local = NULL; + int32_t op_errno = EINVAL; + + local = frame->local; + if (local == NULL) { + gf_log (this->name, GF_LOG_WARNING, "local is NULL"); + goto unwind; + } + + if (local->op_ret == -1) { + op_errno = local->op_errno; + goto unwind; + } + + STACK_WIND (frame, quota_symlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->symlink, linkpath, loc, umask, + xdata); + return 0; + +unwind: + QUOTA_STACK_UNWIND (symlink, frame, -1, op_errno, NULL, NULL, + NULL, NULL, NULL); + return 0; +} + + +int quota_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, loc_t *loc, mode_t umask, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = -1; int32_t op_errno = ENOMEM; quota_local_t *local = NULL; - - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - + call_stub_t *stub = NULL; local = quota_local_new (); if (local == NULL) { @@ -1419,19 +1811,36 @@ quota_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, goto err; } - local->delta = strlen (linkpath); + local->link_count = 1; - ret = quota_check_limit (frame, loc->parent, this, NULL, NULL); - if (ret == -1) { - op_errno = EDQUOT; + stub = fop_symlink_stub (frame, quota_symlink_helper, linkpath, loc, + umask, xdata); + if (stub == NULL) { goto err; } -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_symlink_cbk: default_symlink_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->symlink, - linkpath, loc, umask, xdata); + local->stub = stub; + local->delta = strlen (linkpath); + + quota_check_limit (frame, loc->parent, this, NULL, NULL); + + stub = NULL; + + LOCK (&local->lock); + { + if (local->validate_count == 0) { + stub = local->stub; + local->stub = NULL; + } + + local->link_count = 0; + } + UNLOCK (&local->lock); + + if (stub != NULL) { + call_resume (stub); + } + return 0; err: @@ -1448,8 +1857,8 @@ quota_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, struct iatt *postbuf, dict_t *xdata) { quota_local_t *local = NULL; - quota_inode_ctx_t *ctx = NULL; int64_t delta = 0; + quota_inode_ctx_t *ctx = NULL; if (op_ret < 0) { goto out; @@ -1465,7 +1874,7 @@ quota_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, quota_update_size (this, local->loc.inode, NULL, NULL, delta); - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -1491,15 +1900,9 @@ int32_t quota_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = -1; quota_local_t *local = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - - local = quota_local_new (); if (local == NULL) { goto err; @@ -1513,11 +1916,8 @@ quota_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, goto err; } -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_truncate_cbk: default_truncate_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->truncate, loc, - offset, xdata); + STACK_WIND (frame, quota_truncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); return 0; err: @@ -1533,8 +1933,8 @@ quota_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, struct iatt *postbuf, dict_t *xdata) { quota_local_t *local = NULL; - quota_inode_ctx_t *ctx = NULL; int64_t delta = 0; + quota_inode_ctx_t *ctx = NULL; if (op_ret < 0) { goto out; @@ -1550,7 +1950,7 @@ quota_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, quota_update_size (this, local->loc.inode, NULL, NULL, delta); - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -1576,13 +1976,8 @@ int32_t quota_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) goto err; @@ -1591,11 +1986,8 @@ quota_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, local->loc.inode = inode_ref (fd->inode); -wind: - STACK_WIND (frame, priv->is_quota_on? - quota_ftruncate_cbk: default_ftruncate_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->ftruncate, fd, - offset, xdata); + STACK_WIND (frame, quota_ftruncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); return 0; err: @@ -1614,23 +2006,14 @@ quota_send_dir_limit_to_cli (call_frame_t *frame, xlator_t *this, dict_t *dict = NULL; quota_inode_ctx_t *ctx = NULL; uint64_t value = 0; - quota_priv_t *priv = NULL; - - priv = this->private; - if (!priv->is_quota_on) { - snprintf (dir_limit, 1024, "Quota is disabled please turn on"); - goto dict_set; - } ret = inode_ctx_get (inode, this, &value); if (ret < 0) goto out; ctx = (quota_inode_ctx_t *)(unsigned long)value; - snprintf (dir_limit, 1024, "%"PRId64",%"PRId64, ctx->size, - ctx->hard_lim); + snprintf (dir_limit, 1024, "%"PRId64",%"PRId64, ctx->size, ctx->limit); -dict_set: dict = dict_new (); if (dict == NULL) { ret = -1; @@ -1641,7 +2024,7 @@ dict_set: if (ret < 0) goto out; - gf_log (this->name, GF_LOG_DEBUG, "str = %s", dir_limit); + gf_log (this->name, GF_LOG_INFO, "str = %s", dir_limit); QUOTA_STACK_UNWIND (getxattr, frame, 0, 0, dict, NULL); @@ -1693,8 +2076,7 @@ quota_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t quota_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *buf, - dict_t *xdata) + int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata) { quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -1709,7 +2091,7 @@ quota_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_DEBUG, @@ -1734,15 +2116,9 @@ out: int32_t quota_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; int32_t ret = -1; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - - local = quota_local_new (); if (local == NULL) { goto unwind; @@ -1755,10 +2131,8 @@ quota_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) goto unwind; } -wind: - STACK_WIND (frame, priv->is_quota_on? quota_stat_cbk: default_stat_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->stat, loc, - xdata); + STACK_WIND (frame, quota_stat_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->stat, loc, xdata); return 0; unwind: @@ -1785,7 +2159,7 @@ quota_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -1810,13 +2184,8 @@ out: int32_t quota_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) { goto unwind; @@ -1826,11 +2195,8 @@ quota_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) local->loc.inode = inode_ref (fd->inode); -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_fstat_cbk: default_fstat_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fstat, fd, - xdata); + STACK_WIND (frame, quota_fstat_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, xdata); return 0; unwind: @@ -1857,7 +2223,7 @@ quota_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -1873,8 +2239,7 @@ quota_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, UNLOCK (&ctx->lock); out: - QUOTA_STACK_UNWIND (readlink, frame, op_ret, op_errno, path, buf, - xdata); + QUOTA_STACK_UNWIND (readlink, frame, op_ret, op_errno, path, buf, xdata); return 0; } @@ -1883,14 +2248,9 @@ int32_t quota_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; int32_t ret = -1; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) { goto unwind; @@ -1904,11 +2264,8 @@ quota_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, goto unwind; } -wind: - STACK_WIND (frame, priv->is_quota_on? - quota_readlink_cbk: default_readlink_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->readlink, loc, - size, xdata); + STACK_WIND (frame, quota_readlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readlink, loc, size, xdata); return 0; unwind: @@ -1936,7 +2293,7 @@ quota_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -1962,13 +2319,8 @@ int32_t quota_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) { goto unwind; @@ -1978,16 +2330,13 @@ quota_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, local->loc.inode = inode_ref (fd->inode); -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_readv_cbk: default_readv_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->readv, fd, - size, offset, flags, xdata); + STACK_WIND (frame, quota_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, + xdata); return 0; unwind: - QUOTA_STACK_UNWIND (readv, frame, -1, ENOMEM, NULL, -1, NULL, NULL, - NULL); + QUOTA_STACK_UNWIND (readv, frame, -1, ENOMEM, NULL, -1, NULL, NULL, NULL); return 0; } @@ -2010,7 +2359,7 @@ quota_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -2036,13 +2385,8 @@ int32_t quota_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) { goto unwind; @@ -2052,11 +2396,8 @@ quota_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, frame->local = local; -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_fsync_cbk: default_fsync_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsync, fd, - flags, xdata); + STACK_WIND (frame, quota_fsync_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsync, fd, flags, xdata); return 0; unwind: @@ -2084,7 +2425,7 @@ quota_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_DEBUG, @@ -2111,14 +2452,9 @@ int32_t quota_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; int32_t ret = -1; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - local = quota_local_new (); if (local == NULL) { goto unwind; @@ -2132,11 +2468,8 @@ quota_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, goto unwind; } -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_setattr_cbk: default_setattr_cbk, - FIRST_CHILD (this), FIRST_CHILD (this)->fops->setattr, loc, - stbuf, valid, xdata); + STACK_WIND (frame, quota_setattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, xdata); return 0; unwind: @@ -2163,7 +2496,7 @@ quota_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - quota_inode_ctx_get (local->loc.inode, -1, -1, this, NULL, NULL, + quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, @@ -2189,14 +2522,8 @@ int32_t quota_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, int32_t valid, dict_t *xdata) { - quota_priv_t *priv = NULL; quota_local_t *local = NULL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - - local = quota_local_new (); if (local == NULL) { goto unwind; @@ -2206,11 +2533,8 @@ quota_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, local->loc.inode = inode_ref (fd->inode); -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_fsetattr_cbk: default_fsetattr_cbk, - FIRST_CHILD (this), FIRST_CHILD (this)->fops->fsetattr, fd, - stbuf, valid, xdata); + STACK_WIND (frame, quota_fsetattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid, xdata); return 0; unwind: @@ -2235,7 +2559,7 @@ quota_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto unwind; } - ret = quota_inode_ctx_get (inode, -1, -1, this, NULL, buf, &ctx, 1); + ret = quota_inode_ctx_get (inode, -1, this, NULL, buf, &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)); @@ -2271,17 +2595,43 @@ unwind: int +quota_mknod_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) +{ + quota_local_t *local = NULL; + int32_t op_errno = EINVAL; + + local = frame->local; + if (local == NULL) { + gf_log (this->name, GF_LOG_WARNING, "local is NULL"); + goto unwind; + } + + if (local->op_ret == -1) { + op_errno = local->op_errno; + goto unwind; + } + + STACK_WIND (frame, quota_mknod_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, + xdata); + + return 0; + +unwind: + QUOTA_STACK_UNWIND (mknod, frame, -1, op_errno, NULL, NULL, + NULL, NULL, NULL); + return 0; +} + + +int quota_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t ret = -1; quota_local_t *local = NULL; - int32_t op_errno = 0; - - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); + call_stub_t *stub = NULL; local = quota_local_new (); if (local == NULL) { @@ -2296,24 +2646,37 @@ quota_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, goto err; } - local->delta = 0; - - ret = quota_check_limit (frame, loc->parent, this, NULL, NULL); - if (ret == -1) { - op_errno = EDQUOT; + stub = fop_mknod_stub (frame, quota_mknod_helper, loc, mode, rdev, + umask, xdata); + if (stub == NULL) { goto err; } -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_mknod_cbk: default_mknod_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->mknod, loc, - mode, rdev, umask, xdata); + local->link_count = 1; + local->stub = stub; + local->delta = 0; + + quota_check_limit (frame, loc->parent, this, NULL, NULL); + + stub = NULL; + + LOCK (&local->lock); + { + local->link_count = 0; + if (local->validate_count == 0) { + stub = local->stub; + local->stub = NULL; + } + } + UNLOCK (&local->lock); + if (stub != NULL) { + call_resume (stub); + } return 0; err: - QUOTA_STACK_UNWIND (mknod, frame, -1, op_errno, NULL, NULL, NULL, NULL, + QUOTA_STACK_UNWIND (mknod, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL); return 0; @@ -2331,17 +2694,8 @@ int quota_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, int flags, dict_t *xdata) { - quota_priv_t *priv = NULL; - int op_errno = EINVAL; - int op_ret = -1; - int64_t *size = 0; - uint64_t value = 0; - quota_inode_ctx_t *ctx = NULL; - int ret = -1; - - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); + int op_errno = EINVAL; + int op_ret = -1; VALIDATE_OR_GOTO (frame, err); VALIDATE_OR_GOTO (this, err); @@ -2350,36 +2704,10 @@ quota_setxattr (call_frame_t *frame, xlator_t *this, GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.quota*", dict, op_errno, err); - ret = dict_get_bin (dict, QUOTA_UPDATE_USAGE_KEY, (void **) &size); - if (0 == ret) { - - inode_ctx_get (loc->inode, this, &value); - ctx = (quota_inode_ctx_t *)(unsigned long) value; - if (NULL == ctx) { - gf_log (this->name, GF_LOG_ERROR, "Couldn't get the " - "context for %s. Usage may cross the limit.", - loc->path); - op_ret = -1; - goto err; - } - - LOCK (&ctx->lock); - { - ctx->size = ntoh64 (*size); - if (ctx->size < 0) - ctx->size = 0; - } - UNLOCK (&ctx->lock); - - QUOTA_STACK_UNWIND (setxattr, frame, ret, 0, xdata); - return 0; - } - -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_setxattr_cbk: default_setxattr_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, loc, - dict, flags, xdata); + STACK_WIND (frame, quota_setxattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, + loc, dict, flags, xdata); return 0; err: QUOTA_STACK_UNWIND (setxattr, frame, op_ret, op_errno, NULL); @@ -2398,14 +2726,9 @@ int quota_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, int flags, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t op_ret = -1; int32_t op_errno = EINVAL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - VALIDATE_OR_GOTO (frame, err); VALIDATE_OR_GOTO (this, err); VALIDATE_OR_GOTO (fd, err); @@ -2413,11 +2736,10 @@ quota_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.quota*", dict, op_errno, err); -wind: - STACK_WIND (frame, priv->is_quota_on? - quota_fsetxattr_cbk: default_fsetxattr_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetxattr, fd, - dict, flags, xdata); + STACK_WIND (frame, quota_fsetxattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, + fd, dict, flags, xdata); return 0; err: QUOTA_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, NULL); @@ -2437,13 +2759,8 @@ int quota_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t op_errno = EINVAL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - VALIDATE_OR_GOTO (this, err); GF_IF_NATIVE_XATTR_GOTO ("trusted.quota*", @@ -2452,10 +2769,9 @@ quota_removexattr (call_frame_t *frame, xlator_t *this, VALIDATE_OR_GOTO (frame, err); VALIDATE_OR_GOTO (loc, err); -wind: - STACK_WIND (frame, priv->is_quota_on? - quota_removexattr_cbk: default_removexattr_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->removexattr, + STACK_WIND (frame, quota_removexattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); return 0; err: @@ -2476,14 +2792,9 @@ int quota_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata) { - quota_priv_t *priv = NULL; int32_t op_ret = -1; int32_t op_errno = EINVAL; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - VALIDATE_OR_GOTO (frame, err); VALIDATE_OR_GOTO (this, err); VALIDATE_OR_GOTO (fd, err); @@ -2491,10 +2802,9 @@ quota_fremovexattr (call_frame_t *frame, xlator_t *this, GF_IF_NATIVE_XATTR_GOTO ("trusted.quota*", name, op_errno, err); -wind: - STACK_WIND (frame, priv->is_quota_on? - quota_fremovexattr_cbk: default_fremovexattr_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fremovexattr, + STACK_WIND (frame, quota_fremovexattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); return 0; err: @@ -2550,7 +2860,7 @@ quota_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, list_for_each_entry (limit_node, &priv->limit_head, limit_list) { /* Notice that this only works for volume-level quota. */ if (strcmp (limit_node->path, "/") == 0) { - blocks = limit_node->hard_lim / buf->f_bsize; + blocks = limit_node->value / buf->f_bsize; if (usage > blocks) { break; } @@ -2585,13 +2895,11 @@ unwind: int32_t quota_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - quota_priv_t *priv = NULL; inode_t *root_inode = NULL; + quota_priv_t *priv = NULL; priv = this->private; - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - if (priv->consider_statfs && loc->inode) { root_inode = loc->inode->table->root; inode_ref(root_inode); @@ -2613,7 +2921,6 @@ quota_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) if (priv->consider_statfs) gf_log(this->name,GF_LOG_WARNING, "missing inode, cannot adjust for quota"); -wind: STACK_WIND (frame, default_statfs_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->statfs, loc, xdata); } @@ -2644,13 +2951,8 @@ int quota_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, dict_t *dict) { - quota_priv_t *priv = NULL; int ret = 0; - priv = this->private; - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - if (dict) { ret = dict_set_uint64 (dict, QUOTA_SIZE_KEY, 0); if (ret < 0) { @@ -2658,144 +2960,15 @@ quota_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, } } -wind: - STACK_WIND (frame, - priv->is_quota_on? quota_readdirp_cbk: default_readdirp_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, fd, - size, offset, dict); + STACK_WIND (frame, quota_readdirp_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, + fd, size, offset, dict); return 0; err: STACK_UNWIND_STRICT (readdirp, frame, -1, EINVAL, NULL, NULL); return 0; } -int32_t -quota_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf, dict_t *xdata) -{ - int32_t ret = 0; - uint64_t ctx_int = 0; - quota_inode_ctx_t *ctx = NULL; - quota_local_t *local = NULL; - quota_dentry_t *dentry = NULL; - int64_t delta = 0; - - local = frame->local; - - if ((op_ret < 0) || (local == NULL)) { - goto out; - } - - ret = inode_ctx_get (local->loc.inode, this, &ctx_int); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, - "%s: failed to get the context", local->loc.path); - goto out; - } - - ctx = (quota_inode_ctx_t *)(unsigned long) ctx_int; - - if (ctx == NULL) { - gf_log (this->name, GF_LOG_WARNING, - "quota context not set in %s (gfid:%s)", - local->loc.path, uuid_utoa (local->loc.inode->gfid)); - goto out; - } - - LOCK (&ctx->lock); - { - ctx->buf = *postbuf; - } - UNLOCK (&ctx->lock); - - list_for_each_entry (dentry, &ctx->parents, next) { - delta = (postbuf->ia_blocks - prebuf->ia_blocks) * 512; - quota_update_size (this, local->loc.inode, - dentry->name, dentry->par, delta); - } - -out: - QUOTA_STACK_UNWIND (fallocate, frame, op_ret, op_errno, prebuf, postbuf, - xdata); - - return 0; -} - -int32_t -quota_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, - off_t offset, size_t len, dict_t *xdata) -{ - int32_t ret = -1, op_errno = EINVAL; - int32_t parents = 0; - quota_local_t *local = NULL; - quota_inode_ctx_t *ctx = NULL; - quota_priv_t *priv = NULL; - quota_dentry_t *dentry = NULL; - - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, unwind); - - WIND_IF_QUOTAOFF (priv->is_quota_on, wind); - - GF_ASSERT (frame); - GF_VALIDATE_OR_GOTO ("quota", this, unwind); - GF_VALIDATE_OR_GOTO (this->name, fd, unwind); - - local = quota_local_new (); - if (local == NULL) { - goto unwind; - } - - frame->local = local; - local->loc.inode = inode_ref (fd->inode); - - ret = quota_inode_ctx_get (fd->inode, -1, -1, this, NULL, NULL, &ctx, 0); - if (ctx == NULL) { - gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (gfid:%s)", - uuid_utoa (fd->inode->gfid)); - goto unwind; - } - - - LOCK (&ctx->lock); - { - list_for_each_entry (dentry, &ctx->parents, next) { - parents++; - } - } - UNLOCK (&ctx->lock); - - /* - * Note that by using len as the delta we're assuming the range from - * offset to offset+len has not already been allocated. This can result - * in ENOSPC errors attempting to allocate an already allocated range. - */ - local->delta = len; - local->link_count = parents; - - list_for_each_entry (dentry, &ctx->parents, next) { - ret = quota_check_limit (frame, fd->inode, this, dentry->name, - dentry->par); - if (ret == -1) { - op_errno = EDQUOT; - goto unwind; - } - } - -wind: - STACK_WIND (frame, priv->is_quota_on? - quota_fallocate_cbk: default_fallocate_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fallocate, fd, - mode, offset, len, xdata); - return 0; - -unwind: - QUOTA_STACK_UNWIND (fallocate, frame, -1, op_errno, NULL, NULL, NULL); - return 0; -} - int32_t mem_acct_init (xlator_t *this) @@ -2820,16 +2993,11 @@ mem_acct_init (xlator_t *this) int32_t quota_forget (xlator_t *this, inode_t *inode) { - quota_priv_t *priv = NULL; int32_t ret = 0; uint64_t ctx_int = 0; quota_inode_ctx_t *ctx = NULL; quota_dentry_t *dentry = NULL, *tmp; - priv = this->private; - if (!priv->is_quota_on) - return 0; - ret = inode_ctx_del (inode, this, &ctx_int); if (ret < 0) { @@ -2864,93 +3032,68 @@ quota_parse_limits (quota_priv_t *priv, xlator_t *this, dict_t *xl_options, char *path = NULL, *saveptr = NULL; uint64_t value = 0; limits_t *quota_lim = NULL, *old = NULL; - double soft_l = 0; - char *limit_dir = NULL; - char *saveptr_dir = NULL; - char *path_str = NULL; + char *last_colon= NULL; ret = dict_get_str (xl_options, "limit-set", &str); - if (ret) { - gf_log (this->name, GF_LOG_INFO, "could not get the limits"); - /* limit may not be set at all on the volume yet */ - ret = 0; - goto err; - } - - path_str = gf_strdup (str); - if (!path_str) - goto err; - - - limit_dir = strtok_r (path_str, ",", &saveptr); - - while (limit_dir) { - QUOTA_ALLOC_OR_GOTO (quota_lim, limits_t, err); - saveptr_dir = NULL; - - path = strtok_r (limit_dir, ":", &saveptr_dir); + if (str) { + path = strtok_r (str, ",", &saveptr); - str_val = strtok_r (NULL, ":", &saveptr_dir); + while (path) { + last_colon = strrchr (path, ':'); + *last_colon = '\0'; + str_val = last_colon + 1; - ret = gf_string2bytesize (str_val, &value); - if (ret != 0) - goto err; - - quota_lim->hard_lim = value; - - str_val = strtok_r (NULL, ",", &saveptr_dir); - - soft_l = priv->default_soft_lim; - if (str_val) { - ret = gf_string2percent (str_val, &soft_l); - if (ret) - gf_log (this->name, GF_LOG_WARNING, - "Failed to convert str to " - "percent. Using default soft " - "limit"); - } + ret = gf_string2bytesize (str_val, &value); + if (ret != 0) + goto err; - quota_lim->soft_lim = soft_l; + QUOTA_ALLOC_OR_GOTO (quota_lim, limits_t, err); - quota_lim->path = gf_strdup (path); + quota_lim->path = path; - gf_log (this->name, GF_LOG_INFO, "%s:%"PRId64, - quota_lim->path, quota_lim->hard_lim); + quota_lim->value = value; - 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; + gf_log (this->name, GF_LOG_INFO, "%s:%"PRId64, + quota_lim->path, quota_lim->value); + + 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); + LOCK (&priv->lock); + { + list_add_tail ("a_lim->limit_list, + &priv->limit_head); + } + UNLOCK (&priv->lock); - limit_dir = strtok_r (NULL, ",", &saveptr); + path = strtok_r (NULL, ",", &saveptr); + } + } else { + gf_log (this->name, GF_LOG_INFO, + "no \"limit-set\" option provided"); } 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->hard_lim); + quota_lim->path, quota_lim->value); } } UNLOCK (&priv->lock); ret = 0; err: - GF_FREE (path_str); return ret; } @@ -2988,10 +3131,8 @@ init (xlator_t *this) goto err; } + GF_OPTION_INIT ("timeout", priv->timeout, int64, err); GF_OPTION_INIT ("deem-statfs", priv->consider_statfs, bool, err); - GF_OPTION_INIT ("server-quota", priv->is_quota_on, bool, err); - GF_OPTION_INIT ("default-soft-limit", priv->default_soft_lim, percent, - err); this->local_pool = mem_pool_new (quota_local_t, 64); if (!this->local_pool) { @@ -3017,8 +3158,8 @@ __quota_reconfigure_inode_ctx (xlator_t *this, inode_t *inode, limits_t *limit) GF_VALIDATE_OR_GOTO (this->name, inode, out); GF_VALIDATE_OR_GOTO (this->name, limit, out); - ret = quota_inode_ctx_get (inode, limit->hard_lim, limit->soft_lim, - this, NULL, NULL, &ctx, 1); + 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)", @@ -3028,8 +3169,7 @@ __quota_reconfigure_inode_ctx (xlator_t *this, inode_t *inode, limits_t *limit) LOCK (&ctx->lock); { - ctx->hard_lim = limit->hard_lim; - ctx->soft_lim = limit->soft_lim; + ctx->limit = limit->value; } UNLOCK (&ctx->lock); @@ -3074,13 +3214,6 @@ reconfigure (xlator_t *this, dict_t *options) priv = this->private; - GF_OPTION_RECONF ("deem-statfs", priv->consider_statfs, options, bool, - out); - GF_OPTION_RECONF ("server-quota", priv->is_quota_on, options, bool, - out); - GF_OPTION_RECONF ("default-soft-limit", priv->default_soft_lim, - options, percent, out); - INIT_LIST_HEAD (&head); LOCK (&priv->lock); @@ -3117,7 +3250,7 @@ reconfigure (xlator_t *this, dict_t *options) } if (!found) { - limit->hard_lim = -1; + limit->value = -1; __quota_reconfigure (this, top->itable, limit); } @@ -3127,7 +3260,9 @@ reconfigure (xlator_t *this, dict_t *options) } UNLOCK (&priv->lock); - + GF_OPTION_RECONF ("timeout", priv->timeout, options, int64, out); + GF_OPTION_RECONF ("deem-statfs", priv->consider_statfs, options, bool, + out); ret = 0; out: @@ -3169,7 +3304,6 @@ struct xlator_fops fops = { .removexattr = quota_removexattr, .fremovexattr = quota_fremovexattr, .readdirp = quota_readdirp, - .fallocate = quota_fallocate, }; struct xlator_cbks cbks = { @@ -3178,25 +3312,6 @@ struct xlator_cbks cbks = { struct volume_options options[] = { {.key = {"limit-set"}}, - {.key = {"deem-statfs"}, - .type = GF_OPTION_TYPE_BOOL, - .default_value = "off", - .description = "If set to on, it takes quota limits into" - "consideration while estimating fs size. (df command)" - " (Default is off)." - }, - {.key = {"server-quota"}, - .type = GF_OPTION_TYPE_BOOL, - .default_value = "off", - .description = "Skip the quota if xlator if the feature is not " - "turned on. This is not a user exposed option." - }, - {.key = {"default-soft-limit"}, - .type = GF_OPTION_TYPE_PERCENT, - .default_value = "90%", - .min = 0, - .max = LONG_MAX, - }, {.key = {"timeout"}, .type = GF_OPTION_TYPE_SIZET, .min = 0, @@ -3205,5 +3320,12 @@ struct volume_options options[] = { .description = "quota caches the directory sizes on client. Timeout " "indicates the timeout for the cache to be revalidated." }, + {.key = {"deem-statfs"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "If set to on, it takes quota limits into" + "consideration while estimating fs size. (df command)" + " (Default is off)." + }, {.key = {NULL}} }; diff --git a/xlators/features/quota/src/quota.h b/xlators/features/quota/src/quota.h index de9f6f16..67a195b2 100644 --- a/xlators/features/quota/src/quota.h +++ b/xlators/features/quota/src/quota.h @@ -27,11 +27,7 @@ #define READDIR_BUF 4096 #define QUOTA_UPDATE_USAGE_KEY "quota-update-usage" -#define WIND_IF_QUOTAOFF(is_quota_on, label) \ - if (!is_quota_on) \ - goto label; - -#define DID_REACH_LIMIT(lim, prev_size, cur_size) \ +#define DID_REACH_LIMIT(lim, prev_size, cur_size) \ ((cur_size) >= (lim) && (prev_size) < (lim)) #define QUOTA_SAFE_INCREMENT(lock, var) \ @@ -104,8 +100,6 @@ goto label; \ } while (0) - - struct quota_dentry { char *name; uuid_t par; @@ -115,8 +109,7 @@ typedef struct quota_dentry quota_dentry_t; struct quota_inode_ctx { int64_t size; - int64_t hard_lim; - int64_t soft_lim; + int64_t limit; struct iatt buf; struct list_head parents; struct timeval tv; @@ -136,15 +129,13 @@ struct quota_local { int32_t op_ret; int32_t op_errno; int64_t size; - int64_t hard_lim; - int64_t soft_lim; + int64_t limit; char just_validated; inode_t *inode; call_stub_t *stub; }; typedef struct quota_local quota_local_t; - struct qd_vols_conf { char *name; inode_table_t *itable; @@ -153,35 +144,34 @@ struct qd_vols_conf { double default_soft_lim; gf_lock_t lock; loc_t root_loc; - uint32_t soft_timeout; - uint32_t hard_timeout; - struct list_head limit_head; - call_frame_t *frame; + uint32_t soft_timeout; + uint32_t hard_timeout; + struct list_head limit_head; + call_frame_t *frame; }; typedef struct qd_vols_conf qd_vols_conf_t; - struct quota_priv { - int64_t timeout; - double default_soft_lim; - gf_boolean_t is_quota_on; - gf_boolean_t consider_statfs; - struct list_head limit_head; - qd_vols_conf_t **qd_vols_conf; - gf_lock_t lock; + int64_t timeout; + double default_soft_lim; + gf_boolean_t is_quota_on; + gf_boolean_t consider_statfs; + struct list_head limit_head; + qd_vols_conf_t **qd_vols_conf; + gf_lock_t lock; }; typedef struct quota_priv quota_priv_t; - struct limits { struct list_head limit_list; char *path; + int64_t value; uuid_t gfid; int64_t prev_size; struct timeval prev_log_tv; int64_t hard_lim; int64_t soft_lim; - struct timeval expire; - uint32_t timeout; + struct timeval expire; + uint32_t timeout; }; typedef struct limits limits_t; |
