diff options
| -rw-r--r-- | tests/bugs/replicate/bug-1292379.t | 57 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 51 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.h | 2 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 3 | 
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 5a8f180b9f4..7f5cd5237ae 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -903,12 +903,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) { @@ -921,6 +927,41 @@ posix_create_link_if_gfid_exists (xlator_t *this, uuid_t gfid,          ret = sys_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 3dc8b9209f3..9af6a7a5442 100644 --- a/xlators/storage/posix/src/posix-handle.h +++ b/xlators/storage/posix/src/posix-handle.h @@ -281,7 +281,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 7bdd69d3a0d..0b5a5097afb 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -1181,7 +1181,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;  | 
