Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Aug 2010 23:41:40 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r211854 - head/sys/nfsserver
Message-ID:  <201008262341.o7QNfeR2057181@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Thu Aug 26 23:41:40 2010
New Revision: 211854
URL: http://svn.freebsd.org/changeset/base/211854

Log:
  - When VFS_VGET() is not supported, switch to VOP_LOOKUP().
  - We are fine by only share-locking the vnode.
  - Remove assertion that doesn't hold for ZFS where we cross mount points
    boundaries by going into .zfs/snapshot/<name>/.
  
  Reviewed by:	rmacklem
  MFC after:	1 month

Modified:
  head/sys/nfsserver/nfs_serv.c

Modified: head/sys/nfsserver/nfs_serv.c
==============================================================================
--- head/sys/nfsserver/nfs_serv.c	Thu Aug 26 23:33:04 2010	(r211853)
+++ head/sys/nfsserver/nfs_serv.c	Thu Aug 26 23:41:40 2010	(r211854)
@@ -3041,7 +3041,8 @@ nfsrv_readdirplus(struct nfsrv_descript 
 	u_quad_t off, toff, verf;
 	u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
 	int v3 = (nfsd->nd_flag & ND_NFSV3);
-	int vfslocked;
+	int usevget = 1, vfslocked;
+	struct componentname cn;
 
 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 	vfslocked = 0;
@@ -3186,28 +3187,6 @@ again:
 		goto again;
 	}
 
-	/*
-	 * Probe one of the directory entries to see if the filesystem
-	 * supports VGET.
-	 */
-	error = VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp);
-	if (error) {
-		if (error == EOPNOTSUPP)
-			error = NFSERR_NOTSUPP;
-		else
-			error = NFSERR_SERVERFAULT;
-		vrele(vp);
-		vp = NULL;
-		free((caddr_t)cookies, M_TEMP);
-		free((caddr_t)rbuf, M_TEMP);
-		nfsm_reply(NFSX_V3POSTOPATTR);
-		nfsm_srvpostop_attr(getret, &at);
-		error = 0;
-		goto nfsmout;
-	}
-	vput(nvp);
-	nvp = NULL;
-
 	dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
 	    2 * NFSX_UNSIGNED;
 	nfsm_reply(cnt);
@@ -3224,23 +3203,49 @@ again:
 			nlen = dp->d_namlen;
 			rem = nfsm_rndup(nlen)-nlen;
 
-			/*
-			 * For readdir_and_lookup get the vnode using
-			 * the file number.
-			 */
-			if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE,
-			    &nvp))
-				goto invalid;
+			if (usevget) {
+				/*
+				 * For readdir_and_lookup get the vnode using
+				 * the file number.
+				 */
+				error = VFS_VGET(vp->v_mount, dp->d_fileno,
+				    LK_SHARED, &nvp);
+				if (error != 0 && error != EOPNOTSUPP) {
+					error = 0;
+					goto invalid;
+				} else if (error == EOPNOTSUPP) {
+					/*
+					 * VFS_VGET() not supported?
+					 * Let's switch to VOP_LOOKUP().
+					 */
+					error = 0;
+					usevget = 0;
+					cn.cn_nameiop = LOOKUP;
+					cn.cn_flags = ISLASTCN | NOFOLLOW | \
+					    LOCKSHARED | LOCKLEAF | MPSAFE;
+					cn.cn_lkflags = LK_SHARED | LK_RETRY;
+					cn.cn_cred = cred;
+					cn.cn_thread = curthread;
+				}
+			}
+			if (!usevget) {
+				cn.cn_nameptr = dp->d_name;
+				cn.cn_namelen = dp->d_namlen;
+				if (dp->d_namlen == 2 &&
+				    dp->d_name[0] == '.' &&
+				    dp->d_name[1] == '.') {
+					cn.cn_flags |= ISDOTDOT;
+				} else {
+					cn.cn_flags &= ~ISDOTDOT;
+				}
+				if (!VOP_ISLOCKED(vp))
+					vn_lock(vp, LK_SHARED | LK_RETRY);
+				if (VOP_LOOKUP(vp, &nvp, &cn) != 0)
+					goto invalid;
+			}
+
 			bzero((caddr_t)nfhp, NFSX_V3FH);
-			nfhp->fh_fsid =
-				nvp->v_mount->mnt_stat.f_fsid;
-			/*
-			 * XXXRW: Assert the mountpoints are the same so that
-			 * we know that acquiring Giant based on the
-			 * directory is the right thing for the child.
-			 */
-			KASSERT(nvp->v_mount == vp->v_mount,
-			    ("nfsrv_readdirplus: nvp mount != vp mount"));
+			nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid;
 			if (VOP_VPTOFH(nvp, &nfhp->fh_fid)) {
 				vput(nvp);
 				nvp = NULL;
@@ -3336,7 +3341,10 @@ invalid:
 		cookiep++;
 		ncookies--;
 	}
-	vrele(vp);
+	if (!usevget && VOP_ISLOCKED(vp))
+		vput(vp);
+	else
+		vrele(vp);
 	vp = NULL;
 	nfsm_clget;
 	*tl = nfsrv_nfs_false;



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