svn commit: r189973 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb fs/udf

John Baldwin jhb at FreeBSD.org
Wed Mar 18 11:25:58 PDT 2009


Author: jhb
Date: Wed Mar 18 18:25:56 2009
New Revision: 189973
URL: http://svn.freebsd.org/changeset/base/189973

Log:
  MFC: Mark udf(4) MPSAFE and add support for using shared vnode locks for
  pathname lookups.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/fs/udf/udf_vfsops.c
  stable/7/sys/fs/udf/udf_vnops.c

Modified: stable/7/sys/fs/udf/udf_vfsops.c
==============================================================================
--- stable/7/sys/fs/udf/udf_vfsops.c	Wed Mar 18 18:20:20 2009	(r189972)
+++ stable/7/sys/fs/udf/udf_vfsops.c	Wed Mar 18 18:25:56 2009	(r189973)
@@ -344,6 +344,7 @@ udf_mountfs(struct vnode *devvp, struct 
 	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
 	MNT_ILOCK(mp);
 	mp->mnt_flag |= MNT_LOCAL;
+	mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED;
 	MNT_IUNLOCK(mp);
 	udfmp->im_mountp = mp;
 	udfmp->im_dev = devvp->v_rdev;
@@ -546,22 +547,13 @@ static int
 udf_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td)
 {
 	struct udf_mnt *udfmp;
-	struct vnode *vp;
 	ino_t id;
-	int error;
 
 	udfmp = VFSTOUDFFS(mp);
 
 	id = udf_getid(&udfmp->root_icb);
 
-	error = udf_vget(mp, id, LK_EXCLUSIVE, vpp);
-	if (error)
-		return error;
-
-	vp = *vpp;
-	vp->v_vflag |= VV_ROOT;
-
-	return (0);
+	return (udf_vget(mp, id, flags, vpp));
 }
 
 static int
@@ -597,6 +589,22 @@ udf_vget(struct mount *mp, ino_t ino, in
 	if (error || *vpp != NULL)
 		return (error);
 
+	/*
+	 * We must promote to an exclusive lock for vnode creation.  This
+	 * can happen if lookup is passed LOCKSHARED.
+ 	 */
+	if ((flags & LK_TYPE_MASK) == LK_SHARED) {
+		flags &= ~LK_TYPE_MASK;
+		flags |= LK_EXCLUSIVE;
+	}
+
+	/*
+	 * We do not lock vnode creation as it is believed to be too
+	 * expensive for such rare case as simultaneous creation of vnode
+	 * for same ino by different processes. We just allow them to race
+	 * and check later to decide who wins. Let the race begin!
+	 */
+
 	td = curthread;
 	udfmp = VFSTOUDFFS(mp);
 
@@ -690,6 +698,13 @@ udf_vget(struct mount *mp, ino_t ino, in
 		vp->v_type = VLNK;
 		break;
 	}
+
+	if (vp->v_type != VFIFO)
+		VN_LOCK_ASHARE(vp);
+
+	if (ino == udf_getid(&udfmp->root_icb))
+		vp->v_vflag |= VV_ROOT;
+
 	*vpp = vp;
 
 	return (0);

Modified: stable/7/sys/fs/udf/udf_vnops.c
==============================================================================
--- stable/7/sys/fs/udf/udf_vnops.c	Wed Mar 18 18:20:20 2009	(r189972)
+++ stable/7/sys/fs/udf/udf_vnops.c	Wed Mar 18 18:25:56 2009	(r189973)
@@ -1056,13 +1056,14 @@ udf_lookup(struct vop_cachedlookup_args 
 	long namelen;
 	ino_t id = 0;
 	int offset, error = 0;
-	int numdirpasses, fsize;
+	int fsize, lkflags, ltype, numdirpasses;
 
 	dvp = a->a_dvp;
 	node = VTON(dvp);
 	udfmp = node->udfmp;
 	nameiop = a->a_cnp->cn_nameiop;
 	flags = a->a_cnp->cn_flags;
+	lkflags = a->a_cnp->cn_lkflags;
 	nameptr = a->a_cnp->cn_nameptr;
 	namelen = a->a_cnp->cn_namelen;
 	fsize = le64toh(node->fentry->inf_len);
@@ -1124,20 +1125,36 @@ lookloop:
 
 	/* Did we have a match? */
 	if (id) {
-		if (flags & ISDOTDOT)
-			VOP_UNLOCK(dvp, 0, a->a_cnp->cn_thread);
-		error = udf_vget(udfmp->im_mountp, id, LK_EXCLUSIVE, &tdp);
-		if (flags & ISDOTDOT)
-			vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY, a->a_cnp->cn_thread);
-		if (!error) {
+		/*
+		 * Remember where this entry was if it's the final
+		 * component.
+		 */
+		if ((flags & ISLASTCN) && nameiop == LOOKUP)
+			node->diroff = ds->offset + ds->off;
+		if (numdirpasses == 2)
+			nchstats.ncs_pass2++;
+		udf_closedir(ds);
+
+		if (flags & ISDOTDOT) {
+			error = vn_vget_ino(dvp, id, lkflags, &tdp);
+		} else if (node->hash_id == id) {
+			VREF(dvp);	/* we want ourself, ie "." */
 			/*
-			 * Remember where this entry was if it's the final
-			 * component.
+			 * When we lookup "." we still can be asked to lock it
+			 * differently.
 			 */
-			if ((flags & ISLASTCN) && nameiop == LOOKUP)
-				node->diroff = ds->offset + ds->off;
-			if (numdirpasses == 2)
-				nchstats.ncs_pass2++;
+			ltype = lkflags & LK_TYPE_MASK;
+			if (ltype != VOP_ISLOCKED(dvp, td)) {
+				if (ltype == LK_EXCLUSIVE)
+					vn_lock(dvp, LK_UPGRADE | LK_RETRY, td);
+				else /* if (ltype == LK_SHARED) */
+					vn_lock(dvp, LK_DOWNGRADE | LK_RETRY,
+					    td);
+			}
+			tdp = dvp;
+		} else
+			error = udf_vget(udfmp->im_mountp, id, lkflags, &tdp);
+		if (!error) {
 			*vpp = tdp;
 			/* Put this entry in the cache */
 			if (flags & MAKEENTRY)
@@ -1151,6 +1168,7 @@ lookloop:
 			udf_closedir(ds);
 			goto lookloop;
 		}
+		udf_closedir(ds);
 
 		/* Enter name into cache as non-existant */
 		if (flags & MAKEENTRY)
@@ -1164,7 +1182,6 @@ lookloop:
 		}
 	}
 
-	udf_closedir(ds);
 	return (error);
 }
 


More information about the svn-src-all mailing list