summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/bugs/distribute/bug-1368012.t50
-rw-r--r--xlators/cluster/dht/src/dht-common.c32
-rw-r--r--xlators/cluster/dht/src/dht-selfheal.c16
3 files changed, 93 insertions, 5 deletions
diff --git a/tests/bugs/distribute/bug-1368012.t b/tests/bugs/distribute/bug-1368012.t
new file mode 100644
index 00000000000..f89314b1f2e
--- /dev/null
+++ b/tests/bugs/distribute/bug-1368012.t
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+
+cleanup;
+
+function get_permission {
+ stat -c "%A" $1
+}
+
+## Start glusterd
+TEST glusterd;
+TEST pidof glusterd;
+TEST $CLI volume info;
+
+## Lets create volume
+TEST $CLI volume create $V0 $H0:/${V0}{1,2};
+
+## Verify volume is created
+EXPECT "$V0" volinfo_field $V0 'Volume Name';
+EXPECT 'Created' volinfo_field $V0 'Status';
+## Start volume and verify
+TEST $CLI volume start $V0;
+TEST $CLI volume set $V0 performance.stat-prefetch off
+EXPECT 'Started' volinfo_field $V0 'Status';
+TEST glusterfs -s $H0 --volfile-id=$V0 $M0
+
+##Test case: Add-brick
+#------------------------------------------------------------
+#change permission of both root
+TEST chmod 444 $M0
+
+#store permission for comparision
+TEST permission_root=`stat -c "%A" $M0`
+TEST echo $permission_root
+#Add-brick
+TEST $CLI volume add-brick $V0 $H0:/${V0}3
+
+#Allow one lookup to happen
+TEST pushd $M0
+TEST ls
+#Generate another lookup
+echo 3 > /proc/sys/vm/drop_caches
+TEST ls
+#check root permission
+EXPECT_WITHIN "5" $permission_root get_permission $M0
+#check permission on the new-brick
+EXPECT $permission_root get_permission /${V0}3
+cleanup
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index 0131bb519c9..c4326fd075f 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -736,6 +736,27 @@ out:
return ret;
}
+int static
+is_permission_different (ia_prot_t *prot1, ia_prot_t *prot2)
+{
+ if ((prot1->owner.read != prot2->owner.read) ||
+ (prot1->owner.write != prot2->owner.write) ||
+ (prot1->owner.exec != prot2->owner.exec) ||
+ (prot1->group.read != prot2->group.read) ||
+ (prot1->group.write != prot2->group.write) ||
+ (prot1->group.exec != prot2->group.exec) ||
+ (prot1->other.read != prot2->other.read) ||
+ (prot1->other.write != prot2->other.write) ||
+ (prot1->other.exec != prot2->other.exec) ||
+ (prot1->suid != prot2->suid) ||
+ (prot1->sgid != prot2->sgid) ||
+ (prot1->sticky != prot2->sticky)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
int
dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno,
@@ -857,14 +878,21 @@ dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
local->stbuf.ia_ctime_nsec,
stbuf->ia_ctime,
stbuf->ia_ctime_nsec)) {
+ /* Choose source */
local->prebuf.ia_gid = stbuf->ia_gid;
local->prebuf.ia_uid = stbuf->ia_uid;
+
+ if (__is_root_gfid (stbuf->ia_gfid))
+ local->prebuf.ia_prot = stbuf->ia_prot;
}
}
if (local->stbuf.ia_type != IA_INVAL)
{
if ((local->stbuf.ia_gid != stbuf->ia_gid) ||
- (local->stbuf.ia_uid != stbuf->ia_uid)) {
+ (local->stbuf.ia_uid != stbuf->ia_uid) ||
+ (__is_root_gfid (stbuf->ia_gfid) &&
+ is_permission_different (&local->stbuf.ia_prot,
+ &stbuf->ia_prot))) {
local->need_selfheal = 1;
}
}
@@ -942,6 +970,8 @@ out:
gf_uuid_copy (local->gfid, local->stbuf.ia_gfid);
local->stbuf.ia_gid = local->prebuf.ia_gid;
local->stbuf.ia_uid = local->prebuf.ia_uid;
+ if (__is_root_gfid(local->stbuf.ia_gfid))
+ local->stbuf.ia_prot = local->prebuf.ia_prot;
copy = create_frame (this, this->ctx->pool);
if (copy) {
copy_local = dht_local_init (copy, &local->loc,
diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c
index bd4c236ffcd..331878b3608 100644
--- a/xlators/cluster/dht/src/dht-selfheal.c
+++ b/xlators/cluster/dht/src/dht-selfheal.c
@@ -2253,11 +2253,19 @@ dht_dir_attr_heal (void *data)
for (i = 0; i < call_cnt; i++) {
subvol = conf->subvolumes[i];
- if (!subvol || (subvol == dht_first_up_subvol (this)))
+ if (!subvol)
continue;
- ret = syncop_setattr (subvol, &local->loc, &local->stbuf,
- (GF_SET_ATTR_UID | GF_SET_ATTR_GID),
- NULL, NULL, NULL, NULL);
+
+ if (__is_root_gfid (local->stbuf.ia_gfid)) {
+ ret = syncop_setattr (subvol, &local->loc, &local->stbuf,
+ (GF_SET_ATTR_UID | GF_SET_ATTR_GID | GF_SET_ATTR_MODE),
+ NULL, NULL, NULL, NULL);
+ } else {
+ ret = syncop_setattr (subvol, &local->loc, &local->stbuf,
+ (GF_SET_ATTR_UID | GF_SET_ATTR_GID),
+ NULL, NULL, NULL, NULL);
+ }
+
if (ret) {
gf_uuid_unparse(local->loc.gfid, gfid);