Skip to content

Commit

Permalink
nfsd: export upcalls must not return ESTALE when mountd is down
Browse files Browse the repository at this point in the history
If the rpc.mountd daemon goes down, then that should not cause all
exports to start failing with ESTALE errors. Let's explicitly
distinguish between the cache upcall cases that need to time out,
and those that do not.

Signed-off-by: Trond Myklebust <[email protected]>
Signed-off-by: Chuck Lever <[email protected]>
  • Loading branch information
trondmy authored and chucklever committed Mar 16, 2020
1 parent 6a30e47 commit 65286b8
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 32 deletions.
11 changes: 6 additions & 5 deletions fs/nfs/dns_resolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,13 @@ static int nfs_dns_upcall(struct cache_detail *cd,
struct cache_head *ch)
{
struct nfs_dns_ent *key = container_of(ch, struct nfs_dns_ent, h);
int ret;

ret = nfs_cache_upcall(cd, key->hostname);
if (ret)
ret = sunrpc_cache_pipe_upcall(cd, ch);
return ret;
if (test_and_set_bit(CACHE_PENDING, &ch->flags))
return 0;
if (!nfs_cache_upcall(cd, key->hostname))
return 0;
clear_bit(CACHE_PENDING, &ch->flags);
return sunrpc_cache_pipe_upcall_timeout(cd, ch);
}

static int nfs_dns_match(struct cache_head *ca,
Expand Down
12 changes: 12 additions & 0 deletions fs/nfsd/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ static void expkey_put(struct kref *ref)
kfree_rcu(key, ek_rcu);
}

static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
{
return sunrpc_cache_pipe_upcall(cd, h);
}

static void expkey_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
Expand Down Expand Up @@ -254,6 +259,7 @@ static const struct cache_detail svc_expkey_cache_template = {
.hash_size = EXPKEY_HASHMAX,
.name = "nfsd.fh",
.cache_put = expkey_put,
.cache_upcall = expkey_upcall,
.cache_request = expkey_request,
.cache_parse = expkey_parse,
.cache_show = expkey_show,
Expand Down Expand Up @@ -335,6 +341,11 @@ static void svc_export_put(struct kref *ref)
kfree_rcu(exp, ex_rcu);
}

static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
{
return sunrpc_cache_pipe_upcall(cd, h);
}

static void svc_export_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
Expand Down Expand Up @@ -774,6 +785,7 @@ static const struct cache_detail svc_export_cache_template = {
.hash_size = EXPORT_HASHMAX,
.name = "nfsd.export",
.cache_put = svc_export_put,
.cache_upcall = svc_export_upcall,
.cache_request = svc_export_request,
.cache_parse = svc_export_parse,
.cache_show = svc_export_show,
Expand Down
14 changes: 14 additions & 0 deletions fs/nfsd/nfs4idmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ idtoname_hash(struct ent *ent)
return hash;
}

static int
idtoname_upcall(struct cache_detail *cd, struct cache_head *h)
{
return sunrpc_cache_pipe_upcall_timeout(cd, h);
}

static void
idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
int *blen)
Expand Down Expand Up @@ -184,6 +190,7 @@ static const struct cache_detail idtoname_cache_template = {
.hash_size = ENT_HASHMAX,
.name = "nfs4.idtoname",
.cache_put = ent_put,
.cache_upcall = idtoname_upcall,
.cache_request = idtoname_request,
.cache_parse = idtoname_parse,
.cache_show = idtoname_show,
Expand Down Expand Up @@ -295,6 +302,12 @@ nametoid_hash(struct ent *ent)
return hash_str(ent->name, ENT_HASHBITS);
}

static int
nametoid_upcall(struct cache_detail *cd, struct cache_head *h)
{
return sunrpc_cache_pipe_upcall_timeout(cd, h);
}

static void
nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
int *blen)
Expand Down Expand Up @@ -347,6 +360,7 @@ static const struct cache_detail nametoid_cache_template = {
.hash_size = ENT_HASHMAX,
.name = "nfs4.nametoid",
.cache_put = ent_put,
.cache_upcall = nametoid_upcall,
.cache_request = nametoid_request,
.cache_parse = nametoid_parse,
.cache_show = nametoid_show,
Expand Down
3 changes: 3 additions & 0 deletions include/linux/sunrpc/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ sunrpc_cache_update(struct cache_detail *detail,

extern int
sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h);
extern int
sunrpc_cache_pipe_upcall_timeout(struct cache_detail *detail,
struct cache_head *h);


extern void cache_clean_deferred(void *owner);
Expand Down
12 changes: 12 additions & 0 deletions net/sunrpc/auth_gss/svcauth_gss.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ static struct cache_head *rsi_alloc(void)
return NULL;
}

static int rsi_upcall(struct cache_detail *cd, struct cache_head *h)
{
return sunrpc_cache_pipe_upcall_timeout(cd, h);
}

static void rsi_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
Expand Down Expand Up @@ -278,6 +283,7 @@ static const struct cache_detail rsi_cache_template = {
.hash_size = RSI_HASHMAX,
.name = "auth.rpcsec.init",
.cache_put = rsi_put,
.cache_upcall = rsi_upcall,
.cache_request = rsi_request,
.cache_parse = rsi_parse,
.match = rsi_match,
Expand Down Expand Up @@ -424,6 +430,11 @@ rsc_alloc(void)
return NULL;
}

static int rsc_upcall(struct cache_detail *cd, struct cache_head *h)
{
return -EINVAL;
}

static int rsc_parse(struct cache_detail *cd,
char *mesg, int mlen)
{
Expand Down Expand Up @@ -550,6 +561,7 @@ static const struct cache_detail rsc_cache_template = {
.hash_size = RSC_HASHMAX,
.name = "auth.rpcsec.context",
.cache_put = rsc_put,
.cache_upcall = rsc_upcall,
.cache_parse = rsc_parse,
.match = rsc_match,
.init = rsc_init,
Expand Down
53 changes: 26 additions & 27 deletions net/sunrpc/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@

static bool cache_defer_req(struct cache_req *req, struct cache_head *item);
static void cache_revisit_request(struct cache_head *item);
static bool cache_listeners_exist(struct cache_detail *detail);

static void cache_init(struct cache_head *h, struct cache_detail *detail)
{
Expand Down Expand Up @@ -225,13 +224,6 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
}
EXPORT_SYMBOL_GPL(sunrpc_cache_update);

static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h)
{
if (cd->cache_upcall)
return cd->cache_upcall(cd, h);
return sunrpc_cache_pipe_upcall(cd, h);
}

static inline int cache_is_valid(struct cache_head *h)
{
if (!test_bit(CACHE_VALID, &h->flags))
Expand Down Expand Up @@ -304,17 +296,14 @@ int cache_check(struct cache_detail *detail,
(h->expiry_time != 0 && age > refresh_age/2)) {
dprintk("RPC: Want update, refage=%lld, age=%lld\n",
refresh_age, age);
if (!test_and_set_bit(CACHE_PENDING, &h->flags)) {
switch (cache_make_upcall(detail, h)) {
case -EINVAL:
rv = try_to_negate_entry(detail, h);
break;
case -EAGAIN:
cache_fresh_unlocked(h, detail);
break;
}
} else if (!cache_listeners_exist(detail))
switch (detail->cache_upcall(detail, h)) {
case -EINVAL:
rv = try_to_negate_entry(detail, h);
break;
case -EAGAIN:
cache_fresh_unlocked(h, detail);
break;
}
}

if (rv == -EAGAIN) {
Expand Down Expand Up @@ -1196,20 +1185,12 @@ static bool cache_listeners_exist(struct cache_detail *detail)
*
* Each request is at most one page long.
*/
int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)
static int cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)
{

char *buf;
struct cache_request *crq;
int ret = 0;

if (!detail->cache_request)
return -EINVAL;

if (!cache_listeners_exist(detail)) {
warn_no_listener(detail);
return -EINVAL;
}
if (test_bit(CACHE_CLEANED, &h->flags))
/* Too late to make an upcall */
return -EAGAIN;
Expand Down Expand Up @@ -1243,8 +1224,26 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)
}
return ret;
}

int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)
{
if (test_and_set_bit(CACHE_PENDING, &h->flags))
return 0;
return cache_pipe_upcall(detail, h);
}
EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall);

int sunrpc_cache_pipe_upcall_timeout(struct cache_detail *detail,
struct cache_head *h)
{
if (!cache_listeners_exist(detail)) {
warn_no_listener(detail);
return -EINVAL;
}
return sunrpc_cache_pipe_upcall(detail, h);
}
EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall_timeout);

/*
* parse a message from user-space and pass it
* to an appropriate cache
Expand Down
12 changes: 12 additions & 0 deletions net/sunrpc/svcauth_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ static struct cache_head *ip_map_alloc(void)
return NULL;
}

static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h)
{
return sunrpc_cache_pipe_upcall(cd, h);
}

static void ip_map_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
Expand Down Expand Up @@ -467,6 +472,11 @@ static struct cache_head *unix_gid_alloc(void)
return NULL;
}

static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
{
return sunrpc_cache_pipe_upcall_timeout(cd, h);
}

static void unix_gid_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
Expand Down Expand Up @@ -584,6 +594,7 @@ static const struct cache_detail unix_gid_cache_template = {
.hash_size = GID_HASHMAX,
.name = "auth.unix.gid",
.cache_put = unix_gid_put,
.cache_upcall = unix_gid_upcall,
.cache_request = unix_gid_request,
.cache_parse = unix_gid_parse,
.cache_show = unix_gid_show,
Expand Down Expand Up @@ -881,6 +892,7 @@ static const struct cache_detail ip_map_cache_template = {
.hash_size = IP_HASHMAX,
.name = "auth.unix.ip",
.cache_put = ip_map_put,
.cache_upcall = ip_map_upcall,
.cache_request = ip_map_request,
.cache_parse = ip_map_parse,
.cache_show = ip_map_show,
Expand Down

0 comments on commit 65286b8

Please sign in to comment.