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>
This commit is contained in:
parent
23e530a135
commit
da5ae3afcd
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user