]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
nfsd: allow filecache open to skip fh_verify check
authorJeff Layton <jlayton@poochiereds.net>
Tue, 20 Oct 2015 17:33:44 +0000 (13:33 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 23 Oct 2015 19:57:39 +0000 (15:57 -0400)
Currently, we call fh_verify twice on the filehandle. Once when we call
into nfsd_file_acquire, and then again from nfsd_open. The second one is
completely superfluous though, and fh_verify can do some things that
require a fair bit of work (checking permissions, for instance).

Create a new nfsd_open_verified function that will do an nfsd_open on a
filehandle that has already been verified. Call that from the filecache
code.

Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/filecache.c
fs/nfsd/vfs.c
fs/nfsd/vfs.h

index aca3c3c638ec37d1cd4eb1036f3f0a9e9488220a..3a4e423d2bb982597880e153f0305fe1ab5f5390 100644 (file)
@@ -670,7 +670,8 @@ open_file:
        }
        /* FIXME: should we abort opening if the link count goes to 0? */
        if (status == nfs_ok)
-               status = nfsd_open(rqstp, fhp, S_IFREG, may_flags, &nf->nf_file);
+               status = nfsd_open_verified(rqstp, fhp, S_IFREG, may_flags,
+                                               &nf->nf_file);
        clear_bit_unlock(NFSD_FILE_PENDING, &nf->nf_flags);
        smp_mb__after_atomic();
        wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
index 0f7d4ffcbe829a8f623b3d5611cf3efceee7d7c8..575ce9efbf934408497e4028fd020b9a7126019c 100644 (file)
@@ -634,9 +634,9 @@ nfsd_open_break_lease(struct inode *inode, int access)
  * and additional flags.
  * N.B. After this call fhp needs an fh_put
  */
-__be32
-nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
-                       int may_flags, struct file **filp)
+static __be32
+__nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
+           int may_flags, struct file **filp)
 {
        struct path     path;
        struct inode    *inode;
@@ -645,24 +645,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
        __be32          err;
        int             host_err = 0;
 
-       validate_process_creds();
-
-       /*
-        * If we get here, then the client has already done an "open",
-        * and (hopefully) checked permission - so allow OWNER_OVERRIDE
-        * in case a chmod has now revoked permission.
-        *
-        * Arguably we should also allow the owner override for
-        * directories, but we never have and it doesn't seem to have
-        * caused anyone a problem.  If we were to change this, note
-        * also that our filldir callbacks would need a variant of
-        * lookup_one_len that doesn't check permissions.
-        */
-       if (type == S_IFREG)
-               may_flags |= NFSD_MAY_OWNER_OVERRIDE;
-       err = fh_verify(rqstp, fhp, type, may_flags);
-       if (err)
-               goto out;
+       BUG_ON(!fhp->fh_dentry);
 
        path.mnt = fhp->fh_export->ex_path.mnt;
        path.dentry = fhp->fh_dentry;
@@ -717,6 +700,44 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
 out_nfserr:
        err = nfserrno(host_err);
 out:
+       return err;
+}
+
+__be32
+nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
+                       int may_flags, struct file **filp)
+{
+       __be32 err;
+
+       validate_process_creds();
+       /*
+        * If we get here, then the client has already done an "open",
+        * and (hopefully) checked permission - so allow OWNER_OVERRIDE
+        * in case a chmod has now revoked permission.
+        *
+        * Arguably we should also allow the owner override for
+        * directories, but we never have and it doesn't seem to have
+        * caused anyone a problem.  If we were to change this, note
+        * also that our filldir callbacks would need a variant of
+        * lookup_one_len that doesn't check permissions.
+        */
+       if (type == S_IFREG)
+               may_flags |= NFSD_MAY_OWNER_OVERRIDE;
+       err = fh_verify(rqstp, fhp, type, may_flags);
+       if (!err)
+               err = __nfsd_open(rqstp, fhp, type, may_flags, filp);
+       validate_process_creds();
+       return err;
+}
+
+__be32
+nfsd_open_verified(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
+                  int may_flags, struct file **filp)
+{
+       __be32 err;
+
+       validate_process_creds();
+       err = __nfsd_open(rqstp, fhp, type, may_flags, filp);
        validate_process_creds();
        return err;
 }
index a877be59d5dd5fa0f50be306335e1a82bc13e853..b3beb896b08d6c9651ed40d59a9441c727d70c6c 100644 (file)
@@ -72,6 +72,8 @@ __be32                nfsd_commit(struct svc_rqst *, struct svc_fh *,
 int            nfsd_open_break_lease(struct inode *, int);
 __be32         nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t,
                                int, struct file **);
+__be32         nfsd_open_verified(struct svc_rqst *, struct svc_fh *, umode_t,
+                               int, struct file **);
 struct raparms;
 __be32         nfsd_splice_read(struct svc_rqst *,
                                struct file *, loff_t, unsigned long *);