summaryrefslogtreecommitdiffstats
path: root/xlators/storage/posix/src
diff options
context:
space:
mode:
authorRavishankar N <ravishankar@redhat.com>2017-07-31 23:38:20 +0530
committerJeff Darcy <jeff@pl.atyp.us>2017-08-04 15:54:01 +0000
commit42c057a6d1a03dd2825a278393acb15d52220c8d (patch)
treee626ed22547a454b142b2396e59c5008f7c06525 /xlators/storage/posix/src
parent6d1068ddb35be19df36210c9fcaa7ce97e2a376a (diff)
posix: add sanity checks for removing the gfid symlink for directories
...during mkdir and rmdir. Otherwise, during entry self-heal, the directory could be left out without a .glusterfs symlink causing fops like opendir, readdir to fail. The only chance the missing symlink will be created is when a fresh lookup comes on it. Change-Id: I2e1cf1bce8962ea80187edd8f6d73e0a09cf9f8e BUG: 1477169 Signed-off-by: Ravishankar N <ravishankar@redhat.com> Reviewed-on: https://review.gluster.org/17945 Smoke: Gluster Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
Diffstat (limited to 'xlators/storage/posix/src')
-rw-r--r--xlators/storage/posix/src/posix.c70
1 files changed, 56 insertions, 14 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index a04d830dd69..7a53bc60c6b 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -109,6 +109,37 @@ static char *disallow_removexattrs[] = {
NULL
};
+gf_boolean_t
+posix_symlinks_match (xlator_t *this, loc_t *loc, uuid_t gfid)
+{
+ struct posix_private *priv = NULL;
+ char linkname_actual[PATH_MAX] = {0,};
+ char linkname_expected[PATH_MAX] = {0};
+ char *dir_handle = NULL;
+ size_t len = 0;
+ size_t handle_size = 0;
+ gf_boolean_t ret = _gf_false;
+
+ priv = this->private;
+ handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length);
+ dir_handle = alloca0 (handle_size);
+
+ snprintf (linkname_expected, handle_size, "../../%02x/%02x/%s/%s",
+ loc->pargfid[0], loc->pargfid[1], uuid_utoa (loc->pargfid),
+ loc->name);
+
+ MAKE_HANDLE_GFID_PATH (dir_handle, this, gfid, NULL);
+ len = sys_readlink (dir_handle, linkname_actual, PATH_MAX);
+ if (len < 0)
+ goto out;
+ linkname_actual[len] = '\0';
+
+ if (!strncmp (linkname_actual, linkname_expected, handle_size))
+ ret = _gf_true;
+
+out:
+ return ret;
+}
dict_t*
posix_dict_set_nlink (dict_t *req, dict_t *res, int32_t nlink)
@@ -1592,19 +1623,29 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,
posix_handle_path (this, uuid_req, NULL,
gfid_path, size);
- gf_msg (this->name, GF_LOG_WARNING, 0,
- P_MSG_DIR_OF_SAME_ID, "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>");
-
- gf_event (EVENT_POSIX_SAME_GFID, "gfid=%s;path=%s;"
- "newpath=%s;brick=%s:%s",
- uuid_utoa (uuid_req),
- gfid_path ? gfid_path : "<NULL>", loc->path,
- priv->hostname, priv->base_path);
+ if (frame->root->pid != GF_CLIENT_PID_SELF_HEALD) {
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ P_MSG_DIR_OF_SAME_ID, "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>");
+
+ gf_event (EVENT_POSIX_SAME_GFID, "gfid=%s;"
+ "path=%s;newpath=%s;brick=%s:%s",
+ uuid_utoa (uuid_req),
+ gfid_path ? gfid_path : "<NULL>",
+ loc->path, priv->hostname,
+ priv->base_path);
+ }
+ if (!posix_symlinks_match (this, loc, uuid_req))
+ /* For afr selfheal of dir renames, we need to
+ * remove the old symlink in order for
+ * posix_gfid_set to set the symlink to the
+ * new dir.*/
+ posix_handle_unset (this, stbuf.ia_gfid, NULL);
}
} else if (!uuid_req && frame->root->pid != GF_SERVER_PID_TRASH) {
op_ret = -1;
@@ -2295,7 +2336,8 @@ posix_rmdir (call_frame_t *frame, xlator_t *this,
op_errno = errno;
if (op_ret == 0) {
- posix_handle_unset (this, stbuf.ia_gfid, NULL);
+ if (posix_symlinks_match (this, loc, stbuf.ia_gfid))
+ posix_handle_unset (this, stbuf.ia_gfid, NULL);
}
if (op_errno == EEXIST)