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>
This commit is contained in:
@@ -1091,6 +1091,23 @@ static void warn_no_listener(struct cache_detail *detail)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool cache_listeners_exist(struct cache_detail *detail)
|
||||||
|
{
|
||||||
|
if (atomic_read(&detail->readers))
|
||||||
|
return true;
|
||||||
|
if (detail->last_close == 0)
|
||||||
|
/* This cache was never opened */
|
||||||
|
return false;
|
||||||
|
if (detail->last_close < seconds_since_boot() - 30)
|
||||||
|
/*
|
||||||
|
* We allow for the possibility that someone might
|
||||||
|
* restart a userspace daemon without restarting the
|
||||||
|
* server; but after 30 seconds, we give up.
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* register an upcall request to user-space and queue it up for read() by the
|
* register an upcall request to user-space and queue it up for read() by the
|
||||||
* upcall daemon.
|
* upcall daemon.
|
||||||
@@ -1109,10 +1126,9 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
|
|||||||
char *bp;
|
char *bp;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (atomic_read(&detail->readers) == 0 &&
|
if (!cache_listeners_exist(detail)) {
|
||||||
detail->last_close < seconds_since_boot() - 30) {
|
warn_no_listener(detail);
|
||||||
warn_no_listener(detail);
|
return -EINVAL;
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||||
|
Reference in New Issue
Block a user