summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra G <rgowdapp@redhat.com>2014-06-08 00:46:29 +0530
committerVijay Bellur <vbellur@redhat.com>2014-09-18 10:15:55 -0700
commit1e1b709a4b438dfa768fd4c645e081ede06e7e14 (patch)
treec0d03c6cd185873ae66ce62a7a492a97d2448659
parent331e9e2051addfcc394c933a85046f450961e1af (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.c27
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;