Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Dec 2010 21:56:25 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r216700 - in head/sys/fs: nfs nfsserver
Message-ID:  <201012252156.oBPLuP0o093565@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012252156.oBPLuP0o093565>