summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/bugs/replicate/bug-1292379.t57
-rw-r--r--xlators/storage/posix/src/posix-handle.c51
-rw-r--r--xlators/storage/posix/src/posix-handle.h2
-rw-r--r--xlators/storage/posix/src/posix.c3
4 files changed, 106 insertions, 7 deletions
diff --git a/tests/bugs/replicate/bug-1292379.t b/tests/bugs/replicate/bug-1292379.t
new file mode 100644
index 00000000000..f0865020d54
--- /dev/null
+++ b/tests/bugs/replicate/bug-1292379.t
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+. $(dirname $0)/../../afr.rc
+. $(dirname $0)/../../fileio.rc
+
+cleanup
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume info
+
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
+TEST $CLI volume start $V0
+EXPECT 'Started' volinfo_field $V0 'Status'
+TEST $CLI volume set $V0 cluster.self-heal-daemon off
+TEST $CLI volume set $V0 cluster.entry-self-heal off
+TEST $CLI volume set $V0 cluster.data-self-heal off
+TEST $CLI volume set $V0 cluster.metadata-self-heal off
+TEST $CLI volume set $V0 cluster.eager-lock off
+
+TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0
+
+TEST wfd=`fd_available`
+TEST fd_open $wfd "w" $M0/a
+
+TEST fd_write $wfd "abcd"
+
+# Kill brick-0
+TEST kill_brick $V0 $H0 $B0/${V0}0
+
+# While brick-0 is down, rename 'a' to 'b'
+TEST mv $M0/a $M0/b
+
+TEST fd_write $wfd "lmn"
+
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+TEST fd_write $wfd "pqrs"
+TEST $CLI volume set $V0 self-heal-daemon on
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
+
+TEST $CLI volume heal $V0
+
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
+
+TEST fd_write $wfd "xyz"
+TEST fd_close $wfd
+
+md5sum_b0=$(md5sum $B0/${V0}0/b | awk '{print $1}')
+
+EXPECT "$md5sum_b0" echo `md5sum $B0/${V0}1/b | awk '{print $1}'`
+
+TEST umount $M0
+cleanup
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c
index 4aee2c1104c..aad7db61430 100644
--- a/xlators/storage/posix/src/posix-handle.c
+++ b/xlators/storage/posix/src/posix-handle.c
@@ -898,12 +898,18 @@ posix_handle_unset (xlator_t *this, uuid_t gfid, const char *basename)
int
-posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid,
- char *real_path)
+posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid, char *real_path,
+ inode_table_t *itable)
{
- int ret = -1;
- struct stat stbuf = {0,};
- char *newpath = NULL;
+ int ret = -1;
+ char *newpath = NULL;
+ char *unlink_path = NULL;
+ uint64_t ctx_int = 0;
+ inode_t *inode = NULL;
+ struct stat stbuf = {0,};
+ struct posix_private *priv = NULL;
+
+ priv = this->private;
MAKE_HANDLE_PATH (newpath, this, gfid, NULL);
if (!newpath) {
@@ -916,6 +922,41 @@ posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid,
ret = lstat (newpath, &stbuf);
if (!ret) {
ret = sys_link (newpath, real_path);
+ } else {
+ inode = inode_find (itable, gfid);
+ if (!inode)
+ return -1;
+
+ LOCK (&inode->lock);
+ {
+ ret = __inode_ctx_get0 (inode, this, &ctx_int);
+ if (ret)
+ goto unlock;
+
+ if (ctx_int != GF_UNLINK_TRUE)
+ goto unlock;
+
+ POSIX_GET_FILE_UNLINK_PATH (priv->base_path, gfid,
+ unlink_path);
+ ret = sys_link (unlink_path, real_path);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, errno,
+ P_MSG_HANDLE_CREATE, "Failed to link "
+ "%s with %s", real_path, unlink_path);
+ goto unlock;
+ }
+ ret = sys_rename (unlink_path, newpath);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, errno,
+ P_MSG_HANDLE_CREATE, "Failed to link "
+ "%s with %s", real_path, unlink_path);
+ goto unlock;
+ }
+ ctx_int = GF_UNLINK_FALSE;
+ ret = __inode_ctx_set0 (inode, this, &ctx_int);
+ }
+unlock:
+ UNLOCK (&inode->lock);
}
return ret;
diff --git a/xlators/storage/posix/src/posix-handle.h b/xlators/storage/posix/src/posix-handle.h
index 76ef8547e9e..b41190815ef 100644
--- a/xlators/storage/posix/src/posix-handle.h
+++ b/xlators/storage/posix/src/posix-handle.h
@@ -286,7 +286,7 @@ int posix_handle_mkdir_hashes (xlator_t *this, const char *newpath);
int posix_handle_init (xlator_t *this);
int posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid,
- char *real_path);
+ char *real_path, inode_table_t *itable);
int
posix_handle_trash_init (xlator_t *this);
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index d57d53d5fca..fe0607f09cd 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -1196,7 +1196,8 @@ posix_mknod (call_frame_t *frame, xlator_t *this,
goto real_op;
}
op_ret = posix_create_link_if_gfid_exists (this, uuid_req,
- real_path);
+ real_path,
+ loc->inode->table);
if (!op_ret) {
linked = _gf_true;
goto post_op;