Skip to content

Commit 3b60984

Browse files
committed
NFSD: Return NFS4ERR_FILE_OPEN only when renaming over an open file
RFC 8881 Section 18.26.4 paragraphs 1 - 3 tell us that RENAME should return NFS4ERR_FILE_OPEN only when the target object is a file that is currently open. If the target is a directory, some other status must be returned. Generally I expect that a delegation recall will be triggered in some of these circumstances. In other cases, the VFS might return -EBUSY for other reasons, and NFSD has to ensure that errno does not leak to clients as a status code that is not permitted by spec. There are some error flows where the target dentry hasn't been found yet. The default value for @type therefore is S_IFDIR to return an alternate status code in those cases. Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 370345b commit 3b60984

File tree

1 file changed

+29
-4
lines changed

1 file changed

+29
-4
lines changed

fs/nfsd/vfs.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,16 +1794,27 @@ nfsd_has_cached_files(struct dentry *dentry)
17941794
return ret;
17951795
}
17961796

1797-
/*
1798-
* Rename a file
1799-
* N.B. After this call _both_ ffhp and tfhp need an fh_put
1797+
/**
1798+
* nfsd_rename - rename a directory entry
1799+
* @rqstp: RPC transaction context
1800+
* @ffhp: the file handle of parent directory containing the entry to be renamed
1801+
* @fname: the filename of directory entry to be renamed
1802+
* @flen: the length of @fname in octets
1803+
* @tfhp: the file handle of parent directory to contain the renamed entry
1804+
* @tname: the filename of the new entry
1805+
* @tlen: the length of @tlen in octets
1806+
*
1807+
* After this call _both_ ffhp and tfhp need an fh_put.
1808+
*
1809+
* Returns a generic NFS status code in network byte-order.
18001810
*/
18011811
__be32
18021812
nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
18031813
struct svc_fh *tfhp, char *tname, int tlen)
18041814
{
18051815
struct dentry *fdentry, *tdentry, *odentry, *ndentry, *trap;
18061816
struct inode *fdir, *tdir;
1817+
int type = S_IFDIR;
18071818
__be32 err;
18081819
int host_err;
18091820
bool close_cached = false;
@@ -1861,11 +1872,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
18611872
host_err = -EINVAL;
18621873
if (odentry == trap)
18631874
goto out_dput_old;
1875+
type = d_inode(odentry)->i_mode & S_IFMT;
18641876

18651877
ndentry = lookup_one_len(tname, tdentry, tlen);
18661878
host_err = PTR_ERR(ndentry);
18671879
if (IS_ERR(ndentry))
18681880
goto out_dput_old;
1881+
if (d_inode(ndentry))
1882+
type = d_inode(ndentry)->i_mode & S_IFMT;
18691883
host_err = -ENOTEMPTY;
18701884
if (ndentry == trap)
18711885
goto out_dput_new;
@@ -1903,7 +1917,18 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
19031917
out_dput_old:
19041918
dput(odentry);
19051919
out_nfserr:
1906-
err = nfserrno(host_err);
1920+
if (host_err == -EBUSY) {
1921+
/*
1922+
* See RFC 8881 Section 18.26.4 para 1-3: NFSv4 RENAME
1923+
* wants a status unique to the object type.
1924+
*/
1925+
if (type != S_IFDIR)
1926+
err = nfserr_file_open;
1927+
else
1928+
err = nfserr_acces;
1929+
} else {
1930+
err = nfserrno(host_err);
1931+
}
19071932

19081933
if (!close_cached) {
19091934
fh_fill_post_attrs(ffhp);

0 commit comments

Comments
 (0)