Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 06497524 authored by J. Bruce Fields's avatar J. Bruce Fields
Browse files

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: default avatarJ. Bruce Fields <bfields@redhat.com>
parent c88739b3
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -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
 * upcall daemon.
@@ -1109,8 +1126,7 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
	char *bp;
	int len;

	if (atomic_read(&detail->readers) == 0 &&
	    detail->last_close < seconds_since_boot() - 30) {
	if (!cache_listeners_exist(detail)) {
		warn_no_listener(detail);
		return -EINVAL;
	}