From 1e1b709a4b438dfa768fd4c645e081ede06e7e14 Mon Sep 17 00:00:00 2001 From: Raghavendra G Date: Sun, 8 Jun 2014 00:46:29 +0530 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: 1105082 Signed-off-by: Raghavendra G Reviewed-on: http://review.gluster.org/8008 Reviewed-by: Pranith Kumar Karampuri Reviewed-by: Vijay Bellur Tested-by: Vijay Bellur --- xlators/storage/posix/src/posix.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'xlators/storage/posix/src') diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index e8d6a8bd66a..49dbaadfd03 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