|
|
a3470f |
From 90092b0c276f599bbe415ecc3051ca12d99461b6 Mon Sep 17 00:00:00 2001
|
|
|
a3470f |
From: Raghavendra G <rgowdapp@redhat.com>
|
|
|
a3470f |
Date: Sat, 17 Mar 2018 13:16:59 +0530
|
|
|
a3470f |
Subject: [PATCH 263/271] server/resolver: don't trust inode-table for
|
|
|
a3470f |
RESOLVE_NOT
|
|
|
a3470f |
|
|
|
a3470f |
There have been known races between fops which add a dentry (like
|
|
|
a3470f |
lookup, create, mknod etc) and fops that remove a dentry (like rename,
|
|
|
a3470f |
unlink, rmdir etc) due to which stale dentries are left out in inode
|
|
|
a3470f |
table even though the dentry doesn't exist on backend. For eg.,
|
|
|
a3470f |
consider a lookup (parent/bname) and unlink (parent/bname) racing in
|
|
|
a3470f |
the following order:
|
|
|
a3470f |
|
|
|
a3470f |
* lookup hits storage/posix and finds that dentry exists
|
|
|
a3470f |
* unlink removes the dentry on storage/posix
|
|
|
a3470f |
* unlink reaches protocol/server where the dentry (parent/bname) is
|
|
|
a3470f |
unlinked from the inode
|
|
|
a3470f |
* lookup reaches protocol/server and creates a dentry (parent/bname)
|
|
|
a3470f |
on the inode
|
|
|
a3470f |
|
|
|
a3470f |
Now we've a stale dentry (parent/bname) associated with the inode in
|
|
|
a3470f |
itable. This situation is bad for fops like link, create etc which
|
|
|
a3470f |
invoke resolver with type RESOLVE_NOT. These fops fail with EEXIST
|
|
|
a3470f |
even though there is no such dentry on backend fs. This issue can be
|
|
|
a3470f |
solved in two ways:
|
|
|
a3470f |
|
|
|
a3470f |
* Enable "dentry fop serializer" xlator [1].
|
|
|
a3470f |
# gluster volume set features.sdfs on
|
|
|
a3470f |
|
|
|
a3470f |
* Make sure resolver does a lookup on backend when it finds a dentry
|
|
|
a3470f |
in itable and validates the state of itable.
|
|
|
a3470f |
- If a dentry is not found, unlink those stale dentries from itable
|
|
|
a3470f |
and continue with fop
|
|
|
a3470f |
- If dentry is found, fail the fop with EEXIST
|
|
|
a3470f |
|
|
|
a3470f |
This patch implements second solution as sdfs is not enabled by
|
|
|
a3470f |
default in brick xlator stack. Once sdfs is enabled by default, this
|
|
|
a3470f |
patch can be reverted.
|
|
|
a3470f |
|
|
|
a3470f |
[1] https://github.com/gluster/glusterfs/issues/397
|
|
|
a3470f |
|
|
|
a3470f |
>Change-Id: Ia8bb0cf97f97cb0e72639bce8aadb0f6d3f4a34a
|
|
|
a3470f |
>updates: bz#1543279
|
|
|
a3470f |
>BUG: 1543279
|
|
|
a3470f |
>Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
|
|
|
a3470f |
|
|
|
a3470f |
upstream patch: https://review.gluster.org/19732
|
|
|
a3470f |
BUG: 1488120
|
|
|
a3470f |
Change-Id: I78df4f6751e5db1fc659ee15d92b76d1486455f0
|
|
|
a3470f |
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
|
|
|
a3470f |
Reviewed-on: https://code.engineering.redhat.com/gerrit/138152
|
|
|
a3470f |
Tested-by: RHGS Build Bot <nigelb@redhat.com>
|
|
|
a3470f |
Reviewed-by: Nithya Balachandran <nbalacha@redhat.com>
|
|
|
a3470f |
---
|
|
|
a3470f |
xlators/protocol/server/src/server-resolve.c | 27 +++++++++++++++++++++++----
|
|
|
a3470f |
1 file changed, 23 insertions(+), 4 deletions(-)
|
|
|
a3470f |
|
|
|
a3470f |
diff --git a/xlators/protocol/server/src/server-resolve.c b/xlators/protocol/server/src/server-resolve.c
|
|
|
a3470f |
index d0126aa..6ffb909 100644
|
|
|
a3470f |
--- a/xlators/protocol/server/src/server-resolve.c
|
|
|
a3470f |
+++ b/xlators/protocol/server/src/server-resolve.c
|
|
|
a3470f |
@@ -58,10 +58,27 @@ resolve_gfid_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
a3470f |
|
|
|
a3470f |
if (op_ret == -1) {
|
|
|
a3470f |
if (op_errno == ENOENT) {
|
|
|
a3470f |
- gf_msg_debug (this->name, 0, "%s/%s: failed to resolve"
|
|
|
a3470f |
- " (%s)",
|
|
|
a3470f |
+ gf_msg_debug (this->name, 0,
|
|
|
a3470f |
+ "%s/%s: failed to resolve (%s)",
|
|
|
a3470f |
uuid_utoa (resolve_loc->pargfid),
|
|
|
a3470f |
resolve_loc->name, strerror (op_errno));
|
|
|
a3470f |
+ if (resolve->type == RESOLVE_NOT) {
|
|
|
a3470f |
+ do {
|
|
|
a3470f |
+ inode = inode_grep (state->itable,
|
|
|
a3470f |
+ resolve_loc->parent,
|
|
|
a3470f |
+ resolve->bname);
|
|
|
a3470f |
+
|
|
|
a3470f |
+ if (inode) {
|
|
|
a3470f |
+ gf_msg_debug (this->name, 0, "%s/%s: "
|
|
|
a3470f |
+ "removing stale dentry",
|
|
|
a3470f |
+ uuid_utoa (resolve_loc->pargfid),
|
|
|
a3470f |
+ resolve->bname);
|
|
|
a3470f |
+ inode_unlink (inode,
|
|
|
a3470f |
+ resolve_loc->parent,
|
|
|
a3470f |
+ resolve->bname);
|
|
|
a3470f |
+ }
|
|
|
a3470f |
+ } while (inode);
|
|
|
a3470f |
+ }
|
|
|
a3470f |
} else {
|
|
|
a3470f |
gf_msg (this->name, GF_LOG_WARNING, op_errno,
|
|
|
a3470f |
PS_MSG_GFID_RESOLVE_FAILED, "%s/%s: failed to "
|
|
|
a3470f |
@@ -318,11 +335,13 @@ resolve_entry_simple (call_frame_t *frame)
|
|
|
a3470f |
|
|
|
a3470f |
if (resolve->type == RESOLVE_NOT) {
|
|
|
a3470f |
gf_msg_debug (this->name, 0, "inode (pointer: %p gfid:%s found"
|
|
|
a3470f |
- " for path (%s) while type is RESOLVE_NOT",
|
|
|
a3470f |
+ " for path (%s) while type is RESOLVE_NOT. "
|
|
|
a3470f |
+ "Performing lookup on backend to rule out any "
|
|
|
a3470f |
+ "possible stale dentries in inode table",
|
|
|
a3470f |
inode, uuid_utoa (inode->gfid), resolve->path);
|
|
|
a3470f |
resolve->op_ret = -1;
|
|
|
a3470f |
resolve->op_errno = EEXIST;
|
|
|
a3470f |
- ret = -1;
|
|
|
a3470f |
+ ret = 1;
|
|
|
a3470f |
goto out;
|
|
|
a3470f |
}
|
|
|
a3470f |
|
|
|
a3470f |
--
|
|
|
a3470f |
1.8.3.1
|
|
|
a3470f |
|