summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPranith Kumar K <pkarampu@redhat.com>2014-07-03 06:50:56 +0530
committerVijay Bellur <vbellur@redhat.com>2014-07-06 21:01:20 -0700
commit8202705f98d139ef7d691587b9f68cf1db2e397a (patch)
treed66c310cab14911b2a887aca8d0d90fd20455e8c
parent83c09b75a8fbc3a46fc0e76f805e061e949678f1 (diff)
features/gfid-access: Fix entry operations
Problem: When more than one aux-mounts are performing rmdir .gfid/<pargfid>/dir simultaneously, then sometimes a hang is observed. In gfid-access xlator When virtual parent/inode are replaced with real parent/inode in loc, virtual pargfid/gfid are not replaced with real pargfid/gfid respectively. Afr is using parent_loc->gfids to order the entry locks. But parent_loc->gfid contains random/virtual gfid generated by gfid-access xlator. Entrylk in client xlator is using loc->inod->gfid for sending entrylk which has 'real' gfid. Because the ordering is happening based on random gfids, One mount orders the locks as (L1, L2) where as the other orders them as (L2, L1) leading to a dead-lock thus a hang. Fix: Replace virtual pargfid/gfid with real pargfid/gfid when virtual-inodes are replaced with real-inodes in loc. BUG: 1114501 Change-Id: Ie94e816122ef9e7aad51605adbf49291de60827e Signed-off-by: Pranith Kumar K <pkarampu@redhat.com> Reviewed-on: http://review.gluster.org/8204 Reviewed-by: Kotresh HR <khiremat@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com> Tested-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--tests/basic/gfid-access.t18
-rw-r--r--xlators/features/gfid-access/src/gfid-access.c13
2 files changed, 24 insertions, 7 deletions
diff --git a/tests/basic/gfid-access.t b/tests/basic/gfid-access.t
index 24477acba5c..00e14235fee 100644
--- a/tests/basic/gfid-access.t
+++ b/tests/basic/gfid-access.t
@@ -36,6 +36,24 @@ TEST chmod 0777 $M0/.gfid/$a_gfid_str
EXPECT "777" stat -c "%a" $M0/a
EXPECT "777" stat -c "%a" $M0/.gfid/$a_gfid_str
+#Entry operations on directory
+#Test that virtual directories are not allowed to be deleted.
+TEST ! mkdir $M0/.gfid
+TEST ! rmdir $M0/.gfid
+TEST ! touch $M0/.gfid
+TEST ! rm -f $M0/.gfid
+TEST ! mv $M0/.gfid $M0/dont-rename
+TEST ! ln -s $M0/symlink $M0/.gfid
+TEST ! ln $M0/.gfid $M0/hlink
+TEST ! mknod $M0/.gfid b 0 0
+
+#Test that first level directory/file creations inside .gfid are not allowed.
+TEST ! mkdir $M0/.gfid/a
+TEST ! touch $M0/.gfid/a
+TEST ! mv /etc/passwd $M0/.gfid
+TEST ! mv $M0/a $M0/.gfid
+TEST ! mknod $M0/.gfid/b b 0 0
+
#Operations on File
TEST setfattr -n trusted.abc -v abc $M0/b
EXPECT "abc" echo $(getfattr -n trusted.abc $M0/b)
diff --git a/xlators/features/gfid-access/src/gfid-access.c b/xlators/features/gfid-access/src/gfid-access.c
index 8b699ffc9d4..52c137c342f 100644
--- a/xlators/features/gfid-access/src/gfid-access.c
+++ b/xlators/features/gfid-access/src/gfid-access.c
@@ -30,6 +30,9 @@ ga_valid_inode_loc_copy (loc_t *dst, loc_t *src, xlator_t *this)
if (ret < 0)
goto out;
+ /*
+ * Change ALL virtual inodes with real-inodes in loc
+ */
if (dst->parent) {
ret = inode_ctx_get (dst->parent, this, &value);
if (ret < 0) {
@@ -38,14 +41,9 @@ ga_valid_inode_loc_copy (loc_t *dst, loc_t *src, xlator_t *this)
}
inode_unref (dst->parent);
dst->parent = inode_ref ((inode_t*)value);
- /* if parent is virtual, no need to handle */
- /* loc->inode */
- goto out;
+ uuid_copy (dst->pargfid, dst->parent->gfid);
}
- /* if its an inode operation, on the virtual */
- /* directory inode itself, we need to handle */
- /* it properly */
if (dst->inode) {
ret = inode_ctx_get (dst->inode, this, &value);
if (ret < 0) {
@@ -54,9 +52,10 @@ ga_valid_inode_loc_copy (loc_t *dst, loc_t *src, xlator_t *this)
}
inode_unref (dst->inode);
dst->inode = inode_ref ((inode_t*)value);
- goto out;
+ uuid_copy (dst->gfid, dst->inode->gfid);
}
out:
+
return ret;
}