From 4ce56133a793c97f5995181504ca9a16146a521f Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 9 Apr 2012 18:06:49 -0400 Subject: [PATCH] nfsd: don't fail unchecked creates of non-special files commit 9dc4e6c4d1182d34604ea40fef641775f5b15456 upstream. Allow a v3 unchecked open of a non-regular file succeed as if it were a lookup; typically a client in such a case will want to fall back on a local open, so succeeding and giving it the filehandle is more useful than failing with nfserr_exist, which makes it appear that nothing at all exists by that name. Similarly for v4, on an open-create, return the same errors we would on an attempt to open a non-regular file, instead of returning nfserr_exist. This fixes a problem found doing a v4 open of a symlink with O_RDONLY|O_CREAT, which resulted in the current client returning EEXIST. Thanks also to Trond for analysis. Reported-by: Orion Poplawski Tested-by: Orion Poplawski Signed-off-by: J. Bruce Fields [bwh: Backported to 3.2: use &resfh, not resfh] Signed-off-by: Ben Hutchings --- fs/nfsd/nfs4proc.c | 8 ++++---- fs/nfsd/vfs.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 35840aa63080..b8c5538fe455 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -231,15 +231,15 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o */ if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | - FATTR4_WORD1_TIME_MODIFY); + FATTR4_WORD1_TIME_MODIFY); } else { status = nfsd_lookup(rqstp, current_fh, open->op_fname.data, open->op_fname.len, &resfh); fh_unlock(current_fh); - if (status) - goto out; - status = nfsd_check_obj_isreg(&resfh); } + if (status) + goto out; + status = nfsd_check_obj_isreg(&resfh); if (status) goto out; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7a2e442623c8..5c3cd820a8af 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1439,7 +1439,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, switch (createmode) { case NFS3_CREATE_UNCHECKED: if (! S_ISREG(dchild->d_inode->i_mode)) - err = nfserr_exist; + goto out; else if (truncp) { /* in nfsv4, we need to treat this case a little * differently. we don't want to truncate the -- 2.39.2