Re: [PATCH v2 5/5] NFSD: Don't apply NFS version-specific behavior to LOCALIO requests

NeilBrown <[email protected]> Wed, 29 Jul 2026 08:20:18 +1000
Newsgroups org.kernel.vger.linux-nfs
Message-ID <[email protected]>
On Wed, 29 Jul 2026, Chuck Lever wrote:
> LOCALIO serves NFS clients of every version through one entry point,
> so no protocol version is associated with such a request.
> nfsd_set_fh_dentry() selects version-specific behavior anyway: its
> switch keys off fh_maxsize, and nfsd_open_local_fh() passes
> NFS4_FHSIZE because that is the size of the buffer it copies into, so
> LOCALIO lands in the NFSv4 arm. fh_getattr() keys off fh_maxsize too
> and does run on a LOCALIO open, adding STATX_BTIME and
> STATX_CHANGE_COOKIE to the mask it requests: work on filesystems that
> compute them for a caller that never reads them.
>=20
> nfsd_open_local_fh() only verifies a handle it received, so it has no
> maximum size to state. Pass NFSD_FHSIZE_UNSPEC as nlm_fopen() already
> does, which selects the switch arm that applies no version-specific
> behavior, and state the bound on the copy out of struct nfs_fh as
> NFS_MAXFHSIZE.
>=20
> Suggested-by: NeilBrown <[email protected]>
> Signed-off-by: Chuck Lever <[email protected]>

Thanks for putting in the extra research to get a fully baked
solution instead of just using my half baked idea.  I like what you did
a lot.

For the whole series:
 Reviewed-by: NeilBrown <[email protected]>

NeilBrown


> ---
>  fs/nfsd/localio.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
>=20
> diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c
> index 4110be02b750..33b56d1b3f44 100644
> --- a/fs/nfsd/localio.c
> +++ b/fs/nfsd/localio.c
> @@ -11,7 +11,6 @@
>  #include <linux/exportfs.h>
>  #include <linux/sunrpc/svcauth.h>
>  #include <linux/sunrpc/clnt.h>
> -#include <linux/nfs4.h>
>  #include <linux/nfs_common.h>
>  #include <linux/nfs_fh.h>
>  #include <linux/nfslocalio.h>
> @@ -54,7 +53,7 @@ nfsd_open_local_fh(struct net *net, struct auth_domain *d=
om,
>  	struct nfsd_file *localio;
>  	__be32 beres;
> =20
> -	if (nfs_fh->size > NFS4_FHSIZE)
> +	if (nfs_fh->size > NFS_MAXFHSIZE)
>  		return ERR_PTR(-EINVAL);
> =20
>  	if (!nfsd_net_try_get(net))
> @@ -67,7 +66,7 @@ nfsd_open_local_fh(struct net *net, struct auth_domain *d=
om,
>  		return localio;
> =20
>  	/* nfs_fh -> svc_fh */
> -	fh_init(&fh, NFS4_FHSIZE);
> +	fh_init(&fh, NFSD_FHSIZE_UNSPEC);
>  	fh.fh_handle.fh_size =3D nfs_fh->size;
>  	memcpy(fh.fh_handle.fh_raw, nfs_fh->data, nfs_fh->size);
> =20
> --=20
> 2.54.0
>=20
>=20