nfsd4: return nfserr_symlink on v4 OPEN of non-regular file
authorJ. Bruce Fields <bfields@redhat.com>
Mon, 15 Aug 2011 20:55:02 +0000 (16:55 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 19 Aug 2011 17:25:32 +0000 (13:25 -0400)
Without this, an attempt to open a device special file without first
stat'ing it will fail.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4proc.c

index 9bf0a66251877e8cdd8cf3d0d556fbcf0630598a..d784ceb81a62f053f9f6dc9faf90d18ed64797f4 100644 (file)
@@ -168,6 +168,24 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
        return status;
 }
 
+static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
+{
+       umode_t mode = fh->fh_dentry->d_inode->i_mode;
+
+       if (S_ISREG(mode))
+               return nfs_ok;
+       if (S_ISDIR(mode))
+               return nfserr_isdir;
+       /*
+        * Using err_symlink as our catch-all case may look odd; but
+        * there's no other obvious error for this case in 4.0, and we
+        * happen to know that it will cause the linux v4 client to do
+        * the right thing on attempts to open something other than a
+        * regular file.
+        */
+       return nfserr_symlink;
+}
+
 static __be32
 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
@@ -216,6 +234,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
                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;