summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra G <rgowdapp@redhat.com>2013-11-09 13:44:18 +0530
committerVijay Bellur <vbellur@redhat.com>2014-01-25 08:53:01 -0800
commita10100a4b8501d15c83b416b932d8d786ea550fb (patch)
tree2901e2ca6560b3b8d212d2827c63f76493efdf3d
parent49eb5ea29cf8d6eab0c5f60d70fe8d6a0113b61e (diff)
features/quota: maintain correct link_count in ancestry building
codepath. Ancestry building codepath can be executed simultaneously when a file has hardlinks. So, following fixes are needed: * modify local->link_count under locks in ancestry building codepath. * before invoking check_limit on newly constructed parents, link_count should not be set, but instead incremented by as many number of new invocations of check_limit. * decrementing link_count and the check whether the count has hit zero to resume the waiting call_stub should be atomic. Change-Id: I6f52e50547362a5ded6bd9f085570223aea372d1 BUG: 969461 Signed-off-by: Raghavendra G <rgowdapp@redhat.com> Reviewed-on: http://review.gluster.org/6491 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--xlators/features/quota/src/quota.c121
1 files changed, 68 insertions, 53 deletions
diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c
index 0af514cef0c..e1471258b49 100644
--- a/xlators/features/quota/src/quota.c
+++ b/xlators/features/quota/src/quota.c
@@ -245,7 +245,7 @@ out:
}
inline void
-quota_resume_fop_if_validation_done (quota_local_t *local)
+quota_link_count_decrement (quota_local_t *local)
{
call_stub_t *stub = NULL;
int link_count = -1;
@@ -255,7 +255,7 @@ quota_resume_fop_if_validation_done (quota_local_t *local)
LOCK (&local->lock);
{
- link_count = local->link_count;
+ link_count = --local->link_count;
if (link_count == 0) {
stub = local->stub;
local->stub = NULL;
@@ -283,13 +283,11 @@ quota_handle_validate_error (quota_local_t *local, int32_t op_ret,
local->op_ret = op_ret;
local->op_errno = op_errno;
}
-
- /* we abort checking limits on this path to root */
- local->link_count--;
}
UNLOCK (&local->lock);
- quota_resume_fop_if_validation_done (local);
+ /* we abort checking limits on this path to root */
+ quota_link_count_decrement (local);
out:
return;
}
@@ -795,12 +793,8 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this,
*/
if (0 > frame->root->pid) {
ret = 0;
- LOCK (&local->lock);
- {
- --local->link_count;
- }
- UNLOCK (&local->lock);
- goto resume;
+ quota_link_count_decrement (local);
+ goto done;
}
priv = this->private;
@@ -883,12 +877,7 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this,
}
if (__is_root_gfid (_inode->gfid)) {
- LOCK (&local->lock);
- {
- --local->link_count;
- }
- UNLOCK (&local->lock);
-
+ quota_link_count_decrement (local);
break;
}
@@ -929,8 +918,7 @@ quota_check_limit (call_frame_t *frame, inode_t *inode, xlator_t *this,
_inode = NULL;
}
-resume:
- quota_resume_fop_if_validation_done (local);
+done:
return 0;
err:
@@ -1303,13 +1291,18 @@ quota_writev (call_frame_t *frame, xlator_t *this, fd_t *fd,
UNLOCK (&ctx->lock);
}
- local->delta = size;
-
- local->link_count = parents;
- local->stub = stub;
+ LOCK (&local->lock);
+ {
+ local->delta = size;
+ local->link_count = (parents != 0) ? parents : 1;
+ local->stub = stub;
+ }
+ UNLOCK (&local->lock);
if (parents == 0) {
- local->link_count = 1;
+ /* nameless lookup on this inode, allow quota to reconstruct
+ * ancestry as part of check_limit.
+ */
quota_check_limit (frame, fd->inode, this, NULL, NULL);
} else {
list_for_each_entry_safe (dentry, tmp, &head, next) {
@@ -1412,9 +1405,13 @@ quota_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
goto err;
}
- local->stub = stub;
- local->delta = 0;
- local->link_count = 1;
+ LOCK (&local->lock);
+ {
+ local->stub = stub;
+ local->delta = 0;
+ local->link_count = 1;
+ }
+ UNLOCK (&local->lock);
quota_check_limit (frame, loc->parent, this, NULL, NULL);
return 0;
@@ -1557,9 +1554,13 @@ quota_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
goto err;
}
- local->link_count = 1;
- local->stub = stub;
- local->delta = 0;
+ LOCK (&local->lock);
+ {
+ local->link_count = 1;
+ local->stub = stub;
+ local->delta = 0;
+ }
+ UNLOCK (&local->lock);
quota_check_limit (frame, loc->parent, this, NULL, NULL);
return 0;
@@ -1829,9 +1830,13 @@ quota_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
goto err;
}
- local->link_count = 1;
- local->stub = stub;
- local->delta = (ctx != NULL) ? ctx->buf.ia_blocks * 512 : 0;
+ LOCK (&local->lock);
+ {
+ local->link_count = 1;
+ local->stub = stub;
+ local->delta = (ctx != NULL) ? ctx->buf.ia_blocks * 512 : 0;
+ }
+ UNLOCK (&local->lock);
quota_check_limit (frame, newloc->parent, this, NULL, NULL);
return 0;
@@ -2072,8 +2077,12 @@ quota_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc,
goto err;
}
- local->link_count = 1;
- local->stub = stub;
+ LOCK (&local->lock);
+ {
+ local->link_count = 1;
+ local->stub = stub;
+ }
+ UNLOCK (&local->lock);
if (QUOTA_REG_OR_LNK_FILE (oldloc->inode->ia_type)) {
ret = quota_inode_ctx_get (oldloc->inode, this, &ctx, 0);
@@ -2248,9 +2257,13 @@ quota_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath,
goto err;
}
- local->stub = stub;
- local->delta = strlen (linkpath);
- local->link_count = 1;
+ LOCK (&local->lock);
+ {
+ local->stub = stub;
+ local->delta = strlen (linkpath);
+ local->link_count = 1;
+ }
+ UNLOCK (&local->lock);
quota_check_limit (frame, loc->parent, this, NULL, NULL);
return 0;
@@ -3207,9 +3220,13 @@ quota_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
goto err;
}
- local->link_count = 1;
- local->stub = stub;
- local->delta = 0;
+ LOCK (&local->lock);
+ {
+ local->link_count = 1;
+ local->stub = stub;
+ local->delta = 0;
+ }
+ UNLOCK (&local->lock);
quota_check_limit (frame, loc->parent, this, NULL, NULL);
return 0;
@@ -3655,9 +3672,7 @@ quota_statfs_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
UNLOCK (&ctx->lock);
resume:
- --local->link_count;
-
- quota_resume_fop_if_validation_done (local);
+ quota_link_count_decrement (local);
return 0;
}
@@ -3682,26 +3697,26 @@ quota_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
}
frame->local = local;
- local->inode = inode_ref (loc->inode);
- local->link_count = 1;
-
stub = fop_statfs_stub (frame, quota_statfs_helper, loc, xdata);
if (!stub) {
op_errno = ENOMEM;
goto err;
}
- local->stub = stub;
+ LOCK (&local->lock);
+ {
+ local->inode = inode_ref (loc->inode);
+ local->link_count = 1;
+ local->stub = stub;
+ }
+ UNLOCK (&local->lock);
ret = quota_validate (frame, local->inode, this,
quota_statfs_validate_cbk);
if (0 > ret) {
- op_errno = -ret;
- --local->link_count;
+ quota_handle_validate_error (local, -1, -ret);
}
- quota_resume_fop_if_validation_done (local);
-
return 0;
}