From a2e0602c0910ee448b4e8badeb00eed2a78ea452 Mon Sep 17 00:00:00 2001 From: Raghavendra G Date: Fri, 19 Sep 2014 10:07:53 -0400 Subject: storage/posix: Log when mkdir is on an existing gfid but non-existent path. consider following steps on a distribute volume 1. rename (src, dst) on hashed subvolume 2. snapshot taken 3. restore snapshots and do stat on src and dst Now, we end up with two directories src and dst having same gfid, because of distribute creating directories on non-existent subvolumes as part of directory healing. This can happen even with race between rename and directory healing in dht-lookup. This can lead to undefined behaviour while accessing any of both directories. Hence, we are logging paths of both directories, so that a sysadmin can take some corrective action when (s)he sees this log. One of the corrective action can be to copy contents of both directories from backend into a new directory and delete both directories. Since effort involved to fix this issue is non-trivial, giving this workaround till we come up with a fix. Change-Id: I38f4520e6787ee33180a9cd1bf2f36f46daea1ea BUG: 1144485 Signed-off-by: Raghavendra G Reviewed-on-master: http://review.gluster.org/8008 Reviewed-by: Pranith Kumar Karampuri Reviewed-by: Vijay Bellur Tested-by: Vijay Bellur Reviewed-on: http://review.gluster.org/8783 Tested-by: Gluster Build System --- xlators/storage/posix/src/posix.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 73915db9daa..2b979cfc27f 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -1221,7 +1221,7 @@ posix_mkdir (call_frame_t *frame, xlator_t *this, { int32_t op_ret = -1; int32_t op_errno = 0; - char *real_path = NULL; + char *real_path = NULL, *gfid_path = NULL; char *par_path = NULL; struct iatt stbuf = {0, }; struct posix_private *priv = NULL; @@ -1229,6 +1229,8 @@ posix_mkdir (call_frame_t *frame, xlator_t *this, struct iatt preparent = {0,}; struct iatt postparent = {0,}; gf_boolean_t entry_created = _gf_false, gfid_set = _gf_false; + void *uuid_req = NULL; + ssize_t size = 0; DECLARE_OLD_FS_ID_VAR; @@ -1259,6 +1261,29 @@ posix_mkdir (call_frame_t *frame, xlator_t *this, SET_FS_ID (frame->root->uid, gid); + op_ret = dict_get_ptr (xdata, "gfid-req", &uuid_req); + if (uuid_req && !uuid_is_null (uuid_req)) { + op_ret = posix_istat (this, uuid_req, NULL, &stbuf); + if ((op_ret == 0) && IA_ISDIR (stbuf.ia_type)) { + size = posix_handle_path (this, uuid_req, NULL, NULL, + 0); + if (size > 0) + gfid_path = alloca (size); + + if (gfid_path) + posix_handle_path (this, uuid_req, NULL, + gfid_path, size); + + gf_log (this->name, GF_LOG_WARNING, + "mkdir (%s): gfid (%s) is already associated " + "with directory (%s). Hence, both directories " + "will share same gfid and this can lead to " + "inconsistencies.", loc->path, + uuid_utoa (uuid_req), gfid_path ? gfid_path + : ""); + } + } + op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); if (op_ret == -1) { op_errno = errno; -- cgit