summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra G <rgowdapp@redhat.com>2014-09-19 10:07:53 -0400
committerVijay Bellur <vbellur@redhat.com>2014-09-19 09:46:11 -0700
commita2e0602c0910ee448b4e8badeb00eed2a78ea452 (patch)
tree16e32f195c65aadb0e3cefc853ab34167f611579
parentacd7ebf257453f46be42c8592e2fd784c676a114 (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: 1144485 Signed-off-by: Raghavendra G <rgowdapp@redhat.com> Reviewed-on-master: 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> Reviewed-on: http://review.gluster.org/8783 Tested-by: Gluster Build System <jenkins@build.gluster.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 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
+ : "<NULL>");
+ }
+ }
+
op_ret = posix_pstat (this, loc->pargfid, par_path, &preparent);
if (op_ret == -1) {
op_errno = errno;