Below is the part of the full diff which is adding generic vnode lock
inside struct vnode.
blob - 7df5a5757b90244ab361f0687bd2eabf3e7093c2
blob + 53fb67ace69ada6faf768a6e7b20a48e2b6e9740
--- sys/kern/vfs_default.c
+++ sys/kern/vfs_default.c
@@ -167,6 +167,34 @@ vop_generic_abortop(void *v)
return (0);
}
+int
+vop_generic_lock(void *v)
+{
+ struct vop_lock_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ return rrw_enter(&vp->v_lock, ap->a_flags & LK_RWFLAGS);
+}
+
+int
+vop_generic_unlock(void *v)
+{
+ struct vop_unlock_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ rrw_exit(&vp->v_lock);
+ return 0;
+}
+
+int
+vop_generic_islocked(void *v)
+{
+ struct vop_islocked_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ return rrw_status(&vp->v_lock);
+}
+
const struct filterops generic_filtops = {
.f_flags = FILTEROP_ISFD,
.f_attach = NULL,
blob - 4861468362592c649c579e0f3a47d630a39d051e
blob + 1f7409235f4696765c6b8b22e65d953b1d6e5100
--- sys/kern/vfs_subr.c
+++ sys/kern/vfs_subr.c
@@ -408,6 +408,7 @@ getnewvnode(enum vtagtype tag, struct mount *mp, const
((TAILQ_FIRST(listhd = &vnode_hold_list) == NULL) || toggle))) {
splx(s);
vp = pool_get(&vnode_pool, PR_WAITOK | PR_ZERO);
+ rrw_init_flags(&vp->v_lock, "vnode", RWL_DUPOK | RWL_IS_VNODE);
vp->v_uvm = pool_get(&uvm_vnode_pool, PR_WAITOK | PR_ZERO);
vp->v_uvm->u_vnode = vp;
RBT_INIT(buf_rb_bufs, &vp->v_bufs_tree);
@@ -463,6 +464,10 @@ getnewvnode(enum vtagtype tag, struct mount *mp, const
vp->v_op = vops;
insmntque(vp, mp);
*vpp = vp;
+#ifdef DIAGNOSTIC
+ if (rrw_status(&vp->v_lock) != 0)
+ panic("%s: free vnode %p isn't lock free", __func__, vp);
+#endif
vp->v_usecount = 1;
vp->v_data = 0;
return (0);
blob - 490f3e367cf322eff38ac7a184b7ea49a7cef7fa
blob + 3a9ff1f58d50e005ea9f87c974647d1f56fcb397
--- sys/sys/vnode.h
+++ sys/sys/vnode.h
@@ -102,6 +102,7 @@ struct vnode {
u_int v_uvcount; /* unveil references */
u_int v_writecount; /* reference count of writers */
u_int v_lockcount; /* [V] # threads waiting on lock */
+ struct rrwlock v_lock; /* generic vnode lock */
/* Flags that can be read/written in interrupts */
u_int v_bioflag;
@@ -632,6 +633,9 @@ int vop_generic_bwrite(void *);
int vop_generic_revoke(void *);
int vop_generic_kqfilter(void *);
int vop_generic_lookup(void *);
+int vop_generic_lock(void *);
+int vop_generic_unlock(void *);
+int vop_generic_islocked(void *);
/* vfs_vnops.c */
int vn_isunder(struct vnode *, struct vnode *, struct proc *);