summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrutika Dhananjay <kdhananj@redhat.com>2018-10-17 14:26:14 +0530
committerKrutika Dhananjay <kdhananj@redhat.com>2018-10-22 11:16:38 +0530
commitecdc33ada79f155f2bde2860b29872526939e22b (patch)
tree38fdc5a56dd8b3a79e5ba27f53a0a9005d64bca3
parentab12861f40a767b9b87c98a7b9ccee3afcc30185 (diff)
storage/posix: Do not fail entry creation fops if gfid handle already exists
Backport of: > Change-Id: I84a5e54d214b6c47ed85671a880bb1c767a29f4d > Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com> > (cherry picked from commit 15c9976) > BUG: 1638453 PROBLEM: tests/bugs/shard/bug-1251824.t fails occasionally with EIO due to gfid mismatch across replicas on the same shard when dd is executed. CAUSE: Turns out this is due to a race between posix_mknod() and posix_lookup(). posix mknod does 3 operations, among other things: 1. creation of the entry itself under its parent directory 2. setting the gfid xattr on the file, and 3. creating the gfid link under .glusterfs. Consider a case where the thread doing posix_mknod() (initiated by shard) has executed steps 1 and 2 and is on its way to executing 3. And a parallel LOOKUP from another thread on noting that loc->inode->gfid is NULL, tries to perform gfid_heal where it attempts to create the gfid link under .glusterfs and succeeds. As a result, posix_gfid_set() through MKNOD (step 3) fails with EEXIST. In the older code, MKNOD under such conditions was NOT being treated as a failure. But commit e37ee6d changes this behavior by failing MKNOD, causing the entry creation to be undone in posix_mknod() (it's another matter that the stale gfid handle gets left behind if lookup has gone ahead and gfid-healed it). All of this happens on only one replica while on the other MKNOD succeeds. Now if a parallel write causes shard translator to send another MKNOD of the same shard (shortly after AFR releases entrylk from the first MKNOD), the file is created on the other replica too, although with a new gfid (since "gfid-req" that is passed now is a new UUID. This leads to a gfid-mismatch across the replicas. FIX: The solution is to not fail MKNOD (or any other entry fop for that matter that does posix_gfid_set()) if the .glusterfs link creation fails with EEXIST. Change-Id: I84a5e54d214b6c47ed85671a880bb1c767a29f4d fixes: bz#1641429 Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
-rw-r--r--xlators/storage/posix/src/posix-handle.c20
-rw-r--r--xlators/storage/posix/src/posix-helpers.c2
2 files changed, 16 insertions, 6 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c
index bc34e3e5dba..5c50d413640 100644
--- a/xlators/storage/posix/src/posix-handle.c
+++ b/xlators/storage/posix/src/posix-handle.c
@@ -741,6 +741,7 @@ posix_handle_hard(xlator_t *this, const char *oldpath, uuid_t gfid,
char *newpath = NULL;
struct stat newbuf;
int ret = -1;
+ gf_boolean_t link_exists = _gf_false;
MAKE_HANDLE_ABSPATH(newpath, this, gfid);
@@ -762,11 +763,15 @@ posix_handle_hard(xlator_t *this, const char *oldpath, uuid_t gfid,
ret = sys_link(oldpath, newpath);
if (ret) {
- gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE,
- "link %s -> %s"
- "failed ",
- oldpath, newpath);
- return -1;
+ if (errno != EEXIST) {
+ gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_HANDLE_CREATE,
+ "link %s -> %s"
+ "failed ",
+ oldpath, newpath);
+ return -1;
+ } else {
+ link_exists = _gf_true;
+ }
}
ret = sys_lstat(newpath, &newbuf);
@@ -775,6 +780,11 @@ posix_handle_hard(xlator_t *this, const char *oldpath, uuid_t gfid,
"lstat on %s failed", newpath);
return -1;
}
+ if ((link_exists) && (!S_ISREG(newbuf.st_mode))) {
+ gf_msg(this->name, GF_LOG_ERROR, EINVAL, P_MSG_HANDLE_CREATE,
+ "%s - Expected regular file", newpath);
+ return -1;
+ }
}
if (newbuf.st_ino != oldbuf->st_ino || newbuf.st_dev != oldbuf->st_dev) {
diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c
index 99ee094c114..1200692db4e 100644
--- a/xlators/storage/posix/src/posix-helpers.c
+++ b/xlators/storage/posix/src/posix-helpers.c
@@ -962,7 +962,7 @@ posix_gfid_set(xlator_t *this, const char *path, loc_t *loc, dict_t *xattr_req,
if (sys_lstat(path, &stat) != 0) {
ret = -1;
gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_LSTAT_FAILED,
- "lsatat on %s failed", path);
+ "lstat on %s failed", path);
goto out;
}