svn commit: r189696 - in head/sys: cddl/contrib/opensolaris/uts/common/fs/zfs dev/md fs/cd9660 fs/udf kern sys ufs/ffs

John Baldwin jhb at FreeBSD.org
Wed Mar 11 07:13:48 PDT 2009


Author: jhb
Date: Wed Mar 11 14:13:47 2009
New Revision: 189696
URL: http://svn.freebsd.org/changeset/base/189696

Log:
  Add a new internal mount flag (MNTK_EXTENDED_SHARED) to indicate that a
  filesystem supports additional operations using shared vnode locks.
  Currently this is used to enable shared locks for open() and close() of
  read-only file descriptors.
  - When an ISOPEN namei() request is performed with LOCKSHARED, use a
    shared vnode lock for the leaf vnode only if the mount point has the
    extended shared flag set.
  - Set LOCKSHARED in vn_open_cred() for requests that specify O_RDONLY but
    not O_CREAT.
  - Use a shared vnode lock around VOP_CLOSE() if the file was opened with
    O_RDONLY and the mountpoint has the extended shared flag set.
  - Adjust md(4) to upgrade the vnode lock on the vnode it gets back from
    vn_open() since it now may only have a shared vnode lock.
  - Don't enable shared vnode locks on FIFO vnodes in ZFS and UFS since
    FIFO's require exclusive vnode locks for their open() and close()
    routines.  (My recent MPSAFE patches for UDF and cd9660 already included
    this change.)
  - Enable extended shared operations on UFS, cd9660, and UDF.
  
  Submitted by:	ups
  Reviewed by:	pjd (ZFS bits)
  MFC after:	1 month

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
  head/sys/dev/md/md.c
  head/sys/fs/cd9660/cd9660_vfsops.c
  head/sys/fs/udf/udf_vfsops.c
  head/sys/kern/vfs_lookup.c
  head/sys/kern/vfs_vnops.c
  head/sys/kern/vnode_if.src
  head/sys/sys/mount.h
  head/sys/ufs/ffs/ffs_vfsops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Wed Mar 11 14:13:47 2009	(r189696)
@@ -153,7 +153,6 @@ zfs_znode_cache_constructor(void *buf, v
 	zp->z_vnode = vp;
 	vp->v_data = (caddr_t)zp;
 	VN_LOCK_AREC(vp);
-	VN_LOCK_ASHARE(vp);
 
 	list_link_init(&zp->z_link_node);
 
@@ -610,6 +609,8 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_bu
 		vp->v_op = &zfs_fifoops;
 		break;
 	}
+	if (vp->v_type != VFIFO)
+		VN_LOCK_ASHARE(vp);
 
 	mutex_enter(&zfsvfs->z_znodes_lock);
 	list_insert_tail(&zfsvfs->z_all_znodes, zp);
@@ -1491,6 +1492,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, 
 
 	vp = ZTOV(rootzp);
 	vp->v_type = VDIR;
+	VN_LOCK_ASHARE(vp);
 
 	bzero(&zfsvfs, sizeof (zfsvfs_t));
 

Modified: head/sys/dev/md/md.c
==============================================================================
--- head/sys/dev/md/md.c	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/dev/md/md.c	Wed Mar 11 14:13:47 2009	(r189696)
@@ -924,12 +924,20 @@ mdcreate_vnode(struct md_s *sc, struct m
 		return (error);
 	vfslocked = NDHASGIANT(&nd);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
-	if (nd.ni_vp->v_type != VREG ||
-	    (error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred))) {
-		VOP_UNLOCK(nd.ni_vp, 0);
-		(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
-		VFS_UNLOCK_GIANT(vfslocked);
-		return (error ? error : EINVAL);
+	if (nd.ni_vp->v_type != VREG) {
+		error = EINVAL;
+		goto bad;
+	}	
+	error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred);
+	if (error != 0)
+		goto bad;
+	if (VOP_ISLOCKED(nd.ni_vp) != LK_EXCLUSIVE) {
+		vn_lock(nd.ni_vp, LK_UPGRADE | LK_RETRY);
+		if (nd.ni_vp->v_iflag & VI_DOOMED) {
+			/* Forced unmount. */
+			error = EBADF;
+			goto bad;
+		}
 	}
 	nd.ni_vp->v_vflag |= VV_MD;
 	VOP_UNLOCK(nd.ni_vp, 0);
@@ -948,13 +956,15 @@ mdcreate_vnode(struct md_s *sc, struct m
 		sc->vnode = NULL;
 		vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY);
 		nd.ni_vp->v_vflag &= ~VV_MD;
-		VOP_UNLOCK(nd.ni_vp, 0);
-		(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
-		VFS_UNLOCK_GIANT(vfslocked);
-		return (error);
+		goto bad;
 	}
 	VFS_UNLOCK_GIANT(vfslocked);
 	return (0);
+bad:
+	VOP_UNLOCK(nd.ni_vp, 0);
+	(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
+	VFS_UNLOCK_GIANT(vfslocked);
+	return (error);
 }
 
 static int

Modified: head/sys/fs/cd9660/cd9660_vfsops.c
==============================================================================
--- head/sys/fs/cd9660/cd9660_vfsops.c	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/fs/cd9660/cd9660_vfsops.c	Wed Mar 11 14:13:47 2009	(r189696)
@@ -371,7 +371,8 @@ iso_mountfs(devvp, mp)
 	mp->mnt_maxsymlinklen = 0;
 	MNT_ILOCK(mp);
 	mp->mnt_flag |= MNT_LOCAL;
-	mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED;
+	mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
+	    MNTK_EXTENDED_SHARED;
 	MNT_IUNLOCK(mp);
 	isomp->im_mountp = mp;
 	isomp->im_dev = dev;

Modified: head/sys/fs/udf/udf_vfsops.c
==============================================================================
--- head/sys/fs/udf/udf_vfsops.c	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/fs/udf/udf_vfsops.c	Wed Mar 11 14:13:47 2009	(r189696)
@@ -353,7 +353,8 @@ 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;
+	mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
+	    MNTK_EXTENDED_SHARED;
 	MNT_IUNLOCK(mp);
 	udfmp->im_mountp = mp;
 	udfmp->im_dev = dev;

Modified: head/sys/kern/vfs_lookup.c
==============================================================================
--- head/sys/kern/vfs_lookup.c	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/kern/vfs_lookup.c	Wed Mar 11 14:13:47 2009	(r189696)
@@ -353,6 +353,41 @@ compute_cn_lkflags(struct mount *mp, int
 	return (lkflags);
 }
 
+static __inline int
+needs_exclusive_leaf(struct mount *mp, int flags)
+{
+
+	/*
+	 * Intermediate nodes can use shared locks, we only need to
+	 * force an exclusive lock for leaf nodes.
+	 */
+	if ((flags & (ISLASTCN | LOCKLEAF)) != (ISLASTCN | LOCKLEAF))
+		return (0);
+
+	/* Always use exclusive locks if LOCKSHARED isn't set. */
+	if (!(flags & LOCKSHARED))
+		return (1);
+
+	/*
+	 * For lookups during open(), if the mount point supports
+	 * extended shared operations, then use a shared lock for the
+	 * leaf node, otherwise use an exclusive lock.
+	 */
+	if (flags & ISOPEN) {
+		if (mp != NULL &&
+		    (mp->mnt_kern_flag & MNTK_EXTENDED_SHARED))
+			return (0);
+		else
+			return (1);
+	}
+
+	/*
+	 * Lookup requests outside of open() that specify LOCKSHARED
+	 * only need a shared lock on the leaf vnode.
+	 */
+	return (1);
+}
+
 /*
  * Search a pathname.
  * This is a very central and rather complicated routine.
@@ -610,8 +645,7 @@ unionlookup:
 	 * If we're looking up the last component and we need an exclusive
 	 * lock, adjust our lkflags.
 	 */
-	if ((cnp->cn_flags & (ISLASTCN|LOCKSHARED|LOCKLEAF)) ==
-	    (ISLASTCN|LOCKLEAF))
+	if (needs_exclusive_leaf(dp->v_mount, cnp->cn_flags))
 		cnp->cn_lkflags = LK_EXCLUSIVE;
 #ifdef NAMEI_DIAGNOSTIC
 	vprint("lookup in", dp);
@@ -811,8 +845,8 @@ success:
 	 * Because of lookup_shared we may have the vnode shared locked, but
 	 * the caller may want it to be exclusively locked.
 	 */
-	if ((cnp->cn_flags & (ISLASTCN | LOCKSHARED | LOCKLEAF)) ==
-	    (ISLASTCN | LOCKLEAF) && VOP_ISLOCKED(dp) != LK_EXCLUSIVE) {
+	if (needs_exclusive_leaf(dp->v_mount, cnp->cn_flags) &&
+	    VOP_ISLOCKED(dp) != LK_EXCLUSIVE) {
 		vn_lock(dp, LK_UPGRADE | LK_RETRY);
 		if (dp->v_iflag & VI_DOOMED) {
 			error = ENOENT;

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/kern/vfs_vnops.c	Wed Mar 11 14:13:47 2009	(r189696)
@@ -188,6 +188,8 @@ restart:
 		ndp->ni_cnd.cn_flags = ISOPEN |
 		    ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) |
 		    LOCKLEAF | MPSAFE | AUDITVNODE1;
+		if (!(fmode & FWRITE))
+			ndp->ni_cnd.cn_flags |= LOCKSHARED;
 		if ((error = namei(ndp)) != 0)
 			return (error);
 		if (!mpsafe)
@@ -240,7 +242,7 @@ restart:
 	if (fmode & FWRITE)
 		vp->v_writecount++;
 	*flagp = fmode;
-	ASSERT_VOP_ELOCKED(vp, "vn_open_cred");
+	ASSERT_VOP_LOCKED(vp, "vn_open_cred");
 	if (!mpsafe)
 		VFS_UNLOCK_GIANT(vfslocked);
 	return (0);
@@ -285,12 +287,18 @@ vn_close(vp, flags, file_cred, td)
 	struct thread *td;
 {
 	struct mount *mp;
-	int error;
+	int error, lock_flags;
+
+	if (!(flags & FWRITE) && vp->v_mount != NULL &&
+	    vp->v_mount->mnt_kern_flag & MNTK_EXTENDED_SHARED)
+		lock_flags = LK_SHARED;
+	else
+		lock_flags = LK_EXCLUSIVE;
 
 	VFS_ASSERT_GIANT(vp->v_mount);
 
 	vn_start_write(vp, &mp, V_WAIT);
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	vn_lock(vp, lock_flags | LK_RETRY);
 	if (flags & FWRITE) {
 		VNASSERT(vp->v_writecount > 0, vp, 
 		    ("vn_close: negative writecount"));

Modified: head/sys/kern/vnode_if.src
==============================================================================
--- head/sys/kern/vnode_if.src	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/kern/vnode_if.src	Wed Mar 11 14:13:47 2009	(r189696)
@@ -133,7 +133,7 @@ vop_open {
 };
 
 
-%% close	vp	E E E
+%% close	vp	L L L
 
 vop_close {
 	IN struct vnode *vp;

Modified: head/sys/sys/mount.h
==============================================================================
--- head/sys/sys/mount.h	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/sys/mount.h	Wed Mar 11 14:13:47 2009	(r189696)
@@ -324,14 +324,15 @@ void          __mnt_vnode_markerfree(str
 #define MNTK_NOINSMNTQ	0x00000008	/* insmntque is not allowed */
 #define	MNTK_DRAINING	0x00000010	/* lock draining is happening */
 #define	MNTK_REFEXPIRE	0x00000020	/* refcount expiring is happening */
+#define MNTK_EXTENDED_SHARED	0x00000040 /* Allow shared locking for more ops */
 #define MNTK_UNMOUNT	0x01000000	/* unmount in progress */
 #define	MNTK_MWAIT	0x02000000	/* waiting for unmount to finish */
 #define	MNTK_SUSPEND	0x08000000	/* request write suspension */
 #define	MNTK_SUSPEND2	0x04000000	/* block secondary writes */
 #define	MNTK_SUSPENDED	0x10000000	/* write operations are suspended */
 #define	MNTK_MPSAFE	0x20000000	/* Filesystem is MPSAFE. */
-#define	MNTK_NOKNOTE	0x80000000	/* Don't send KNOTEs from VOP hooks */
 #define MNTK_LOOKUP_SHARED	0x40000000 /* FS supports shared lock lookups */
+#define	MNTK_NOKNOTE	0x80000000	/* Don't send KNOTEs from VOP hooks */
 
 /*
  * Sysctl CTL_VFS definitions.

Modified: head/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vfsops.c	Wed Mar 11 13:15:42 2009	(r189695)
+++ head/sys/ufs/ffs/ffs_vfsops.c	Wed Mar 11 14:13:47 2009	(r189696)
@@ -883,7 +883,8 @@ ffs_mountfs(devvp, mp, td)
 	 * Initialize filesystem stat information in mount struct.
 	 */
 	MNT_ILOCK(mp);
-	mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED;
+	mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
+	    MNTK_EXTENDED_SHARED;
 	MNT_IUNLOCK(mp);
 #ifdef UFS_EXTATTR
 #ifdef UFS_EXTATTR_AUTOSTART
@@ -1440,10 +1441,9 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags
 		return (error);
 	}
 	/*
-	 * FFS supports recursive and shared locking.
+	 * FFS supports recursive locking.
 	 */
 	VN_LOCK_AREC(vp);
-	VN_LOCK_ASHARE(vp);
 	vp->v_data = ip;
 	vp->v_bufobj.bo_bsize = fs->fs_bsize;
 	ip->i_vnode = vp;
@@ -1516,6 +1516,10 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags
 	/*
 	 * Finish inode initialization.
 	 */
+	if (vp->v_type != VFIFO) {
+		/* FFS supports shared locking for all files except fifos. */
+		VN_LOCK_ASHARE(vp);
+	}
 
 	/*
 	 * Set up a generation number for this inode if it does not


More information about the svn-src-all mailing list