summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorN Balachandran <nbalacha@redhat.com>2019-01-29 09:47:32 +0530
committerAmar Tumballi <amarts@redhat.com>2019-02-02 03:09:36 +0000
commitda5ae3afcd1b16bb0f2f9bffc1878b17b75429ed (patch)
tree1826c366c3aeaeb43a4cd25bb7d7ad4dba694660
parent23e530a135fc419fba401448290f8b1809e23f53 (diff)
cluster/dht: Do not use gfid-req in fresh lookup
Fuse sets a random gfid-req value for a fresh lookup. Posix lookup will set this gfid on entries with missing gfids causing a GFID mismatch for directories. DHT will now ignore the Fuse provided gfid-req and use the GFID returned from other subvols to heal the missing gfid. Change-Id: I5f541978808f246ba4542564251e341ec490db14 fixes: bz#1670259 Signed-off-by: N Balachandran <nbalacha@redhat.com>
-rw-r--r--xlators/cluster/dht/src/dht-common.c64
-rw-r--r--xlators/cluster/dht/src/dht-common.h4
2 files changed, 60 insertions, 8 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index bc7214e1c7a..cc409c9103d 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -1291,7 +1291,6 @@ dht_lookup_dir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
{
/* TODO: assert equal mode on stbuf->st_mode and
local->stbuf->st_mode
-
else mkdir/chmod/chown and fix
*/
ret = dht_layout_merge(this, layout, prev, op_ret, op_errno, xattr);
@@ -1299,9 +1298,13 @@ dht_lookup_dir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret == -1) {
local->op_errno = op_errno;
gf_msg_debug(this->name, op_errno,
- "lookup of %s on %s returned error", local->loc.path,
+ "%s: lookup on %s returned error", local->loc.path,
prev->name);
+ /* The GFID is missing on this subvol. Force a heal. */
+ if (op_errno == ENODATA) {
+ local->need_selfheal = 1;
+ }
goto unlock;
}
@@ -1401,6 +1404,15 @@ unlock:
if (local->need_selfheal) {
local->need_selfheal = 0;
+ /* Set the gfid-req so posix will set the GFID*/
+ if (!gf_uuid_is_null(local->gfid)) {
+ ret = dict_set_static_bin(local->xattr_req, "gfid-req",
+ local->gfid, 16);
+ } else {
+ if (!gf_uuid_is_null(local->gfid_req))
+ ret = dict_set_static_bin(local->xattr_req, "gfid-req",
+ local->gfid_req, 16);
+ }
dht_lookup_everywhere(frame, this, &local->loc);
return 0;
}
@@ -1590,6 +1602,13 @@ dht_revalidate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
local->need_lookup_everywhere = 1;
}
}
+
+ /* The GFID is missing on this subvol*/
+ if ((op_errno == ENODATA) &&
+ (IA_ISDIR(local->loc.inode->ia_type))) {
+ local->need_lookup_everywhere = 1;
+ }
+
goto unlock;
}
@@ -1818,6 +1837,13 @@ unlock:
/* We know that current cached subvol is no more
valid, get the new one */
local->cached_subvol = NULL;
+ if (local->xattr_req) {
+ if (!gf_uuid_is_null(local->gfid)) {
+ ret = dict_set_static_bin(local->xattr_req, "gfid-req",
+ local->gfid, 16);
+ }
+ }
+
dht_lookup_everywhere(frame, this, &local->loc);
return 0;
}
@@ -2253,6 +2279,16 @@ dht_lookup_everywhere_done(call_frame_t *frame, xlator_t *this)
DHT_STACK_UNWIND(lookup, frame, -1, EIO, NULL, NULL, NULL, NULL);
return 0;
}
+ if (local->op_ret && local->gfid_missing) {
+ if (gf_uuid_is_null(local->gfid_req)) {
+ DHT_STACK_UNWIND(lookup, frame, -1, ENODATA, NULL, NULL, NULL,
+ NULL);
+ return 0;
+ }
+ /* A hack */
+ dht_lookup_directory(frame, this, &local->loc);
+ return 0;
+ }
if (local->dir_count) {
dht_lookup_directory(frame, this, &local->loc);
@@ -2572,6 +2608,8 @@ dht_lookup_everywhere_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret == -1) {
if (op_errno != ENOENT)
local->op_errno = op_errno;
+ if (op_errno == ENODATA)
+ local->gfid_missing = _gf_true;
goto unlock;
}
@@ -3067,7 +3105,11 @@ dht_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
}
} else {
- if (op_errno == ENOTCONN) {
+ /* posix returns ENODATA if the gfid is not set but the client and
+ * server protocol layers do not send the stbuf. We need to
+ * heal this so check if this is a directory on the other subvols.
+ */
+ if ((op_errno == ENOTCONN) || (op_errno == ENODATA)) {
dht_lookup_directory(frame, this, &local->loc);
return 0;
}
@@ -3419,6 +3461,16 @@ dht_do_fresh_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc)
goto err;
}
+ /* Fuse sets a random value in gfid-req. If the gfid is missing
+ * on one or more subvols, posix will set the gfid to this value,
+ * causing GFID mismatches for directories.
+ */
+ ret = dict_get_gfuuid(local->xattr_req, "gfid-req", &local->gfid_req);
+ if (ret) {
+ gf_msg_debug(this->name, 0, "%s: No gfid-req available", loc->path);
+ } else {
+ dict_del(local->xattr_req, "gfid-req");
+ }
/* This should have been set in dht_lookup */
hashed_subvol = local->hashed_subvol;
@@ -3454,10 +3506,8 @@ dht_do_fresh_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc)
/* if we have the hashed_subvol, send the lookup there first so
* as to see whether we have a file or a directory */
- gf_msg_debug(this->name, 0,
- "Calling fresh lookup for %s on"
- " %s",
- loc->path, hashed_subvol->name);
+ gf_msg_debug(this->name, 0, "%s: Calling fresh lookup on %s", loc->path,
+ hashed_subvol->name);
STACK_WIND_COOKIE(frame, dht_lookup_cbk, hashed_subvol, hashed_subvol,
hashed_subvol->fops->lookup, loc, local->xattr_req);
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
index 6fb1c16d0d8..c516271228e 100644
--- a/xlators/cluster/dht/src/dht-common.h
+++ b/xlators/cluster/dht/src/dht-common.h
@@ -323,7 +323,7 @@ struct dht_local {
uint32_t uid;
uint32_t gid;
- pid_t pid;
+ pid_t pid;
/* needed by nufa */
int32_t flags;
@@ -341,6 +341,7 @@ struct dht_local {
/* gfid related */
uuid_t gfid;
+ uuid_t gfid_req;
/* flag used to make sure we need to return estale in
{lookup,revalidate}_cbk */
@@ -385,6 +386,7 @@ struct dht_local {
loc_t loc2_copy;
gf_boolean_t locked;
gf_boolean_t dont_create_linkto;
+ gf_boolean_t gfid_missing;
};
typedef struct dht_local dht_local_t;