diff options
Diffstat (limited to 'xlators/features/quota/src/quota.c')
| -rw-r--r-- | xlators/features/quota/src/quota.c | 1487 |
1 files changed, 1100 insertions, 387 deletions
diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c index 5d1f304f4..c527e7ca7 100644 --- a/xlators/features/quota/src/quota.c +++ b/xlators/features/quota/src/quota.c @@ -1,28 +1,22 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ +#include <fnmatch.h> #include "quota.h" #include "common-utils.h" +#include "defaults.h" int32_t quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, - char *name, ino_t par); + char *name, uuid_t par); +struct volume_options options[]; int quota_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) @@ -35,7 +29,6 @@ quota_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) if (inode) { loc->inode = inode_ref (inode); - loc->ino = inode->ino; } if (parent) { @@ -79,16 +72,15 @@ quota_inode_loc_fill (inode_t *inode, loc_t *loc) this = THIS; - if ((inode) && (inode->ino == 1)) { + if ((inode) && __is_root_gfid (inode->gfid)) { loc->parent = NULL; goto ignore_parent; } parent = inode_parent (inode, 0, NULL); if (!parent) { - gf_log (this->name, GF_LOG_WARNING, - "cannot find parent for inode (ino:%"PRId64", " - "gfid:%s)", inode->ino, + gf_log (this->name, GF_LOG_DEBUG, + "cannot find parent for inode (gfid:%s)", uuid_utoa (inode->gfid)); goto err; } @@ -96,9 +88,8 @@ quota_inode_loc_fill (inode_t *inode, loc_t *loc) ignore_parent: ret = inode_path (inode, NULL, &resolvedpath); if (ret < 0) { - gf_log (this->name, GF_LOG_WARNING, - "cannot construct path for inode (ino:%"PRId64", " - "gfid:%s)", inode->ino, + gf_log (this->name, GF_LOG_DEBUG, + "cannot construct path for inode (gfid:%s)", uuid_utoa (inode->gfid)); goto err; } @@ -135,28 +126,28 @@ quota_local_cleanup (xlator_t *this, quota_local_t *local) inode_unref (local->inode); LOCK_DESTROY (&local->lock); + mem_put (local); out: return 0; } -quota_local_t * +static inline quota_local_t * quota_local_new () { - quota_local_t *local = NULL; - int32_t ret = 0; - - QUOTA_LOCAL_ALLOC_OR_GOTO (local, quota_local_t, err); -err: + quota_local_t *local = NULL; + local = mem_get0 (THIS->local_pool); + if (local) + LOCK_INIT (&local->lock); return local; } quota_dentry_t * -__quota_dentry_new (quota_inode_ctx_t *ctx, char *name, ino_t par) +__quota_dentry_new (quota_inode_ctx_t *ctx, char *name, uuid_t par) { - quota_dentry_t *dentry = NULL; - int32_t ret = 0; + quota_dentry_t *dentry = NULL; + GF_UNUSED int32_t ret = 0; QUOTA_ALLOC_OR_GOTO (dentry, quota_dentry_t, err); @@ -168,7 +159,7 @@ __quota_dentry_new (quota_inode_ctx_t *ctx, char *name, ino_t par) goto err; } - dentry->par = par; + uuid_copy (dentry->par, par); list_add_tail (&dentry->next, &ctx->parents); err: @@ -194,13 +185,13 @@ out: 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) + 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; - quota_priv_t *priv = NULL; int64_t *size = 0; uint64_t value = 0; call_stub_t *stub = NULL; @@ -212,9 +203,6 @@ quota_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } GF_ASSERT (local); - - priv = this->private; - GF_ASSERT (frame); GF_VALIDATE_OR_GOTO_WITH_ERROR ("quota", this, unwind, op_errno, EINVAL); @@ -226,8 +214,7 @@ quota_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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 (ino:%"PRId64", " - "gfid:%s)", local->validate_loc.inode->ino, + "quota context is not present in inode (gfid:%s)", uuid_utoa (local->validate_loc.inode->gfid)); op_errno = EINVAL; goto unwind; @@ -252,7 +239,7 @@ quota_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } UNLOCK (&ctx->lock); - quota_check_limit (frame, local->validate_loc.inode, this, NULL, 0); + quota_check_limit (frame, local->validate_loc.inode, this, NULL, NULL); return 0; unwind: @@ -304,7 +291,7 @@ quota_timeout (struct timeval *tv, int32_t timeout) int32_t quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, - char *name, ino_t par) + char *name, uuid_t par) { int32_t ret = -1; inode_t *_inode = NULL, *parent = NULL; @@ -317,6 +304,7 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, 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); GF_VALIDATE_OR_GOTO (this->name, frame, out); @@ -336,8 +324,20 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, _inode = inode_ref (inode); - just_validated = local->just_validated; - local->just_validated = 0; + 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); + } do { if (ctx != NULL) { @@ -367,27 +367,27 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, } } - if (_inode->ino == 1) { + if (__is_root_gfid (_inode->gfid)) { break; } - parent = inode_parent (_inode, par, name); + parent = inode_parent (_inode, trav_uuid, name); if (name != NULL) { name = NULL; - par = 0; + uuid_clear (trav_uuid); } if (parent == NULL) { - gf_log (this->name, GF_LOG_WARNING, - "cannot find parent for inode (ino:%"PRId64", " - "gfid:%s), hence aborting enforcing " - "quota-limits and continuing with the fop", - _inode->ino, uuid_utoa (_inode->gfid)); + gf_log (this->name, GF_LOG_DEBUG, + "cannot find parent for inode (gfid:%s), hence " + "aborting enforcing quota-limits and continuing" + " with the fop", uuid_utoa (_inode->gfid)); } inode_unref (_inode); _inode = parent; + just_validated = 0; if (_inode == NULL) { break; @@ -406,10 +406,6 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this, LOCK (&local->lock); { - if (just_validated) { - local->validate_count--; - } - validate_count = local->validate_count; link_count = local->link_count; if ((validate_count == 0) && (link_count == 0)) { @@ -439,9 +435,8 @@ validate: ret = quota_inode_loc_fill (_inode, &local->validate_loc); if (ret < 0) { gf_log (this->name, GF_LOG_WARNING, - "cannot fill loc for inode (ino:%"PRId64", " - "gfid:%s), hence aborting quota-checks and " - "continuing with the fop", _inode->ino, + "cannot fill loc for inode (gfid:%s), hence " + "aborting quota-checks and continuing with fop", uuid_utoa (_inode->gfid)); local->validate_count--; } @@ -454,7 +449,7 @@ validate: STACK_WIND (frame, quota_validate_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->getxattr, &local->validate_loc, - QUOTA_SIZE_KEY); + QUOTA_SIZE_KEY, NULL); loc_fill_failed: inode_unref (_inode); @@ -493,6 +488,8 @@ quota_get_limit_value (inode_t *inode, xlator_t *this, int64_t *n) } out: + GF_FREE (path); + return ret; } @@ -505,14 +502,11 @@ __quota_init_inode_ctx (inode_t *inode, int64_t limit, xlator_t *this, int32_t ret = -1; int64_t *size = 0; quota_inode_ctx_t *ctx = NULL; - quota_priv_t *priv = NULL; if (inode == NULL) { goto out; } - priv = this->private; - QUOTA_ALLOC_OR_GOTO (ctx, quota_inode_ctx_t, out); ctx->limit = limit; @@ -538,8 +532,8 @@ __quota_init_inode_ctx (inode_t *inode, int64_t limit, xlator_t *this, 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 (ino:%"PRId64", " - "gfid:%s)", inode->ino, uuid_utoa (inode->gfid)); + "cannot set quota context in inode (gfid:%s)", + uuid_utoa (inode->gfid)); } out: return ret; @@ -576,30 +570,47 @@ 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; - quota_priv_t *priv = NULL; - int64_t *size = 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; + if ((op_ret < 0) || (local == NULL) - || ((local->limit < 0) && !((IA_ISREG (buf->ia_type)) - || (IA_ISLNK (buf->ia_type))))) { + || (((ctx == NULL) || (ctx->limit == local->limit)) + && (local->limit < 0) && !((IA_ISREG (buf->ia_type)) + || (IA_ISLNK (buf->ia_type))))) { goto unwind; } - priv = this->private; + 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)) { gf_log (this->name, GF_LOG_WARNING, "cannot create quota " - "context in inode(ino:%"PRId64", gfid:%s)", - local->loc.inode->ino, + "context in inode(gfid:%s)", uuid_utoa (local->loc.inode->gfid)); op_ret = -1; op_errno = ENOMEM; @@ -628,9 +639,13 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto unlock; } + if (local->loc.name == NULL) + goto unlock; + list_for_each_entry (dentry, &ctx->parents, next) { - if ((strcmp (dentry->name, local->loc.name) == 0) - && (local->loc.parent->ino == dentry->par)) { + if ((strcmp (dentry->name, local->loc.name) == 0) && + (uuid_compare (local->loc.parent->gfid, + dentry->par) == 0)) { found = 1; break; } @@ -639,15 +654,13 @@ quota_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (!found) { dentry = __quota_dentry_new (ctx, (char *)local->loc.name, - local->loc.parent->ino); + local->loc.parent->gfid); if (dentry == NULL) { /* gf_log (this->name, GF_LOG_WARNING, "cannot create a new dentry (par:%" PRId64", name:%s) for inode(ino:%" PRId64", gfid:%s)", - local->loc.parent->ino, - local->loc.inode->ino, uuid_utoa (local->loc.inode->gfid)); */ op_ret = -1; @@ -734,12 +747,14 @@ err: void -quota_update_size (xlator_t *this, inode_t *inode, char *name, ino_t par, +quota_update_size (xlator_t *this, inode_t *inode, char *name, uuid_t par, int64_t delta) { - inode_t *_inode = NULL, *parent = NULL; - uint64_t value = 0; - quota_inode_ctx_t *ctx = NULL; + inode_t *_inode = NULL; + inode_t *parent = NULL; + uint64_t value = 0; + quota_inode_ctx_t *ctx = NULL; + uuid_t trav_uuid = {0,}; GF_VALIDATE_OR_GOTO ("quota", this, out); GF_VALIDATE_OR_GOTO (this->name, inode, out); @@ -749,6 +764,10 @@ quota_update_size (xlator_t *this, inode_t *inode, char *name, ino_t par, _inode = inode_ref (inode); + if ( par != NULL ) { + uuid_copy (trav_uuid, par); + } + do { if ((ctx != NULL) && (ctx->limit >= 0)) { LOCK (&ctx->lock); @@ -758,22 +777,21 @@ quota_update_size (xlator_t *this, inode_t *inode, char *name, ino_t par, UNLOCK (&ctx->lock); } - if (_inode->ino == 1) { + if (__is_root_gfid (_inode->gfid)) { break; } - parent = inode_parent (_inode, par, name); + parent = inode_parent (_inode, trav_uuid, name); if (parent == NULL) { - gf_log (this->name, GF_LOG_WARNING, - "cannot find parent for inode (ino:%"PRId64", " - "gfid:%s), hence aborting size updation of " - "parents", - _inode->ino, uuid_utoa (_inode->gfid)); + gf_log (this->name, GF_LOG_DEBUG, + "cannot find parent for inode (gfid:%s), hence " + "aborting size updation of parents", + uuid_utoa (_inode->gfid)); } if (name != NULL) { name = NULL; - par = 0; + uuid_clear (trav_uuid); } inode_unref (_inode); @@ -795,7 +813,7 @@ out: int32_t quota_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf) + struct iatt *postbuf, dict_t *xdata) { int32_t ret = 0; uint64_t ctx_int = 0; @@ -811,14 +829,18 @@ quota_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } 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 inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, - uuid_utoa (local->loc.inode->gfid)); + "quota context not set in %s (gfid:%s)", + local->loc.path, uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -835,7 +857,8 @@ quota_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } out: - QUOTA_STACK_UNWIND (writev, frame, op_ret, op_errno, prebuf, postbuf); + QUOTA_STACK_UNWIND (writev, frame, op_ret, op_errno, prebuf, postbuf, + xdata); return 0; } @@ -844,7 +867,7 @@ 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, - struct iobref *iobref) + uint32_t flags, struct iobref *iobref, dict_t *xdata) { quota_local_t *local = NULL; int32_t op_errno = EINVAL; @@ -862,11 +885,11 @@ quota_writev_helper (call_frame_t *frame, xlator_t *this, fd_t *fd, STACK_WIND (frame, quota_writev_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, vector, count, off, - iobref); + flags, iobref, xdata); return 0; unwind: - QUOTA_STACK_UNWIND (writev, frame, -1, op_errno, NULL, NULL); + QUOTA_STACK_UNWIND (writev, frame, -1, op_errno, NULL, NULL, NULL); return 0; } @@ -874,7 +897,7 @@ unwind: int32_t quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t off, - struct iobref *iobref) + uint32_t flags, struct iobref *iobref, dict_t *xdata) { int32_t ret = -1, op_errno = EINVAL; int32_t parents = 0; @@ -900,14 +923,13 @@ quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, 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 (ino:%"PRId64", " - "gfid:%s)", fd->inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (fd->inode->gfid)); goto unwind; } stub = fop_writev_stub (frame, quota_writev_helper, fd, vector, count, - off, iobref); + off, flags, iobref, xdata); if (stub == NULL) { op_errno = ENOMEM; goto unwind; @@ -956,7 +978,7 @@ quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, return 0; unwind: - QUOTA_STACK_UNWIND (writev, frame, -1, op_errno, NULL, NULL); + QUOTA_STACK_UNWIND (writev, frame, -1, op_errno, NULL, NULL, NULL); return 0; } @@ -965,17 +987,17 @@ int32_t quota_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { QUOTA_STACK_UNWIND (mkdir, frame, op_ret, op_errno, inode, - buf, preparent, postparent); + buf, preparent, postparent, xdata); return 0; } int32_t quota_mkdir_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, - mode_t mode, dict_t *params) + mode_t mode, mode_t umask, dict_t *xdata) { quota_local_t *local = NULL; int32_t op_errno = EINVAL; @@ -993,19 +1015,19 @@ quota_mkdir_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, } STACK_WIND (frame, quota_mkdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mkdir, loc, mode, params); + 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, NULL, NULL); return 0; } int32_t quota_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, - dict_t *params) + mode_t umask, dict_t *xdata) { int32_t ret = 0, op_errno = 0; quota_local_t *local = NULL; @@ -1028,7 +1050,8 @@ 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, params); + stub = fop_mkdir_stub (frame, quota_mkdir_helper, loc, mode, umask, + xdata); if (stub == NULL) { op_errno = ENOMEM; goto err; @@ -1037,7 +1060,7 @@ quota_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, local->stub = stub; local->delta = 0; - quota_check_limit (frame, loc->parent, this, NULL, 0); + quota_check_limit (frame, loc->parent, this, NULL, NULL); stub = NULL; @@ -1059,7 +1082,7 @@ quota_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, return 0; err: QUOTA_STACK_UNWIND (mkdir, frame, -1, op_errno, NULL, NULL, NULL, - NULL); + NULL, NULL); return 0; } @@ -1069,7 +1092,7 @@ int32_t quota_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { int32_t ret = -1; quota_local_t *local = NULL; @@ -1084,8 +1107,8 @@ quota_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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(ino:%"PRId64", gfid:%s)", - inode->ino, uuid_utoa (inode->gfid)); + "context in inode(gfid:%s)", + uuid_utoa (inode->gfid)); op_ret = -1; op_errno = ENOMEM; goto unwind; @@ -1096,13 +1119,11 @@ quota_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ctx->buf = *buf; dentry = __quota_dentry_new (ctx, (char *)local->loc.name, - local->loc.parent->ino); + local->loc.parent->gfid); if (dentry == NULL) { gf_log (this->name, GF_LOG_WARNING, - "cannot create a new dentry (par:%" - PRId64", name:%s) for inode(ino:%" - PRId64", gfid:%s)", local->loc.parent->ino, - local->loc.name, local->loc.inode->ino, + "cannot create a new dentry (name:%s) for " + "inode(gfid:%s)", local->loc.name, uuid_utoa (local->loc.inode->gfid)); op_ret = -1; op_errno = ENOMEM; @@ -1114,14 +1135,15 @@ unlock: unwind: QUOTA_STACK_UNWIND (create, frame, op_ret, op_errno, fd, inode, buf, - preparent, postparent); + preparent, postparent, xdata); return 0; } int32_t quota_create_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, - int32_t flags, mode_t mode, fd_t *fd, dict_t *params) + 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; @@ -1138,20 +1160,20 @@ quota_create_helper (call_frame_t *frame, xlator_t *this, loc_t *loc, } STACK_WIND (frame, quota_create_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, loc, flags, mode, fd, - params); + 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, 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, fd_t *fd, dict_t *params) + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { int32_t ret = -1; quota_local_t *local = NULL; @@ -1171,7 +1193,7 @@ quota_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, } stub = fop_create_stub (frame, quota_create_helper, loc, flags, mode, - fd, params); + umask, fd, xdata); if (stub == NULL) { goto err; } @@ -1180,7 +1202,7 @@ quota_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, local->stub = stub; local->delta = 0; - quota_check_limit (frame, loc->parent, this, NULL, 0); + quota_check_limit (frame, loc->parent, this, NULL, NULL); stub = NULL; @@ -1201,7 +1223,7 @@ quota_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, return 0; err: QUOTA_STACK_UNWIND (create, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, - NULL); + NULL, NULL); return 0; } @@ -1210,7 +1232,7 @@ err: int32_t quota_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -1227,25 +1249,25 @@ quota_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } quota_update_size (this, local->loc.inode, (char *)local->loc.name, - local->loc.parent->ino, + local->loc.parent->gfid, (-(ctx->buf.ia_blocks * 512))); out: QUOTA_STACK_UNWIND (unlink, frame, op_ret, op_errno, preparent, - postparent); + postparent, xdata); return 0; } int32_t -quota_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) +quota_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata) { int32_t ret = 0; quota_local_t *local = NULL; @@ -1264,13 +1286,13 @@ quota_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) } STACK_WIND (frame, quota_unlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, loc); + FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); ret = 0; err: if (ret == -1) { - QUOTA_STACK_UNWIND (unlink, frame, -1, 0, NULL, NULL); + QUOTA_STACK_UNWIND (unlink, frame, -1, 0, NULL, NULL, NULL); } return 0; @@ -1281,7 +1303,7 @@ int32_t quota_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { int32_t ret = -1; quota_local_t *local = NULL; @@ -1295,14 +1317,14 @@ quota_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local = (quota_local_t *) frame->local; - quota_update_size (this, local->loc.parent, NULL, 0, + quota_update_size (this, local->loc.parent, NULL, NULL, (buf->ia_blocks * 512)); 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 inode(ino:%"PRId64", gfid:%s)", - inode->ino, uuid_utoa (inode->gfid)); + "context in %s (gfid:%s)", local->loc.path, + uuid_utoa (inode->gfid)); op_ret = -1; op_errno = EINVAL; goto out; @@ -1311,15 +1333,14 @@ quota_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, LOCK (&ctx->lock); { list_for_each_entry (dentry, &ctx->parents, next) { - if ((strcmp (dentry->name, local->loc.name) == 0) - && (local->loc.parent->ino == dentry->par)) { + if ((strcmp (dentry->name, local->loc.name) == 0) && + (uuid_compare (local->loc.parent->gfid, + dentry->par) == 0)) { found = 1; gf_log (this->name, GF_LOG_WARNING, - "new entry being linked (par:%" - PRId64", name:%s) for inode (ino:%" - PRId64", gfid:%s) is already present " - "in inode-dentry-list", dentry->par, - dentry->name, local->loc.inode->ino, + "new entry being linked (name:%s) for " + "inode (gfid:%s) is already present " + "in inode-dentry-list", dentry->name, uuid_utoa (local->loc.inode->gfid)); break; } @@ -1328,15 +1349,11 @@ quota_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (!found) { dentry = __quota_dentry_new (ctx, (char *)local->loc.name, - local->loc.parent->ino); + local->loc.parent->gfid); if (dentry == NULL) { gf_log (this->name, GF_LOG_WARNING, - "cannot create a new dentry (par:%" - PRId64", name:%s) for inode(ino:%" - PRId64", gfid:%s)", - local->loc.parent->ino, - local->loc.name, - local->loc.inode->ino, + "cannot create a new dentry (name:%s) " + "for inode(gfid:%s)", local->loc.name, uuid_utoa (local->loc.inode->gfid)); op_ret = -1; op_errno = ENOMEM; @@ -1351,7 +1368,7 @@ unlock: out: QUOTA_STACK_UNWIND (link, frame, op_ret, op_errno, inode, buf, - preparent, postparent); + preparent, postparent, xdata); return 0; } @@ -1359,7 +1376,7 @@ out: int32_t quota_link_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc) + loc_t *newloc, dict_t *xdata) { quota_local_t *local = NULL; int32_t op_errno = EINVAL; @@ -1377,18 +1394,19 @@ quota_link_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc, } STACK_WIND (frame, quota_link_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, oldloc, newloc); + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); return 0; unwind: QUOTA_STACK_UNWIND (link, frame, -1, op_errno, NULL, NULL, - NULL, NULL); + NULL, NULL, NULL); return 0; } int32_t -quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) +quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) { int32_t ret = -1, op_errno = ENOMEM; quota_local_t *local = NULL; @@ -1408,7 +1426,7 @@ quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) goto err; } - stub = fop_link_stub (frame, quota_link_helper, oldloc, newloc); + stub = fop_link_stub (frame, quota_link_helper, oldloc, newloc, xdata); if (stub == NULL) { goto err; } @@ -1420,16 +1438,15 @@ quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", oldloc->inode?oldloc->inode->ino:0, - oldloc->inode?uuid_utoa (oldloc->inode->gfid):"0"); + "quota context not set in inode (gfid:%s)", + oldloc->inode ? uuid_utoa (oldloc->inode->gfid) : "0"); op_errno = EINVAL; goto err; } local->delta = ctx->buf.ia_blocks * 512; - quota_check_limit (frame, newloc->parent, this, NULL, 0); + quota_check_limit (frame, newloc->parent, this, NULL, NULL); stub = NULL; @@ -1452,7 +1469,7 @@ quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) err: if (ret < 0) { QUOTA_STACK_UNWIND (link, frame, -1, op_errno, NULL, NULL, - NULL, NULL); + NULL, NULL, NULL); } return 0; @@ -1463,7 +1480,8 @@ int32_t quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *buf, struct iatt *preoldparent, struct iatt *postoldparent, - struct iatt *prenewparent, struct iatt *postnewparent) + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) { int32_t ret = -1; quota_local_t *local = NULL; @@ -1490,8 +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, 0, (-size)); - quota_update_size (this, local->newloc.parent, NULL, 0, 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) @@ -1503,8 +1521,7 @@ quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if ((ret == -1) || (ctx == NULL)) { gf_log (this->name, GF_LOG_WARNING, "quota context not" - "set in inode(ino:%"PRId64", gfid:%s)", - local->oldloc.inode->ino, + "set in inode(gfid:%s)", uuid_utoa (local->oldloc.inode->gfid)); op_ret = -1; op_errno = EINVAL; @@ -1520,19 +1537,19 @@ quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, * should be changed to set a new context in newloc->inode. */ list_for_each_entry (dentry, &ctx->parents, next) { - if ((strcmp (dentry->name, local->oldloc.name) == 0) - && (local->oldloc.parent->ino == dentry->par)) { + if ((strcmp (dentry->name, local->oldloc.name) == 0) && + (uuid_compare (local->oldloc.parent->gfid, + dentry->par) == 0)) { old_dentry = dentry; - } else if ((strcmp (dentry->name, local->newloc.name) - == 0) && (local->oldloc.parent->ino - == dentry->par)) { + } else if ((strcmp (dentry->name, + local->newloc.name) == 0) && + (uuid_compare (local->oldloc.parent->gfid, + dentry->par) == 0)) { new_dentry_found = 1; gf_log (this->name, GF_LOG_WARNING, - "new entry being linked (par:%" - PRId64", name:%s) for inode (ino:%" - PRId64", gfid:%s) is already present " - "in inode-dentry-list", dentry->par, - dentry->name, local->newloc.inode->ino, + "new entry being linked (name:%s) for " + "inode (gfid:%s) is already present " + "in inode-dentry-list", dentry->name, uuid_utoa (local->newloc.inode->gfid)); break; } @@ -1543,22 +1560,17 @@ quota_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } else { gf_log (this->name, GF_LOG_WARNING, "dentry corresponding to the path just renamed " - "(par:%"PRId64", name:%s) is not present", - local->oldloc.inode->ino, local->oldloc.name); + "(name:%s) is not present", local->oldloc.name); } if (!new_dentry_found) { dentry = __quota_dentry_new (ctx, (char *)local->newloc.name, - local->newloc.parent->ino); + local->newloc.parent->gfid); if (dentry == NULL) { gf_log (this->name, GF_LOG_WARNING, - "cannot create a new dentry (par:%" - PRId64", name:%s) for inode(ino:%" - PRId64", gfid:%s)", - local->newloc.parent->ino, - local->newloc.name, - local->newloc.inode->ino, + "cannot create a new dentry (name:%s) " + "for inode(gfid:%s)", local->newloc.name, uuid_utoa (local->newloc.inode->gfid)); op_ret = -1; op_errno = ENOMEM; @@ -1573,7 +1585,7 @@ unlock: out: QUOTA_STACK_UNWIND (rename, frame, op_ret, op_errno, buf, preoldparent, - postoldparent, prenewparent, postnewparent); + postoldparent, prenewparent, postnewparent, xdata); return 0; } @@ -1581,7 +1593,7 @@ out: int32_t quota_rename_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc) + loc_t *newloc, dict_t *xdata) { quota_local_t *local = NULL; int32_t op_errno = EINVAL; @@ -1599,19 +1611,19 @@ quota_rename_helper (call_frame_t *frame, xlator_t *this, loc_t *oldloc, } STACK_WIND (frame, quota_rename_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, oldloc, newloc); + 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, NULL, NULL, NULL); return 0; } int32_t quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc) + loc_t *newloc, dict_t *xdata) { int32_t ret = -1, op_errno = ENOMEM; quota_local_t *local = NULL; @@ -1637,7 +1649,8 @@ quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, goto err; } - stub = fop_rename_stub (frame, quota_rename_helper, oldloc, newloc); + stub = fop_rename_stub (frame, quota_rename_helper, oldloc, newloc, + xdata); if (stub == NULL) { goto err; } @@ -1651,11 +1664,9 @@ quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", - oldloc->inode ? oldloc->inode->ino:0, + "quota context not set in inode (gfid:%s)", oldloc->inode ? uuid_utoa (oldloc->inode->gfid) - :"0"); + : "0"); op_errno = EINVAL; goto err; } @@ -1664,7 +1675,7 @@ quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, local->delta = 0; } - quota_check_limit (frame, newloc->parent, this, NULL, 0); + quota_check_limit (frame, newloc->parent, this, NULL, NULL); stub = NULL; @@ -1687,7 +1698,7 @@ quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, err: if (ret == -1) { QUOTA_STACK_UNWIND (rename, frame, -1, op_errno, NULL, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); } return 0; @@ -1698,7 +1709,7 @@ int32_t quota_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { int64_t size = 0; quota_local_t *local = NULL; @@ -1712,14 +1723,13 @@ quota_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local = frame->local; size = buf->ia_blocks * 512; - quota_update_size (this, local->loc.parent, NULL, 0, size); + quota_update_size (this, local->loc.parent, NULL, NULL, size); quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 1); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -1729,13 +1739,11 @@ quota_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ctx->buf = *buf; dentry = __quota_dentry_new (ctx, (char *)local->loc.name, - local->loc.parent->ino); + local->loc.parent->gfid); if (dentry == NULL) { gf_log (this->name, GF_LOG_WARNING, - "cannot create a new dentry (par:%" - PRId64", name:%s) for inode(ino:%" - PRId64", gfid:%s)", local->loc.parent->ino, - local->loc.name, local->loc.inode->ino, + "cannot create a new dentry (name:%s) for " + "inode(gfid:%s)", local->loc.name, uuid_utoa (local->loc.inode->gfid)); op_ret = -1; op_errno = ENOMEM; @@ -1745,7 +1753,7 @@ quota_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, out: QUOTA_STACK_UNWIND (symlink, frame, op_ret, op_errno, inode, buf, - preparent, postparent); + preparent, postparent, xdata); return 0; } @@ -1753,7 +1761,7 @@ out: int quota_symlink_helper (call_frame_t *frame, xlator_t *this, const char *linkpath, - loc_t *loc, dict_t *params) + loc_t *loc, mode_t umask, dict_t *xdata) { quota_local_t *local = NULL; int32_t op_errno = EINVAL; @@ -1770,19 +1778,20 @@ quota_symlink_helper (call_frame_t *frame, xlator_t *this, const char *linkpath, } STACK_WIND (frame, quota_symlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->symlink, linkpath, loc, params); + 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, NULL, NULL); return 0; } int quota_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, - loc_t *loc, dict_t *params) + loc_t *loc, mode_t umask, dict_t *xdata) { int32_t ret = -1; int32_t op_errno = ENOMEM; @@ -1805,7 +1814,7 @@ quota_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, local->link_count = 1; stub = fop_symlink_stub (frame, quota_symlink_helper, linkpath, loc, - params); + umask, xdata); if (stub == NULL) { goto err; } @@ -1813,7 +1822,7 @@ quota_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, local->stub = stub; local->delta = strlen (linkpath); - quota_check_limit (frame, loc->parent, this, NULL, 0); + quota_check_limit (frame, loc->parent, this, NULL, NULL); stub = NULL; @@ -1836,7 +1845,7 @@ quota_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, err: QUOTA_STACK_UNWIND (symlink, frame, -1, op_errno, NULL, NULL, NULL, - NULL); + NULL, NULL); return 0; } @@ -1845,7 +1854,7 @@ err: int32_t quota_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf) + struct iatt *postbuf, dict_t *xdata) { quota_local_t *local = NULL; int64_t delta = 0; @@ -1863,14 +1872,13 @@ quota_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, delta = (postbuf->ia_blocks - prebuf->ia_blocks) * 512; - quota_update_size (this, local->loc.inode, NULL, 0, delta); + quota_update_size (this, local->loc.inode, NULL, NULL, delta); quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -1883,13 +1891,14 @@ quota_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, out: QUOTA_STACK_UNWIND (truncate, frame, op_ret, op_errno, prebuf, - postbuf); + postbuf, xdata); return 0; } int32_t -quota_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) +quota_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, + dict_t *xdata) { int32_t ret = -1; quota_local_t *local = NULL; @@ -1908,11 +1917,11 @@ quota_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) } STACK_WIND (frame, quota_truncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->truncate, loc, offset); + FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); return 0; err: - QUOTA_STACK_UNWIND (truncate, frame, -1, ENOMEM, NULL, NULL); + QUOTA_STACK_UNWIND (truncate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -1921,7 +1930,7 @@ err: int32_t quota_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf) + struct iatt *postbuf, dict_t *xdata) { quota_local_t *local = NULL; int64_t delta = 0; @@ -1939,14 +1948,13 @@ quota_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, delta = (postbuf->ia_blocks - prebuf->ia_blocks) * 512; - quota_update_size (this, local->loc.inode, NULL, 0, delta); + quota_update_size (this, local->loc.inode, NULL, NULL, delta); quota_inode_ctx_get (local->loc.inode, -1, this, NULL, NULL, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -1959,13 +1967,14 @@ quota_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, out: QUOTA_STACK_UNWIND (ftruncate, frame, op_ret, op_errno, prebuf, - postbuf); + postbuf, xdata); return 0; } int32_t -quota_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +quota_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + dict_t *xdata) { quota_local_t *local = NULL; @@ -1978,11 +1987,11 @@ quota_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) local->loc.inode = inode_ref (fd->inode); STACK_WIND (frame, quota_ftruncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, fd, offset); + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); return 0; err: - QUOTA_STACK_UNWIND (ftruncate, frame, -1, ENOMEM, NULL, NULL); + QUOTA_STACK_UNWIND (ftruncate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -2017,7 +2026,7 @@ quota_send_dir_limit_to_cli (call_frame_t *frame, xlator_t *this, gf_log (this->name, GF_LOG_INFO, "str = %s", dir_limit); - QUOTA_STACK_UNWIND (getxattr, frame, 0, 0, dict); + QUOTA_STACK_UNWIND (getxattr, frame, 0, 0, dict, NULL); ret = 0; @@ -2028,11 +2037,11 @@ out: int32_t quota_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name) + const char *name, dict_t *xdata) { int32_t ret = 0; - if (strcasecmp (name, "trusted.limit.list") == 0) { + if (name && strcasecmp (name, "trusted.limit.list") == 0) { ret = quota_send_dir_limit_to_cli (frame, this, fd->inode, name); if (ret == 0) { @@ -2041,14 +2050,14 @@ quota_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, } STACK_WIND (frame, default_fgetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, fd, name); + FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata); return 0; } int32_t quota_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name) + const char *name, dict_t *xdata) { int32_t ret = 0; @@ -2060,14 +2069,14 @@ quota_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, } STACK_WIND (frame, default_getxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, loc, name); + FIRST_CHILD(this)->fops->getxattr, loc, name, xdata); return 0; } 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) + 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; @@ -2086,8 +2095,7 @@ quota_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_DEBUG, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -2100,13 +2108,13 @@ quota_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, UNLOCK (&ctx->lock); out: - QUOTA_STACK_UNWIND (stat, frame, op_ret, op_errno, buf); + QUOTA_STACK_UNWIND (stat, frame, op_ret, op_errno, buf, xdata); return 0; } int32_t -quota_stat (call_frame_t *frame, xlator_t *this, loc_t *loc) +quota_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { quota_local_t *local = NULL; int32_t ret = -1; @@ -2124,18 +2132,19 @@ quota_stat (call_frame_t *frame, xlator_t *this, loc_t *loc) } STACK_WIND (frame, quota_stat_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->stat, loc); + FIRST_CHILD(this)->fops->stat, loc, xdata); return 0; unwind: - QUOTA_STACK_UNWIND (stat, frame, -1, ENOMEM, NULL); + QUOTA_STACK_UNWIND (stat, frame, -1, ENOMEM, NULL, NULL); return 0; } int32_t quota_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *buf) + 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; @@ -2154,8 +2163,7 @@ quota_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -2168,13 +2176,13 @@ quota_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, UNLOCK (&ctx->lock); out: - QUOTA_STACK_UNWIND (fstat, frame, op_ret, op_errno, buf); + QUOTA_STACK_UNWIND (fstat, frame, op_ret, op_errno, buf, xdata); return 0; } int32_t -quota_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd) +quota_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { quota_local_t *local = NULL; @@ -2188,11 +2196,11 @@ quota_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd) local->loc.inode = inode_ref (fd->inode); STACK_WIND (frame, quota_fstat_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fstat, fd); + FIRST_CHILD(this)->fops->fstat, fd, xdata); return 0; unwind: - QUOTA_STACK_UNWIND (fstat, frame, -1, ENOMEM, NULL); + QUOTA_STACK_UNWIND (fstat, frame, -1, ENOMEM, NULL, NULL); return 0; } @@ -2200,7 +2208,7 @@ unwind: int32_t quota_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, const char *path, - struct iatt *buf) + struct iatt *buf, dict_t *xdata) { quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -2219,8 +2227,7 @@ quota_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -2232,13 +2239,14 @@ 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); + QUOTA_STACK_UNWIND (readlink, frame, op_ret, op_errno, path, buf, xdata); return 0; } int32_t -quota_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size) +quota_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, + dict_t *xdata) { quota_local_t *local = NULL; int32_t ret = -1; @@ -2257,11 +2265,11 @@ quota_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size) } STACK_WIND (frame, quota_readlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readlink, loc, size); + FIRST_CHILD(this)->fops->readlink, loc, size, xdata); return 0; unwind: - QUOTA_STACK_UNWIND (readlink, frame, -1, ENOMEM, NULL, NULL); + QUOTA_STACK_UNWIND (readlink, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -2269,7 +2277,8 @@ unwind: int32_t quota_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iovec *vector, - int32_t count, struct iatt *buf, struct iobref *iobref) + int32_t count, struct iatt *buf, struct iobref *iobref, + dict_t *xdata) { quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -2288,8 +2297,7 @@ quota_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -2302,14 +2310,14 @@ quota_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, out: QUOTA_STACK_UNWIND (readv, frame, op_ret, op_errno, vector, count, - buf, iobref); + buf, iobref, xdata); return 0; } int32_t quota_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - off_t offset) + off_t offset, uint32_t flags, dict_t *xdata) { quota_local_t *local = NULL; @@ -2323,11 +2331,12 @@ quota_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, local->loc.inode = inode_ref (fd->inode); STACK_WIND (frame, quota_readv_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readv, fd, size, offset); + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, + xdata); return 0; unwind: - QUOTA_STACK_UNWIND (readv, frame, -1, ENOMEM, NULL, -1, NULL, NULL); + QUOTA_STACK_UNWIND (readv, frame, -1, ENOMEM, NULL, -1, NULL, NULL, NULL); return 0; } @@ -2335,7 +2344,7 @@ unwind: int32_t quota_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf) + struct iatt *postbuf, dict_t *xdata) { quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -2354,8 +2363,7 @@ quota_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -2367,13 +2375,15 @@ quota_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, UNLOCK (&ctx->lock); out: - QUOTA_STACK_UNWIND (fsync, frame, op_ret, op_errno, prebuf, postbuf); + QUOTA_STACK_UNWIND (fsync, frame, op_ret, op_errno, prebuf, postbuf, + xdata); return 0; } int32_t -quota_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +quota_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, + dict_t *xdata) { quota_local_t *local = NULL; @@ -2387,11 +2397,11 @@ quota_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) frame->local = local; STACK_WIND (frame, quota_fsync_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsync, fd, flags); + FIRST_CHILD(this)->fops->fsync, fd, flags, xdata); return 0; unwind: - QUOTA_STACK_UNWIND (fsync, frame, -1, ENOMEM, NULL, NULL); + QUOTA_STACK_UNWIND (fsync, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -2400,7 +2410,7 @@ unwind: int32_t quota_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *statpre, - struct iatt *statpost) + struct iatt *statpost, dict_t *xdata) { quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -2419,8 +2429,7 @@ quota_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_DEBUG, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -2434,14 +2443,14 @@ quota_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, out: QUOTA_STACK_UNWIND (setattr, frame, op_ret, op_errno, statpre, - statpost); + statpost, xdata); return 0; } int32_t quota_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - struct iatt *stbuf, int32_t valid) + struct iatt *stbuf, int32_t valid, dict_t *xdata) { quota_local_t *local = NULL; int32_t ret = -1; @@ -2460,11 +2469,11 @@ quota_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, } STACK_WIND (frame, quota_setattr_cbk, FIRST_CHILD (this), - FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid); + FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, xdata); return 0; unwind: - QUOTA_STACK_UNWIND (setattr, frame, -1, ENOMEM, NULL, NULL); + QUOTA_STACK_UNWIND (setattr, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -2472,7 +2481,7 @@ unwind: int32_t quota_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *statpre, - struct iatt *statpost) + struct iatt *statpost, dict_t *xdata) { quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -2491,8 +2500,7 @@ quota_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, &ctx, 0); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota context not set in inode (ino:%"PRId64 - ", gfid:%s)", local->loc.inode->ino, + "quota context not set in inode (gfid:%s)", uuid_utoa (local->loc.inode->gfid)); goto out; } @@ -2505,14 +2513,14 @@ quota_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, out: QUOTA_STACK_UNWIND (fsetattr, frame, op_ret, op_errno, statpre, - statpost); + statpost, xdata); return 0; } int32_t quota_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iatt *stbuf, int32_t valid) + struct iatt *stbuf, int32_t valid, dict_t *xdata) { quota_local_t *local = NULL; @@ -2526,11 +2534,609 @@ quota_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, local->loc.inode = inode_ref (fd->inode); STACK_WIND (frame, quota_fsetattr_cbk, FIRST_CHILD (this), - FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid); + FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid, xdata); + return 0; + +unwind: + QUOTA_STACK_UNWIND (fsetattr, frame, -1, ENOMEM, NULL, NULL, NULL); + return 0; +} + + +int32_t +quota_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + int32_t ret = -1; + quota_local_t *local = NULL; + quota_inode_ctx_t *ctx = NULL; + quota_dentry_t *dentry = NULL; + + local = frame->local; + if (op_ret < 0) { + goto unwind; + } + + 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)); + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + + LOCK (&ctx->lock); + { + ctx->buf = *buf; + + dentry = __quota_dentry_new (ctx, (char *)local->loc.name, + local->loc.parent->gfid); + if (dentry == NULL) { + gf_log (this->name, GF_LOG_WARNING, + "cannot create a new dentry (name:%s) for " + "inode(gfid:%s)", local->loc.name, + uuid_utoa (local->loc.inode->gfid)); + op_ret = -1; + op_errno = ENOMEM; + goto unlock; + } + } +unlock: + UNLOCK (&ctx->lock); + +unwind: + QUOTA_STACK_UNWIND (mknod, frame, op_ret, op_errno, inode, + buf, preparent, postparent, xdata); + return 0; +} + + +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) +{ + int32_t ret = -1; + quota_local_t *local = NULL; + call_stub_t *stub = NULL; + + local = quota_local_new (); + if (local == NULL) { + goto err; + } + + frame->local = local; + + ret = loc_copy (&local->loc, loc); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "loc_copy failed"); + goto err; + } + + stub = fop_mknod_stub (frame, quota_mknod_helper, loc, mode, rdev, + umask, xdata); + if (stub == NULL) { + goto err; + } + + 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, ENOMEM, NULL, NULL, NULL, NULL, + NULL); + + return 0; +} + +int +quota_setxattr_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int op_ret, int op_errno, dict_t *xdata) +{ + QUOTA_STACK_UNWIND (setxattr, frame, op_ret, op_errno, xdata); + return 0; +} + +int +quota_setxattr (call_frame_t *frame, xlator_t *this, + loc_t *loc, dict_t *dict, int flags, dict_t *xdata) +{ + int op_errno = EINVAL; + int op_ret = -1; + + VALIDATE_OR_GOTO (frame, err); + VALIDATE_OR_GOTO (this, err); + VALIDATE_OR_GOTO (loc, err); + + GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.quota*", dict, + op_errno, err); + + 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); + return 0; +} + +int +quota_fsetxattr_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int op_ret, int op_errno, dict_t *xdata) +{ + QUOTA_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, xdata); + return 0; +} + +int +quota_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *dict, int flags, dict_t *xdata) +{ + int32_t op_ret = -1; + int32_t op_errno = EINVAL; + + VALIDATE_OR_GOTO (frame, err); + VALIDATE_OR_GOTO (this, err); + VALIDATE_OR_GOTO (fd, err); + + GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.quota*", dict, + op_errno, err); + + 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); + return 0; +} + + +int +quota_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + QUOTA_STACK_UNWIND (removexattr, frame, op_ret, op_errno, xdata); + return 0; +} + +int +quota_removexattr (call_frame_t *frame, xlator_t *this, + loc_t *loc, const char *name, dict_t *xdata) +{ + int32_t op_errno = EINVAL; + + VALIDATE_OR_GOTO (this, err); + + GF_IF_NATIVE_XATTR_GOTO ("trusted.quota*", + name, op_errno, err); + + VALIDATE_OR_GOTO (frame, err); + VALIDATE_OR_GOTO (loc, err); + + STACK_WIND (frame, quota_removexattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, + loc, name, xdata); + return 0; +err: + QUOTA_STACK_UNWIND (removexattr, frame, -1, op_errno, NULL); + return 0; +} + + +int +quota_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + QUOTA_STACK_UNWIND (fremovexattr, frame, op_ret, op_errno, xdata); + return 0; +} + +int +quota_fremovexattr (call_frame_t *frame, xlator_t *this, + fd_t *fd, const char *name, dict_t *xdata) +{ + int32_t op_ret = -1; + int32_t op_errno = EINVAL; + + VALIDATE_OR_GOTO (frame, err); + VALIDATE_OR_GOTO (this, err); + VALIDATE_OR_GOTO (fd, err); + + GF_IF_NATIVE_XATTR_GOTO ("trusted.quota*", + name, op_errno, err); + + STACK_WIND (frame, quota_fremovexattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, + fd, name, xdata); + return 0; + err: + QUOTA_STACK_UNWIND (fremovexattr, frame, op_ret, op_errno, NULL); + return 0; +} + + +int32_t +quota_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct statvfs *buf, + dict_t *xdata) +{ + inode_t *root_inode = NULL; + quota_priv_t *priv = NULL; + uint64_t value = 0; + quota_inode_ctx_t *ctx = NULL; + limits_t *limit_node = NULL; + int64_t usage = -1; + int64_t avail = -1; + int64_t blocks = 0; + + root_inode = cookie; + + /* This fop will fail mostly in case of client disconnect's, + * which is already logged. Hence, not logging here */ + if (op_ret == -1) + goto unwind; + /* + * We should never get here unless quota_statfs (below) sent us a + * cookie, and it would only do so if the value was non-NULL. This + * check is therefore just routine defensive coding. + */ + if (!root_inode) { + gf_log(this->name,GF_LOG_WARNING, + "null inode, cannot adjust for quota"); + goto unwind; + } + if (!root_inode->table || (root_inode != root_inode->table->root)) { + gf_log(this->name,GF_LOG_WARNING, + "non-root inode, cannot adjust for quota"); + goto unwind; + } + + inode_ctx_get (root_inode, this, &value); + if (!value) { + goto unwind; + } + ctx = (quota_inode_ctx_t *)(unsigned long)value; + usage = (ctx->size) / buf->f_bsize; + priv = this->private; + + 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->value / buf->f_bsize; + if (usage > blocks) { + break; + } + + buf->f_blocks = blocks; + avail = buf->f_blocks - usage; + if (buf->f_bfree > avail) { + buf->f_bfree = avail; + } + /* + * We have to assume that the total assigned quota + * won't cause us to dip into the reserved space, + * because dealing with the overcommitted cases is + * just too hairy (especially when different bricks + * might be using different reserved percentages and + * such). + */ + buf->f_bavail = buf->f_bfree; + break; + } + } + +unwind: + if (root_inode) { + inode_unref(root_inode); + } + STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, buf, xdata); + return 0; +} + + +int32_t +quota_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + inode_t *root_inode = NULL; + quota_priv_t *priv = NULL; + + priv = this->private; + + if (priv->consider_statfs && loc->inode) { + root_inode = loc->inode->table->root; + inode_ref(root_inode); + STACK_WIND_COOKIE (frame, quota_statfs_cbk, root_inode, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->statfs, loc, xdata); + } + else { + /* + * We have to make sure that we never get to quota_statfs_cbk + * with a cookie that points to something other than an inode, + * which is exactly what would happen with STACK_UNWIND using + * that as a callback. Therefore, use default_statfs_cbk in + * this case instead. + * + * Also if the option deem-statfs is not set to "on" don't + * bother calculating quota limit on / in statfs_cbk. + */ + if (priv->consider_statfs) + gf_log(this->name,GF_LOG_WARNING, + "missing inode, cannot adjust for quota"); + STACK_WIND (frame, default_statfs_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->statfs, loc, xdata); + } return 0; +} + + +int +quota_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + gf_dirent_t *entry = NULL; + + if (op_ret <= 0) + goto unwind; + + list_for_each_entry (entry, &entries->list, list) { + /* TODO: fill things */ + } unwind: - QUOTA_STACK_UNWIND (fsetattr, frame, -1, ENOMEM, NULL, NULL); + STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries, xdata); + + return 0; +} +int +quota_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, dict_t *dict) +{ + int ret = 0; + + if (dict) { + ret = dict_set_uint64 (dict, QUOTA_SIZE_KEY, 0); + if (ret < 0) { + goto err; + } + } + + 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_helper(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t mode, off_t offset, size_t len, 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_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 +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; + call_stub_t *stub = NULL; + quota_dentry_t *dentry = NULL; + + 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, 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; + } + + stub = fop_fallocate_stub(frame, quota_fallocate_helper, fd, mode, offset, len, + xdata); + if (stub == NULL) { + op_errno = ENOMEM; + goto unwind; + } + + priv = this->private; + GF_VALIDATE_OR_GOTO (this->name, priv, 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->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) { + break; + } + } + + 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; + +unwind: + QUOTA_STACK_UNWIND (fallocate, frame, -1, op_errno, NULL, NULL, NULL); return 0; } @@ -2586,52 +3192,28 @@ quota_forget (xlator_t *this, inode_t *inode) return 0; } -int -validate_options (xlator_t *this, char **op_errstr) -{ - int ret = 0; - volume_opt_list_t *vol_opt = NULL; - volume_opt_list_t *tmp; - - if (!this) { - gf_log (this->name, GF_LOG_DEBUG, "'this' not a valid ptr"); - ret =-1; - goto out; - } - - if (list_empty (&this->volume_options)) - goto out; - - vol_opt = list_entry (this->volume_options.next, - volume_opt_list_t, list); - list_for_each_entry_safe (vol_opt, tmp, &this->volume_options, list) { - ret = validate_xlator_volume_options_attacherr (this, - vol_opt->given_opt, - op_errstr); - } - -out: - return ret; -} - -int32_t -quota_parse_options (quota_priv_t *priv, xlator_t *this, dict_t *options) +int +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; + char *last_colon= NULL; - ret = dict_get_str (options, "limit-set", &str); + 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, ","); + last_colon = strrchr (path, ':'); + *last_colon = '\0'; + str_val = last_colon + 1; ret = gf_string2bytesize (str_val, &value); if (ret != 0) @@ -2646,40 +3228,40 @@ quota_parse_options (quota_priv_t *priv, xlator_t *this, dict_t *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; + } + } + } - path = strtok (NULL, ":"); + LOCK (&priv->lock); + { + list_add_tail ("a_lim->limit_list, + &priv->limit_head); + } + UNLOCK (&priv->lock); + + path = strtok_r (NULL, ",", &saveptr); } } else { gf_log (this->name, GF_LOG_INFO, "no \"limit-set\" option provided"); } - ret = dict_get_str (options, "timeout", &str); - if (str) { - ret = gf_string2bytesize (str, &value); - if (ret < 0) { - gf_log (this->name, GF_LOG_INFO, - "Invalid quota timout value."); - ret = -1; - goto err; - } else { - priv->timeout = (int64_t) value; - gf_log (this->name, GF_LOG_INFO, - "quota timeout value = %"PRId64, - priv->timeout); + 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); } - } else { - gf_log (this->name, GF_LOG_INFO, "timeout option not provided, " - "taking default as 0"); - priv->timeout = 0; - } - - 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: @@ -2710,41 +3292,151 @@ init (xlator_t *this) INIT_LIST_HEAD (&priv->limit_head); + LOCK_INIT (&priv->lock); + this->private = priv; - ret = quota_parse_options (priv, this, this->options); + ret = quota_parse_limits (priv, this, this->options, NULL); if (ret) { goto err; } + GF_OPTION_INIT ("timeout", priv->timeout, int64, err); + GF_OPTION_INIT ("deem-statfs", priv->consider_statfs, bool, err); + + this->local_pool = mem_pool_new (quota_local_t, 64); + if (!this->local_pool) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "failed to create local_t's memory pool"); + goto err; + } + ret = 0; err: return ret; } +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); + + LOCK (&priv->lock); + { + list_splice_init (&priv->limit_head, &head); + } + UNLOCK (&priv->lock); - GF_FREE (limit); + ret = quota_parse_limits (priv, this, options, &head); + if (ret == -1) { + gf_log ("quota", GF_LOG_WARNING, + "quota reconfigure failed, " + "new changes will not take effect"); + goto out; } - ret = quota_parse_options (priv, this, options); + LOCK (&priv->lock); + { + top = ((glusterfs_ctx_t *)this->ctx)->active->top; + GF_ASSERT (top); - if (ret == -1) - GF_ASSERT (0); + list_for_each_entry (limit, &priv->limit_head, limit_list) { + __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); + GF_OPTION_RECONF ("deem-statfs", priv->consider_statfs, options, bool, + out); + + ret = 0; +out: return ret; } @@ -2757,25 +3449,33 @@ fini (xlator_t *this) struct xlator_fops fops = { - .lookup = quota_lookup, - .writev = quota_writev, - .create = quota_create, - .mkdir = quota_mkdir, - .truncate = quota_truncate, - .ftruncate = quota_ftruncate, - .unlink = quota_unlink, - .symlink = quota_symlink, - .link = quota_link, - .rename = quota_rename, - .getxattr = quota_getxattr, - .fgetxattr = quota_fgetxattr, - .stat = quota_stat, - .fstat = quota_fstat, - .readlink = quota_readlink, - .readv = quota_readv, - .fsync = quota_fsync, - .setattr = quota_setattr, - .fsetattr = quota_fsetattr, + .statfs = quota_statfs, + .lookup = quota_lookup, + .writev = quota_writev, + .create = quota_create, + .mkdir = quota_mkdir, + .truncate = quota_truncate, + .ftruncate = quota_ftruncate, + .unlink = quota_unlink, + .symlink = quota_symlink, + .link = quota_link, + .rename = quota_rename, + .getxattr = quota_getxattr, + .fgetxattr = quota_fgetxattr, + .stat = quota_stat, + .fstat = quota_fstat, + .readlink = quota_readlink, + .readv = quota_readv, + .fsync = quota_fsync, + .setattr = quota_setattr, + .fsetattr = quota_fsetattr, + .mknod = quota_mknod, + .setxattr = quota_setxattr, + .fsetxattr = quota_fsetxattr, + .removexattr = quota_removexattr, + .fremovexattr = quota_fremovexattr, + .readdirp = quota_readdirp, + .fallocate = quota_fallocate, }; struct xlator_cbks cbks = { @@ -2784,7 +3484,20 @@ struct xlator_cbks cbks = { struct volume_options options[] = { {.key = {"limit-set"}}, - {.key = {"timeout"} + {.key = {"timeout"}, + .type = GF_OPTION_TYPE_SIZET, + .min = 0, + .max = 60, + .default_value = "0", + .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}} }; |
