diff options
author | J. Bruce Fields <bfields@redhat.com> | 2010-09-19 22:55:06 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-09-19 23:49:30 -0400 |
commit | 06497524589f2a7717da33969d541674e0a27da6 (patch) | |
tree | 3d7d21b9dd325c36e11a923f186059f587d7724d /net/sunrpc/cache.c | |
parent | c88739b373e4930ed082a607cb78bf82616fd076 (diff) |
nfsd4: fix hang on fast-booting nfs servers
The last_close field of a cache_detail is initialized to zero, so the
condition
detail->last_close < seconds_since_boot() - 30
may be false even for a cache that was never opened.
However, we want to immediately fail upcalls to caches that were never
opened: in the case of the auth_unix_gid cache, especially, which may
never be opened by mountd (if the --manage-gids option is not set), we
want to fail the upcall immediately. Otherwise client requests will be
dropped unnecessarily on reboot.
Also document these conditions.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r-- | net/sunrpc/cache.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index da872f9fe1e0..ca7c621cd975 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -1091,6 +1091,23 @@ static void warn_no_listener(struct cache_detail *detail) | |||
1091 | } | 1091 | } |
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | static bool cache_listeners_exist(struct cache_detail *detail) | ||
1095 | { | ||
1096 | if (atomic_read(&detail->readers)) | ||
1097 | return true; | ||
1098 | if (detail->last_close == 0) | ||
1099 | /* This cache was never opened */ | ||
1100 | return false; | ||
1101 | if (detail->last_close < seconds_since_boot() - 30) | ||
1102 | /* | ||
1103 | * We allow for the possibility that someone might | ||
1104 | * restart a userspace daemon without restarting the | ||
1105 | * server; but after 30 seconds, we give up. | ||
1106 | */ | ||
1107 | return false; | ||
1108 | return true; | ||
1109 | } | ||
1110 | |||
1094 | /* | 1111 | /* |
1095 | * register an upcall request to user-space and queue it up for read() by the | 1112 | * register an upcall request to user-space and queue it up for read() by the |
1096 | * upcall daemon. | 1113 | * upcall daemon. |
@@ -1109,10 +1126,9 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h, | |||
1109 | char *bp; | 1126 | char *bp; |
1110 | int len; | 1127 | int len; |
1111 | 1128 | ||
1112 | if (atomic_read(&detail->readers) == 0 && | 1129 | if (!cache_listeners_exist(detail)) { |
1113 | detail->last_close < seconds_since_boot() - 30) { | 1130 | warn_no_listener(detail); |
1114 | warn_no_listener(detail); | 1131 | return -EINVAL; |
1115 | return -EINVAL; | ||
1116 | } | 1132 | } |
1117 | 1133 | ||
1118 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1134 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |