]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
nfsd: check for EBUSY from vfs_rmdir/vfs_unink.
authorNeilBrown <neilb@suse.de>
Thu, 28 Nov 2019 02:56:43 +0000 (13:56 +1100)
committerJ. Bruce Fields <bfields@redhat.com>
Sat, 30 Nov 2019 19:59:52 +0000 (14:59 -0500)
vfs_rmdir and vfs_unlink can return -EBUSY if the
target is a mountpoint.  This currently gets passed to
nfserrno() by nfsd_unlink(), and that results in a WARNing,
which is not user-friendly.

Possibly the best NFSv4 error is NFS4ERR_FILE_OPEN, because
there is a sense in which the object is currently in use
by some other task.  The Linux NFSv4 client will map this
back to EBUSY, which is an added benefit.

For NFSv3, the best we can do is probably NFS3ERR_ACCES, which isn't
true, but is not less true than the other options.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfsd.h
fs/nfsd/vfs.c

index af2947551e9ce87cf3f8a94564963974e84199b3..57b93d95fa5c84479894a9a8e518da65907373cd 100644 (file)
@@ -280,7 +280,8 @@ void                nfsd_lockd_shutdown(void);
 #define nfserr_union_notsupp           cpu_to_be32(NFS4ERR_UNION_NOTSUPP)
 #define nfserr_offload_denied          cpu_to_be32(NFS4ERR_OFFLOAD_DENIED)
 #define nfserr_wrong_lfs               cpu_to_be32(NFS4ERR_WRONG_LFS)
-#define nfserr_badlabel                cpu_to_be32(NFS4ERR_BADLABEL)
+#define nfserr_badlabel                        cpu_to_be32(NFS4ERR_BADLABEL)
+#define nfserr_file_open               cpu_to_be32(NFS4ERR_FILE_OPEN)
 
 /* error codes for internal use */
 /* if a request fails due to kmalloc failure, it gets dropped.
index cf423fea0c6fef3299d50d063eae03d920712971..c0dc491537a69f4271b235e46e583bbb3924e0fc 100644 (file)
@@ -1815,7 +1815,17 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
 out_drop_write:
        fh_drop_write(fhp);
 out_nfserr:
-       err = nfserrno(host_err);
+       if (host_err == -EBUSY) {
+               /* name is mounted-on. There is no perfect
+                * error status.
+                */
+               if (nfsd_v4client(rqstp))
+                       err = nfserr_file_open;
+               else
+                       err = nfserr_acces;
+       } else {
+               err = nfserrno(host_err);
+       }
 out:
        return err;
 }