* [PATCH v1] NFSD: Return NFSERR_ISDIR for NFSv2 READ and WRITE on a non-regular file
@ 2026-08-28 23:18 Chuck Lever
2026-08-28 23:28 ` Jeff Layton
2026-08-28 23:50 ` NeilBrown
0 siblings, 2 replies; 3+ messages in thread
From: Chuck Lever @ 2026-08-28 23:18 UTC (permalink / raw)
To: NeilBrown, Jeff Layton, Olga Kornievskaia, Dai Ngo, Tom Talpey
Cc: linux-nfs, Jörg Sommer
Commit 0ac903d1bfdc ("NFS: NFSERR_INVAL is not defined by NFSv2")
changed the status NFSD returns for an NFSv2 READ or WRITE of a
symlink or other non-regular file from NFSERR_INVAL to NFSERR_IO.
RFC 1094 defines neither an INVAL nor a SYMLINK status.
U-Boot's NFS client follows a symlink only when READ fails with
NFSERR_ISDIR or NFSERR_INVAL. Since that commit it cannot load a
boot image through a symlink exported by a Linux NFS server: the
load completes with zero bytes transferred.
Solaris returns NFSERR_ISDIR when the target of an NFSv2 READ or
WRITE is not a regular file. Return the same status from NFSD.
Other NFSv2 procedures continue to return NFSERR_IO.
Fixes: 0ac903d1bfdc ("NFS: NFSERR_INVAL is not defined by NFSv2")
Reported-by: Jörg Sommer <joerg@jo-so.de>
Closes: https://lore.kernel.org/linux-nfs/apE90ZRZB8IW_AiS@jo-so.de/
Signed-off-by: Chuck Lever <cel@kernel.org>
---
fs/nfsd/nfsproc.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 48541ef7644f..09d360839825 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -40,6 +40,21 @@ static __be32 nfsd_map_status(__be32 status)
return status;
}
+/*
+ * Because NFSv2 does not have an NFSERR_SYMLINK, Solaris returns
+ * NFSERR_ISDIR when the target of a READ or WRITE is any object
+ * that is not a regular file.
+ */
+static __be32 nfsd_map_io_status(__be32 status)
+{
+ switch (status) {
+ case nfserr_symlink:
+ case nfserr_wrong_type:
+ return nfserr_isdir;
+ }
+ return nfsd_map_status(status);
+}
+
static __be32
nfsd_proc_null(struct svc_rqst *rqstp)
{
@@ -238,7 +253,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
resp->status = fh_getattr(&resp->fh, &resp->stat);
else if (resp->status == nfserr_jukebox)
set_bit(RQ_DROPME, &rqstp->rq_flags);
- resp->status = nfsd_map_status(resp->status);
+ resp->status = nfsd_map_io_status(resp->status);
return rpc_success;
}
@@ -271,7 +286,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
resp->status = fh_getattr(&resp->fh, &resp->stat);
else if (resp->status == nfserr_jukebox)
set_bit(RQ_DROPME, &rqstp->rq_flags);
- resp->status = nfsd_map_status(resp->status);
+ resp->status = nfsd_map_io_status(resp->status);
return rpc_success;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v1] NFSD: Return NFSERR_ISDIR for NFSv2 READ and WRITE on a non-regular file
2026-08-28 23:18 [PATCH v1] NFSD: Return NFSERR_ISDIR for NFSv2 READ and WRITE on a non-regular file Chuck Lever
@ 2026-08-28 23:28 ` Jeff Layton
2026-08-28 23:50 ` NeilBrown
1 sibling, 0 replies; 3+ messages in thread
From: Jeff Layton @ 2026-08-28 23:28 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey
Cc: linux-nfs, Jörg Sommer
On Fri, 2026-08-28 at 19:18 -0400, Chuck Lever wrote:
> Commit 0ac903d1bfdc ("NFS: NFSERR_INVAL is not defined by NFSv2")
> changed the status NFSD returns for an NFSv2 READ or WRITE of a
> symlink or other non-regular file from NFSERR_INVAL to NFSERR_IO.
> RFC 1094 defines neither an INVAL nor a SYMLINK status.
>
> U-Boot's NFS client follows a symlink only when READ fails with
> NFSERR_ISDIR or NFSERR_INVAL. Since that commit it cannot load a
> boot image through a symlink exported by a Linux NFS server: the
> load completes with zero bytes transferred.
>
> Solaris returns NFSERR_ISDIR when the target of an NFSv2 READ or
> WRITE is not a regular file. Return the same status from NFSD.
> Other NFSv2 procedures continue to return NFSERR_IO.
>
> Fixes: 0ac903d1bfdc ("NFS: NFSERR_INVAL is not defined by NFSv2")
> Reported-by: Jörg Sommer <joerg@jo-so.de>
> Closes: https://lore.kernel.org/linux-nfs/apE90ZRZB8IW_AiS@jo-so.de/
> Signed-off-by: Chuck Lever <cel@kernel.org>
> ---
> fs/nfsd/nfsproc.c | 19 +++++++++++++++++--
> 1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
> index 48541ef7644f..09d360839825 100644
> --- a/fs/nfsd/nfsproc.c
> +++ b/fs/nfsd/nfsproc.c
> @@ -40,6 +40,21 @@ static __be32 nfsd_map_status(__be32 status)
> return status;
> }
>
> +/*
> + * Because NFSv2 does not have an NFSERR_SYMLINK, Solaris returns
> + * NFSERR_ISDIR when the target of a READ or WRITE is any object
> + * that is not a regular file.
> + */
> +static __be32 nfsd_map_io_status(__be32 status)
> +{
> + switch (status) {
> + case nfserr_symlink:
> + case nfserr_wrong_type:
> + return nfserr_isdir;
> + }
> + return nfsd_map_status(status);
> +}
> +
> static __be32
> nfsd_proc_null(struct svc_rqst *rqstp)
> {
> @@ -238,7 +253,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
> resp->status = fh_getattr(&resp->fh, &resp->stat);
> else if (resp->status == nfserr_jukebox)
> set_bit(RQ_DROPME, &rqstp->rq_flags);
> - resp->status = nfsd_map_status(resp->status);
> + resp->status = nfsd_map_io_status(resp->status);
> return rpc_success;
> }
>
> @@ -271,7 +286,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
> resp->status = fh_getattr(&resp->fh, &resp->stat);
> else if (resp->status == nfserr_jukebox)
> set_bit(RQ_DROPME, &rqstp->rq_flags);
> - resp->status = nfsd_map_status(resp->status);
> + resp->status = nfsd_map_io_status(resp->status);
> return rpc_success;
> }
>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v1] NFSD: Return NFSERR_ISDIR for NFSv2 READ and WRITE on a non-regular file
2026-08-28 23:18 [PATCH v1] NFSD: Return NFSERR_ISDIR for NFSv2 READ and WRITE on a non-regular file Chuck Lever
2026-08-28 23:28 ` Jeff Layton
@ 2026-08-28 23:50 ` NeilBrown
1 sibling, 0 replies; 3+ messages in thread
From: NeilBrown @ 2026-08-28 23:50 UTC (permalink / raw)
To: Chuck Lever
Cc: Jeff Layton, Olga Kornievskaia, Dai Ngo, Tom Talpey, linux-nfs,
Jörg Sommer
On Sat, 29 Aug 2026, Chuck Lever wrote:
> Commit 0ac903d1bfdc ("NFS: NFSERR_INVAL is not defined by NFSv2")
> changed the status NFSD returns for an NFSv2 READ or WRITE of a
> symlink or other non-regular file from NFSERR_INVAL to NFSERR_IO.
> RFC 1094 defines neither an INVAL nor a SYMLINK status.
>
> U-Boot's NFS client follows a symlink only when READ fails with
> NFSERR_ISDIR or NFSERR_INVAL. Since that commit it cannot load a
> boot image through a symlink exported by a Linux NFS server: the
> load completes with zero bytes transferred.
>
> Solaris returns NFSERR_ISDIR when the target of an NFSv2 READ or
> WRITE is not a regular file. Return the same status from NFSD.
> Other NFSv2 procedures continue to return NFSERR_IO.
>
> Fixes: 0ac903d1bfdc ("NFS: NFSERR_INVAL is not defined by NFSv2")
> Reported-by: Jörg Sommer <joerg@jo-so.de>
> Closes: https://lore.kernel.org/linux-nfs/apE90ZRZB8IW_AiS@jo-so.de/
> Signed-off-by: Chuck Lever <cel@kernel.org>
Reviewed-by: NeilBrown <neil@brown.name>
The only places that openSolaris returns NFSERR_ISDIR when the object
might not be a directory are in rfs_read(), rfs_write(), and
rfs_write_sync(), which is called for rfs_write().
So adding this special handling only for nfsd_proc_read() and
nfsd_proc_write() makes sense.
Thanks,
NeilBrown
> ---
> fs/nfsd/nfsproc.c | 19 +++++++++++++++++--
> 1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
> index 48541ef7644f..09d360839825 100644
> --- a/fs/nfsd/nfsproc.c
> +++ b/fs/nfsd/nfsproc.c
> @@ -40,6 +40,21 @@ static __be32 nfsd_map_status(__be32 status)
> return status;
> }
>
> +/*
> + * Because NFSv2 does not have an NFSERR_SYMLINK, Solaris returns
> + * NFSERR_ISDIR when the target of a READ or WRITE is any object
> + * that is not a regular file.
> + */
> +static __be32 nfsd_map_io_status(__be32 status)
> +{
> + switch (status) {
> + case nfserr_symlink:
> + case nfserr_wrong_type:
> + return nfserr_isdir;
> + }
> + return nfsd_map_status(status);
> +}
> +
> static __be32
> nfsd_proc_null(struct svc_rqst *rqstp)
> {
> @@ -238,7 +253,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
> resp->status = fh_getattr(&resp->fh, &resp->stat);
> else if (resp->status == nfserr_jukebox)
> set_bit(RQ_DROPME, &rqstp->rq_flags);
> - resp->status = nfsd_map_status(resp->status);
> + resp->status = nfsd_map_io_status(resp->status);
> return rpc_success;
> }
>
> @@ -271,7 +286,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
> resp->status = fh_getattr(&resp->fh, &resp->stat);
> else if (resp->status == nfserr_jukebox)
> set_bit(RQ_DROPME, &rqstp->rq_flags);
> - resp->status = nfsd_map_status(resp->status);
> + resp->status = nfsd_map_io_status(resp->status);
> return rpc_success;
> }
>
> --
> 2.55.0
>
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-28 23:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28 23:18 [PATCH v1] NFSD: Return NFSERR_ISDIR for NFSv2 READ and WRITE on a non-regular file Chuck Lever
2026-08-28 23:28 ` Jeff Layton
2026-08-28 23:50 ` NeilBrown
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.