diff options
author | mjg <mjg@FreeBSD.org> | 2017-03-16 08:51:30 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2017-03-16 08:51:30 +0000 |
commit | 8ccd06bc3a50430569bde4e69bce65c4ac636189 (patch) | |
tree | 9155665e3546fcd3dde1738fedf30d053aac0769 | |
parent | 63dc841531eff25dfc46cd55a801ecdd671b3cc4 (diff) | |
download | FreeBSD-src-8ccd06bc3a50430569bde4e69bce65c4ac636189.zip FreeBSD-src-8ccd06bc3a50430569bde4e69bce65c4ac636189.tar.gz |
MFC r309425,r312645,r312598,r312621:
vfs: provide fake locking primitives for the crossmp vnode
Since the vnode is only expected to be shared locked, we can save a
little overhead by only pretending we are locking in the first place.
==
Provide fallback VOP methods for crossmp vnode.
In particular, crossmp vnode might leak into rename code.
==
vfs: hide the getvnode NULL mp message behind DIAGNOSTIC
Since crossmp vnode changes the message was being printed on each boot.
==
Improve debugging printf.
-rw-r--r-- | sys/kern/vfs_lookup.c | 64 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 6 |
2 files changed, 64 insertions, 6 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index e8a2c83..88dd715 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -79,6 +79,65 @@ uma_zone_t namei_zone; /* Placeholder vnode for mp traversal. */ static struct vnode *vp_crossmp; +static int +crossmp_vop_islocked(struct vop_islocked_args *ap) +{ + + return (LK_SHARED); +} + +static int +crossmp_vop_lock1(struct vop_lock1_args *ap) +{ + struct vnode *vp; + struct lock *lk; + const char *file; + int flags, line; + + vp = ap->a_vp; + lk = vp->v_vnlock; + flags = ap->a_flags; + file = ap->a_file; + line = ap->a_line; + + if ((flags & LK_SHARED) == 0) + panic("invalid lock request for crossmp"); + + WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER, file, line, + flags & LK_INTERLOCK ? &VI_MTX(vp)->lock_object : NULL); + WITNESS_LOCK(&lk->lock_object, 0, file, line); + if ((flags & LK_INTERLOCK) != 0) + VI_UNLOCK(vp); + LOCK_LOG_LOCK("SLOCK", &lk->lock_object, 0, 0, ap->a_file, line); + return (0); +} + +static int +crossmp_vop_unlock(struct vop_unlock_args *ap) +{ + struct vnode *vp; + struct lock *lk; + int flags; + + vp = ap->a_vp; + lk = vp->v_vnlock; + flags = ap->a_flags; + + if ((flags & LK_INTERLOCK) != 0) + VI_UNLOCK(vp); + WITNESS_UNLOCK(&lk->lock_object, 0, LOCK_FILE, LOCK_LINE); + LOCK_LOG_LOCK("SUNLOCK", &lk->lock_object, 0, 0, LOCK_FILE, + LOCK_LINE); + return (0); +} + +static struct vop_vector crossmp_vnodeops = { + .vop_default = &default_vnodeops, + .vop_islocked = crossmp_vop_islocked, + .vop_lock1 = crossmp_vop_lock1, + .vop_unlock = crossmp_vop_unlock, +}; + struct nameicap_tracker { struct vnode *dp; TAILQ_ENTRY(nameicap_tracker) nm_link; @@ -95,10 +154,7 @@ nameiinit(void *dummy __unused) UMA_ALIGN_PTR, 0); nt_zone = uma_zcreate("rentr", sizeof(struct nameicap_tracker), NULL, NULL, NULL, NULL, sizeof(void *), 0); - getnewvnode("crossmp", NULL, &dead_vnodeops, &vp_crossmp); - vn_lock(vp_crossmp, LK_EXCLUSIVE); - VN_LOCK_ASHARE(vp_crossmp); - VOP_UNLOCK(vp_crossmp, 0); + getnewvnode("crossmp", NULL, &crossmp_vnodeops, &vp_crossmp); } SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nameiinit, NULL); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 9b5fc4a..7efdde6 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1419,12 +1419,14 @@ alloc: vp->v_op = vops; v_init_counters(vp); vp->v_bufobj.bo_ops = &buf_ops_bio; +#ifdef DIAGNOSTIC + if (mp == NULL && vops != &dead_vnodeops) + printf("NULL mp in getnewvnode(9), tag %s\n", tag); +#endif #ifdef MAC mac_vnode_init(vp); if (mp != NULL && (mp->mnt_flag & MNT_MULTILABEL) == 0) mac_vnode_associate_singlelabel(mp, vp); - else if (mp == NULL && vops != &dead_vnodeops) - printf("NULL mp in getnewvnode()\n"); #endif if (mp != NULL) { vp->v_bufobj.bo_bsize = mp->mnt_stat.f_iosize; |