diff options
author | Raghavendra G <rgowdapp@redhat.com> | 2014-06-08 00:46:29 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-09-18 10:15:55 -0700 |
commit | 1e1b709a4b438dfa768fd4c645e081ede06e7e14 (patch) | |
tree | c0d03c6cd185873ae66ce62a7a492a97d2448659 | |
parent | 331e9e2051addfcc394c933a85046f450961e1af (diff) |
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 <rgowdapp@redhat.com>
Reviewed-on: http://review.gluster.org/8008
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Tested-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r-- | xlators/storage/posix/src/posix.c | 27 |
1 files changed, 26 insertions, 1 deletions
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 + : "<NULL>"); + } + } + op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent); if (op_ret == -1) { op_errno = errno; |