From: Chuck Lever <chuck.lever@oracle.com>
To: Amir Goldstein <amir73il@gmail.com>
Cc: NeilBrown <neilb@suse.de>, Jeff Layton <jlayton@kernel.org>,
"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>,
"linux-nfs@vger.kernel.org" <linux-nfs@vger.kernel.org>,
Trond Myklebust <trondmy@hammerspace.com>,
Miklos Szeredi <miklos@szeredi.hu>
Subject: Re: [PATCH v2] nfsd: map EBUSY to NFS4ERR_ACCESS for all operations
Date: Wed, 22 Jan 2025 14:20:37 -0500 [thread overview]
Message-ID: <d36de874-7603-478b-a01e-b7d1eb7110d3@oracle.com> (raw)
In-Reply-To: <CAOQ4uxiVLTv94=Xkiqw4NJHa8RysE3bGDx64TLuLF+nxkOh-Eg@mail.gmail.com>
On 1/22/25 1:53 PM, Amir Goldstein wrote:
>>> I am fine with handling EBUSY in unlink/rmdir/rename/open
>>> only for now if that is what everyone prefers.
>>
>> As far as I can tell, NFSv2 and NFSv3 REMOVE/RMDIR are working
>> correctly. NFSv4 REMOVE needs to return a status code that depends
>> on whether the target object is a file or not. Probably not much more
>> than something like this:
>>
>> status = vfs_unlink( ... );
>> + /* RFC 8881 Section 18.25.4 paragraph 5 */
>> + if (status == nfserr_file_open && !S_ISREG(...))
>> + status = nfserr_access;
>>
>> added to nfsd4_remove().
>
> Don't you think it's a bit awkward mapping back and forth like this?
Yes, it's awkward. It's an artifact of the way NFSD's VFS helpers have
been co-opted for new versions of the NFS protocol over the years.
With NFSv2 and NFSv3, the operations and their permitted status codes
are roughly similar so that these VFS helpers can be re-used without
a lot of fuss. This is also why, internally, the symbolic status codes
are named without the version number in them (ie, nfserr_inval).
With NFSv4, the world is more complicated.
The NFSv4 code was prototyped 20 years ago using these NFSv2/3 helpers,
and is never revisited until there's a bug. Thus there is quite a bit of
technical debt in fs/nfsd/vfs.c that we're replacing over time.
IMO it would be better if these VFS helpers returned errno values and
then the callers should figure out the conversion to an NFS status code.
I suspect that's difficult because some of the functions invoked by the
VFS helpers (like fh_verify() ) also return NFS status codes. We just
spent some time extracting NFS version-specific code from fh_verify().
> Don't you think something like this is a more sane way to keep the
> mapping rules in one place:
>
> @@ -111,6 +111,26 @@ nfserrno (int errno)
> return nfserr_io;
> }
>
> +static __be32
> +nfsd_map_errno(int host_err, int may_flags, int type)
> +{
> + switch (host_err) {
> + case -EBUSY:
> + /*
> + * According to RFC 8881 Section 18.25.4 paragraph 5,
> + * removal of regular file can fail with NFS4ERR_FILE_OPEN.
> + * For failure to remove directory we return NFS4ERR_ACCESS,
> + * same as NFS4ERR_FILE_OPEN is mapped in v3 and v2.
> + */
> + if (may_flags == NFSD_MAY_REMOVE && type == S_IFREG)
> + return nfserr_file_open;
> + else
> + return nfserr_acces;
> + }
> +
> + return nfserrno(host_err);
> +}
> +
> /*
> * Called from nfsd_lookup and encode_dirent. Check if we have crossed
> * a mount point.
> @@ -2006,14 +2026,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct
> svc_fh *fhp, int type,
> out_drop_write:
> fh_drop_write(fhp);
> out_nfserr:
> - if (host_err == -EBUSY) {
> - /* name is mounted-on. There is no perfect
> - * error status.
> - */
> - err = nfserr_file_open;
> - } else {
> - err = nfserrno(host_err);
> - }
> + err = nfsd_map_errno(host_err, NFSD_MAY_REMOVE, type);
> out:
> return err;
No, I don't.
NFSD has Kconfig options that disable support for some versions of NFS.
The code that manages which status code to return really needs to be
inside the functions that are enabled or disabled by Kconfig.
As I keep repeating: there is no good way to handle the NFS status codes
in one set of functions. Each NFS version has its variations that
require special handling.
>> Let's visit RENAME once that is addressed.
>
> And then next patch would be:
>
> @@ -1828,6 +1828,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct
> svc_fh *ffhp, char *fname, int flen,
> __be32 err;
> int host_err;
> bool close_cached = false;
> + int type;
>
> err = fh_verify(rqstp, ffhp, S_IFDIR, NFSD_MAY_REMOVE);
> if (err)
> @@ -1922,8 +1923,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct
> svc_fh *ffhp, char *fname, int flen,
> out_dput_new:
> dput(ndentry);
> out_dput_old:
> + type = d_inode(odentry)->i_mode & S_IFMT;
> dput(odentry);
> out_nfserr:
> - err = nfserrno(host_err);
> + err = nfsd_map_errno(host_err, NFSD_MAY_REMOVE, type);
Same problem here: the NFS version-specific status codes have to be
figured out in the callers, not in nfsd_rename(). The status codes
are not common to all NFS versions.
>> Then handle OPEN as a third patch, because I bet we are going to meet
>> some complications there.
>
> Did you think of anything better to do for OPEN other than NFS4ERR_ACCESS?
I haven't even started to think about that yet.
--
Chuck Lever
next prev parent reply other threads:[~2025-01-22 19:20 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-21 10:39 [PATCH v2] nfsd: map EBUSY to NFS4ERR_ACCESS for all operations Amir Goldstein
2025-01-21 12:21 ` Jeff Layton
2025-01-21 19:45 ` Chuck Lever
2025-01-21 21:44 ` Amir Goldstein
2025-01-21 22:59 ` NeilBrown
2025-01-22 9:05 ` Amir Goldstein
2025-01-22 15:04 ` Chuck Lever
2025-01-22 15:29 ` Amir Goldstein
2025-01-22 16:50 ` Chuck Lever
2025-01-22 18:53 ` Amir Goldstein
2025-01-22 19:20 ` Chuck Lever [this message]
2025-01-22 20:11 ` Amir Goldstein
2025-01-23 14:59 ` Chuck Lever
2025-01-23 15:29 ` Amir Goldstein
2025-01-23 17:37 ` Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d36de874-7603-478b-a01e-b7d1eb7110d3@oracle.com \
--to=chuck.lever@oracle.com \
--cc=amir73il@gmail.com \
--cc=jlayton@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=neilb@suse.de \
--cc=trondmy@hammerspace.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox