Author: rmacklem
Date: Sat Dec 25 21:56:25 2010
New Revision: 216700
URL: http://svn.freebsd.org/changeset/base/216700

Log:
  Modify the experimental NFS server so that it uses LK_SHARED
  for RPC operations when it can. Since VFS_FHTOVP() currently
  always gets an exclusively locked vnode and is usually called
  at the beginning of each RPC, the RPCs for a given vnode will
  still be serialized. As such, passing a lock type argument to
  VFS_FHTOVP() would be preferable to doing the vn_lock() with
  LK_DOWNGRADE after the VFS_FHTOVP() call.
  
  Reviewed by:  kib
  MFC after:    2 weeks

Modified:
  head/sys/fs/nfs/nfs.h
  head/sys/fs/nfs/nfs_commonsubs.c
  head/sys/fs/nfs/nfs_var.h
  head/sys/fs/nfsserver/nfs_nfsdport.c
  head/sys/fs/nfsserver/nfs_nfsdserv.c
  head/sys/fs/nfsserver/nfs_nfsdsocket.c

Modified: head/sys/fs/nfs/nfs.h
==============================================================================
--- head/sys/fs/nfs/nfs.h       Sat Dec 25 21:26:56 2010        (r216699)
+++ head/sys/fs/nfs/nfs.h       Sat Dec 25 21:56:25 2010        (r216700)
@@ -568,6 +568,7 @@ struct nfsv4_opflag {
        int     needscfh;
        int     savereply;
        int     modifyfs;
+       int     lktype;
 };
 
 /*

Modified: head/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- head/sys/fs/nfs/nfs_commonsubs.c    Sat Dec 25 21:26:56 2010        
(r216699)
+++ head/sys/fs/nfs/nfs_commonsubs.c    Sat Dec 25 21:56:25 2010        
(r216700)
@@ -84,46 +84,46 @@ NFSSOCKMUTEX;
  * Define it here, since it is used by both the client and server.
  */
 struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS] = {
-       { 0, 0, 0, 0 },         /* undef */
-       { 0, 0, 0, 0 },         /* undef */
-       { 0, 0, 0, 0 },         /* undef */
-       { 0, 1, 0, 0 },         /* Access */
-       { 0, 1, 0, 0 },         /* Close */
-       { 0, 2, 0, 1 },         /* Commit */
-       { 1, 2, 1, 1 },         /* Create */
-       { 0, 0, 0, 0 },         /* Delegpurge */
-       { 0, 1, 0, 0 },         /* Delegreturn */
-       { 0, 1, 0, 0 },         /* Getattr */
-       { 0, 1, 0, 0 },         /* GetFH */
-       { 2, 1, 1, 1 },         /* Link */
-       { 0, 1, 0, 0 },         /* Lock */
-       { 0, 1, 0, 0 },         /* LockT */
-       { 0, 1, 0, 0 },         /* LockU */
-       { 1, 1, 0, 0 },         /* Lookup */
-       { 1, 1, 0, 0 },         /* Lookupp */
-       { 0, 1, 0, 0 },         /* NVerify */
-       { 1, 1, 0, 1 },         /* Open */
-       { 1, 1, 0, 0 },         /* OpenAttr */
-       { 0, 1, 0, 0 },         /* OpenConfirm */
-       { 0, 1, 0, 0 },         /* OpenDowngrade */
-       { 1, 0, 0, 0 },         /* PutFH */
-       { 1, 0, 0, 0 },         /* PutPubFH */
-       { 1, 0, 0, 0 },         /* PutRootFH */
-       { 0, 1, 0, 0 },         /* Read */
-       { 0, 1, 0, 0 },         /* Readdir */
-       { 0, 1, 0, 0 },         /* ReadLink */
-       { 0, 2, 1, 1 },         /* Remove */
-       { 2, 1, 1, 1 },         /* Rename */
-       { 0, 0, 0, 0 },         /* Renew */
-       { 0, 0, 0, 0 },         /* RestoreFH */
-       { 0, 1, 0, 0 },         /* SaveFH */
-       { 0, 1, 0, 0 },         /* SecInfo */
-       { 0, 2, 1, 1 },         /* Setattr */
-       { 0, 0, 0, 0 },         /* SetClientID */
-       { 0, 0, 0, 0 },         /* SetClientIDConfirm */
-       { 0, 1, 0, 0 },         /* Verify */
-       { 0, 2, 1, 1 },         /* Write */
-       { 0, 0, 0, 0 },         /* ReleaseLockOwner */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* undef */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* undef */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* undef */
+       { 0, 1, 0, 0, LK_SHARED },              /* Access */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* Close */
+       { 0, 2, 0, 1, LK_EXCLUSIVE },           /* Commit */
+       { 1, 2, 1, 1, LK_EXCLUSIVE },           /* Create */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* Delegpurge */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* Delegreturn */
+       { 0, 1, 0, 0, LK_SHARED },              /* Getattr */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* GetFH */
+       { 2, 1, 1, 1, LK_EXCLUSIVE },           /* Link */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* Lock */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* LockT */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* LockU */
+       { 1, 1, 0, 0, LK_EXCLUSIVE },           /* Lookup */
+       { 1, 1, 0, 0, LK_EXCLUSIVE },           /* Lookupp */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* NVerify */
+       { 1, 1, 0, 1, LK_EXCLUSIVE },           /* Open */
+       { 1, 1, 0, 0, LK_EXCLUSIVE },           /* OpenAttr */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* OpenConfirm */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* OpenDowngrade */
+       { 1, 0, 0, 0, LK_EXCLUSIVE },           /* PutFH */
+       { 1, 0, 0, 0, LK_EXCLUSIVE },           /* PutPubFH */
+       { 1, 0, 0, 0, LK_EXCLUSIVE },           /* PutRootFH */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* Read */
+       { 0, 1, 0, 0, LK_SHARED },              /* Readdir */
+       { 0, 1, 0, 0, LK_SHARED },              /* ReadLink */
+       { 0, 2, 1, 1, LK_EXCLUSIVE },           /* Remove */
+       { 2, 1, 1, 1, LK_EXCLUSIVE },           /* Rename */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* Renew */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* RestoreFH */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* SaveFH */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* SecInfo */
+       { 0, 2, 1, 1, LK_EXCLUSIVE },           /* Setattr */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* SetClientID */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* SetClientIDConfirm */
+       { 0, 1, 0, 0, LK_EXCLUSIVE },           /* Verify */
+       { 0, 2, 1, 1, LK_EXCLUSIVE },           /* Write */
+       { 0, 0, 0, 0, LK_EXCLUSIVE },           /* ReleaseLockOwner */
 };
 #endif /* !APPLEKEXT */
 
@@ -1982,12 +1982,14 @@ nfsv4_fillattr(struct nfsrv_descript *nd
                    !NFSHASNFS4ACL(vnode_mount(vp)))) {
                        NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
                } else if (naclp != NULL) {
-                       NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
-                       error = VOP_ACCESS(vp, VREAD_ACL, cred, p);
-                       if (error == 0)
-                               error = VOP_GETACL(vp, ACL_TYPE_NFS4, naclp,
-                                   cred, p);
-                       NFSVOPUNLOCK(vp, 0, p);
+                       if (vn_lock(vp, LK_SHARED) == 0) {
+                               error = VOP_ACCESS(vp, VREAD_ACL, cred, p);
+                               if (error == 0)
+                                       error = VOP_GETACL(vp, ACL_TYPE_NFS4,
+                                           naclp, cred, p);
+                               VOP_UNLOCK(vp, 0);
+                       } else
+                               error = NFSERR_PERM;
                        if (error != 0) {
                                if (reterr) {
                                        nd->nd_repstat = NFSERR_ACCES;

Modified: head/sys/fs/nfs/nfs_var.h
==============================================================================
--- head/sys/fs/nfs/nfs_var.h   Sat Dec 25 21:26:56 2010        (r216699)
+++ head/sys/fs/nfs/nfs_var.h   Sat Dec 25 21:56:25 2010        (r216700)
@@ -279,7 +279,7 @@ int nfscl_request(struct nfsrv_descript 
 void nfsm_stateidtom(struct nfsrv_descript *, nfsv4stateid_t *, int);
 
 /* nfs_nfsdsubs.c */
-void nfsd_fhtovp(struct nfsrv_descript *, struct nfsrvfh *,
+void nfsd_fhtovp(struct nfsrv_descript *, struct nfsrvfh *, int,
     vnode_t *, struct nfsexstuff *,
     mount_t *, int, NFSPROC_T *);
 int nfsd_excred(struct nfsrv_descript *, struct nfsexstuff *, struct ucred *);
@@ -564,7 +564,7 @@ int nfsv4_sattr(struct nfsrv_descript *,
     NFSACL_T *, NFSPROC_T *);
 int nfsvno_checkexp(mount_t, NFSSOCKADDR_T, struct nfsexstuff *,
     struct ucred **);
-int nfsvno_fhtovp(mount_t, fhandle_t *, NFSSOCKADDR_T,
+int nfsvno_fhtovp(mount_t, fhandle_t *, NFSSOCKADDR_T, int,
     vnode_t *, struct nfsexstuff *, struct ucred **);
 int nfsvno_pathconf(vnode_t, int, register_t *, struct ucred *,
     NFSPROC_T *);

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c        Sat Dec 25 21:26:56 2010        
(r216699)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c        Sat Dec 25 21:56:25 2010        
(r216700)
@@ -180,7 +180,7 @@ nfsvno_accchk(struct vnode *vp, accmode_
                        return (ETXTBSY);
        }
        if (vpislocked == 0)
-               NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
+               vn_lock(vp, LK_SHARED | LK_RETRY);
 
        /*
         * Should the override still be applied when ACLs are enabled?
@@ -218,7 +218,7 @@ nfsvno_accchk(struct vnode *vp, accmode_
                }
        }
        if (vpislocked == 0)
-               NFSVOPUNLOCK(vp, 0, p);
+               VOP_UNLOCK(vp, 0);
        return (error);
 }
 
@@ -1916,7 +1916,7 @@ again:
                                if (refp == NULL) {
                                        if (usevget)
                                                r = VFS_VGET(vp->v_mount,
-                                                   dp->d_fileno, LK_EXCLUSIVE,
+                                                   dp->d_fileno, LK_SHARED,
                                                    &nvp);
                                        else
                                                r = EOPNOTSUPP;
@@ -1925,7 +1925,7 @@ again:
                                                        usevget = 0;
                                                        cn.cn_nameiop = LOOKUP;
                                                        cn.cn_lkflags =
-                                                           LK_EXCLUSIVE |
+                                                           LK_SHARED |
                                                            LK_RETRY;
                                                        cn.cn_cred =
                                                            nd->nd_cred;
@@ -1941,7 +1941,7 @@ again:
                                                    dp->d_name[1] == '.')
                                                        cn.cn_flags |=
                                                            ISDOTDOT;
-                                               if (vn_lock(vp, LK_EXCLUSIVE)
+                                               if (vn_lock(vp, LK_SHARED)
                                                    != 0) {
                                                        nd->nd_repstat = EPERM;
                                                        break;
@@ -2454,7 +2454,8 @@ nfsvno_checkexp(struct mount *mp, struct
  */
 int
 nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
-    struct vnode **vpp, struct nfsexstuff *exp, struct ucred **credp)
+    int lktype, struct vnode **vpp, struct nfsexstuff *exp,
+    struct ucred **credp)
 {
        int i, error, *secflavors;
 
@@ -2481,6 +2482,13 @@ nfsvno_fhtovp(struct mount *mp, fhandle_
                                exp->nes_secflavors[i] = secflavors[i];
                }
        }
+       if (error == 0 && lktype == LK_SHARED)
+               /*
+                * It would be much better to pass lktype to VFS_FHTOVP(),
+                * but this will have to do until VFS_FHTOVP() has a lock
+                * type argument like VFS_VGET().
+                */
+               vn_lock(*vpp, LK_DOWNGRADE | LK_RETRY);
        return (error);
 }
 
@@ -2518,7 +2526,7 @@ nfsvno_pathconf(struct vnode *vp, int fl
  *       call VFS_LOCK_GIANT()
  */
 void
-nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp,
+nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
     struct vnode **vpp, struct nfsexstuff *exp,
     struct mount **mpp, int startwrite, struct thread *p)
 {
@@ -2555,7 +2563,7 @@ nfsd_fhtovp(struct nfsrv_descript *nd, s
        if (startwrite)
                vn_start_write(NULL, mpp, V_WAIT);
 
-       nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, vpp, exp,
+       nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, lktype, vpp, exp,
            &credanon);
 
        /*

Modified: head/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdserv.c        Sat Dec 25 21:26:56 2010        
(r216699)
+++ head/sys/fs/nfsserver/nfs_nfsdserv.c        Sat Dec 25 21:56:25 2010        
(r216700)
@@ -1392,7 +1392,7 @@ nfsrvd_rename(struct nfsrv_descript *nd,
                nd->nd_cred->cr_uid = nd->nd_saveduid;
                /* Won't lock vfs if already locked, mp == NULL */
                tnes.nes_vfslocked = exp->nes_vfslocked;
-               nfsd_fhtovp(nd, &tfh, &tdp, &tnes, &mp, 0, p);
+               nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, &mp, 0, p);
                if (tdp) {
                        tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
                            p, 1);
@@ -1546,7 +1546,8 @@ nfsrvd_link(struct nfsrv_descript *nd, i
                        }
                        /* Won't lock vfs if already locked, mp == NULL */
                        tnes.nes_vfslocked = exp->nes_vfslocked;
-                       nfsd_fhtovp(nd, &dfh, &dp, &tnes, &mp, 0, p);
+                       nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, &mp, 0,
+                           p);
                        if (dp)
                                NFSVOPUNLOCK(dp, 0, p);
                }
@@ -3141,7 +3142,7 @@ nfsrvd_secinfo(struct nfsrv_descript *nd
        vput(vp);
        savflag = nd->nd_flag;
        if (!nd->nd_repstat) {
-               nfsd_fhtovp(nd, &fh, &vp, &retnes, &mp, 0, p);
+               nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, &mp, 0, p);
                if (vp)
                        vput(vp);
        }

Modified: head/sys/fs/nfsserver/nfs_nfsdsocket.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdsocket.c      Sat Dec 25 21:26:56 2010        
(r216699)
+++ head/sys/fs/nfsserver/nfs_nfsdsocket.c      Sat Dec 25 21:56:25 2010        
(r216700)
@@ -354,7 +354,7 @@ APPLESTATIC void
 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
     NFSPROC_T *p)
 {
-       int error = 0;
+       int error = 0, lktype;
        vnode_t vp;
        mount_t mp = NULL;
        struct nfsrvfh fh;
@@ -380,12 +380,20 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, 
                                nd->nd_repstat = NFSERR_GARBAGE;
                                return;
                        }
+                       if (nd->nd_procnum == NFSPROC_READ ||
+                           nd->nd_procnum == NFSPROC_READDIR ||
+                           nd->nd_procnum == NFSPROC_READLINK ||
+                           nd->nd_procnum == NFSPROC_GETATTR ||
+                           nd->nd_procnum == NFSPROC_ACCESS)
+                               lktype = LK_SHARED;
+                       else
+                               lktype = LK_EXCLUSIVE;
                        nes.nes_vfslocked = 0;
                        if (nd->nd_flag & ND_PUBLOOKUP)
-                               nfsd_fhtovp(nd, &nfs_pubfh, &vp, &nes,
+                               nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
                                    &mp, nfs_writerpc[nd->nd_procnum], p);
                        else
-                               nfsd_fhtovp(nd, &fh, &vp, &nes,
+                               nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
                                    &mp, nfs_writerpc[nd->nd_procnum], p);
                        if (nd->nd_repstat == NFSERR_PROGNOTV4)
                                return;
@@ -700,7 +708,7 @@ nfsrvd_compound(struct nfsrv_descript *n
                                goto nfsmout;
                        if (!nd->nd_repstat) {
                                nes.nes_vfslocked = vpnes.nes_vfslocked;
-                               nfsd_fhtovp(nd, &fh, &nvp, &nes, &mp,
+                               nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, &mp,
                                    0, p);
                        }
                        /* For now, allow this for non-export FHs */
@@ -715,7 +723,7 @@ nfsrvd_compound(struct nfsrv_descript *n
                case NFSV4OP_PUTPUBFH:
                        if (nfs_pubfhset) {
                            nes.nes_vfslocked = vpnes.nes_vfslocked;
-                           nfsd_fhtovp(nd, &nfs_pubfh, &nvp,
+                           nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
                                &nes, &mp, 0, p);
                        } else {
                            nd->nd_repstat = NFSERR_NOFILEHANDLE;
@@ -731,7 +739,7 @@ nfsrvd_compound(struct nfsrv_descript *n
                case NFSV4OP_PUTROOTFH:
                        if (nfs_rootfhset) {
                                nes.nes_vfslocked = vpnes.nes_vfslocked;
-                               nfsd_fhtovp(nd, &nfs_rootfh, &nvp,
+                               nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
                                    &nes, &mp, 0, p);
                                if (!nd->nd_repstat) {
                                        if (vp)
@@ -907,24 +915,28 @@ nfsrvd_compound(struct nfsrv_descript *n
                        if (nfsv4_opflag[op].retfh != 0)
                                panic("nfsrvd_compound");
                        if (nfsv4_opflag[op].needscfh) {
-                               if (vp) {
-                                       VREF(vp);
-                                       if (nfsv4_opflag[op].modifyfs)
-                                               NFS_STARTWRITE(NULL, &mp);
-                                       NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, 
p);
-                               } else {
+                               if (vp != NULL) {
+                                       if (vn_lock(vp, nfsv4_opflag[op].lktype)
+                                           != 0)
+                                               nd->nd_repstat = NFSERR_PERM;
+                               } else
                                        nd->nd_repstat = NFSERR_NOFILEHANDLE;
+                               if (nd->nd_repstat != 0) {
                                        if (op == NFSV4OP_SETATTR) {
-                                           /*
-                                            * Setattr reply requires a bitmap
-                                            * even for errors like these.
-                                            */
-                                           NFSM_BUILD(tl, u_int32_t *,
-                                               NFSX_UNSIGNED);
-                                           *tl = 0;
+                                               /*
+                                                * Setattr reply requires a
+                                                * bitmap even for errors like
+                                                * these.
+                                                */
+                                               NFSM_BUILD(tl, u_int32_t *,
+                                                   NFSX_UNSIGNED);
+                                               *tl = 0;
                                        }
                                        break;
                                }
+                               VREF(vp);
+                               if (nfsv4_opflag[op].modifyfs)
+                                       NFS_STARTWRITE(NULL, &mp);
                                error = (*(nfsrv4_ops0[op]))(nd, isdgram, vp,
                                    p, &vpnes);
                                if (nfsv4_opflag[op].modifyfs)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to