summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c4
-rw-r--r--sys/dev/md/md.c30
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c3
-rw-r--r--sys/fs/udf/udf_vfsops.c3
-rw-r--r--sys/kern/vfs_lookup.c42
-rw-r--r--sys/kern/vfs_vnops.c14
-rw-r--r--sys/kern/vnode_if.src2
-rw-r--r--sys/sys/mount.h3
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c10
9 files changed, 86 insertions, 25 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
index 5687522..a6172f8 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
@@ -153,7 +153,6 @@ zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
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_buf_t *db, int blksz)
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, nvlist_t *zplprops, dmu_tx_t *tx)
vp = ZTOV(rootzp);
vp->v_type = VDIR;
+ VN_LOCK_ASHARE(vp);
bzero(&zfsvfs, sizeof (zfsvfs_t));
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index d3e3da8..48d48fd 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -924,12 +924,20 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
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 md_ioctl *mdio, struct thread *td)
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
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index e6001eb..95a9a23 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -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;
diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c
index 98a2a13..8519a07 100644
--- a/sys/fs/udf/udf_vfsops.c
+++ b/sys/fs/udf/udf_vfsops.c
@@ -353,7 +353,8 @@ udf_mountfs(struct vnode *devvp, struct mount *mp)
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;
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index c4840ce..a21af4f 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -353,6 +353,41 @@ compute_cn_lkflags(struct mount *mp, int lkflags)
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;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index e210fee..681c0eb 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -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"));
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index ad4d1f7..0e198bf 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -133,7 +133,7 @@ vop_open {
};
-%% close vp E E E
+%% close vp L L L
vop_close {
IN struct vnode *vp;
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index f83686c..45f21bc 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -324,14 +324,15 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
#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.
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 3913d79..c6de7df 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -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
OpenPOWER on IntegriCloud