From da5ae3afcd1b16bb0f2f9bffc1878b17b75429ed Mon Sep 17 00:00:00 2001 From: N Balachandran Date: Tue, 29 Jan 2019 09:47:32 +0530 Subject: 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 --- xlators/cluster/dht/src/dht-common.c | 64 ++++++++++++++++++++++++++++++++---- xlators/cluster/dht/src/dht-common.h | 4 ++- 2 files changed, 60 insertions(+), 8 deletions(-) (limited to 'xlators') 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; -- cgit