summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-06-10 20:59:32 +0000
committerkib <kib@FreeBSD.org>2009-06-10 20:59:32 +0000
commite1cb2941d4424de90eb68716d6c4d95f4c0af0ba (patch)
tree9c12d3a92805f512ad054e2b8fa5618e0bd9cc71 /sys/kern/vfs_subr.c
parenta9806592196870f6605860715c0edac4deb6a55d (diff)
downloadFreeBSD-src-e1cb2941d4424de90eb68716d6c4d95f4c0af0ba.zip
FreeBSD-src-e1cb2941d4424de90eb68716d6c4d95f4c0af0ba.tar.gz
Adapt vfs kqfilter to the shared vnode lock used by zfs write vop. Use
vnode interlock to protect the knote fields [1]. The locking assumes that shared vnode lock is held, thus we get exclusive access to knote either by exclusive vnode lock protection, or by shared vnode lock + vnode interlock. Do not use kl_locked() method to assert either lock ownership or the fact that curthread does not own the lock. For shared locks, ownership is not recorded, e.g. VOP_ISLOCKED can return LK_SHARED for the shared lock not owned by curthread, causing false positives in kqueue subsystem assertions about knlist lock. Remove kl_locked method from knlist lock vector, and add two separate assertion methods kl_assert_locked and kl_assert_unlocked, that are supposed to use proper asserts. Change knlist_init accordingly. Add convenience function knlist_init_mtx to reduce number of arguments for typical knlist initialization. Submitted by: jhb [1] Noted by: jhb [2] Reviewed by: jhb Tested by: rnoland
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 47a5046..7aca90ac 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -110,7 +110,8 @@ static void vnlru_free(int);
static void vgonel(struct vnode *);
static void vfs_knllock(void *arg);
static void vfs_knlunlock(void *arg);
-static int vfs_knllocked(void *arg);
+static void vfs_knl_assert_locked(void *arg);
+static void vfs_knl_assert_unlocked(void *arg);
static void destroy_vpollinfo(struct vpollinfo *vi);
/*
@@ -3271,7 +3272,7 @@ v_addpollinfo(struct vnode *vp)
vi = uma_zalloc(vnodepoll_zone, M_WAITOK);
mtx_init(&vi->vpi_lock, "vnode pollinfo", NULL, MTX_DEF);
knlist_init(&vi->vpi_selinfo.si_note, vp, vfs_knllock,
- vfs_knlunlock, vfs_knllocked);
+ vfs_knlunlock, vfs_knl_assert_locked, vfs_knl_assert_unlocked);
VI_LOCK(vp);
if (vp->v_pollinfo != NULL) {
VI_UNLOCK(vp);
@@ -3986,7 +3987,7 @@ static struct knlist fs_knlist;
static void
vfs_event_init(void *arg)
{
- knlist_init(&fs_knlist, NULL, NULL, NULL, NULL);
+ knlist_init_mtx(&fs_knlist, NULL);
}
/* XXX - correct order? */
SYSINIT(vfs_knlist, SI_SUB_VFS, SI_ORDER_ANY, vfs_event_init, NULL);
@@ -4099,12 +4100,24 @@ vfs_knlunlock(void *arg)
VOP_UNLOCK(vp, 0);
}
-static int
-vfs_knllocked(void *arg)
+static void
+vfs_knl_assert_locked(void *arg)
+{
+#ifdef DEBUG_VFS_LOCKS
+ struct vnode *vp = arg;
+
+ ASSERT_VOP_LOCKED(vp, "vfs_knl_assert_locked");
+#endif
+}
+
+static void
+vfs_knl_assert_unlocked(void *arg)
{
+#ifdef DEBUG_VFS_LOCKS
struct vnode *vp = arg;
- return (VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+ ASSERT_VOP_UNLOCKED(vp, "vfs_knl_assert_unlocked");
+#endif
}
int
@@ -4157,27 +4170,37 @@ filt_vfsread(struct knote *kn, long hint)
{
struct vnode *vp = (struct vnode *)kn->kn_hook;
struct vattr va;
+ int res;
/*
* filesystem is gone, so set the EOF flag and schedule
* the knote for deletion.
*/
if (hint == NOTE_REVOKE) {
+ VI_LOCK(vp);
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+ VI_UNLOCK(vp);
return (1);
}
if (VOP_GETATTR(vp, &va, curthread->td_ucred))
return (0);
+ VI_LOCK(vp);
kn->kn_data = va.va_size - kn->kn_fp->f_offset;
- return (kn->kn_data != 0);
+ res = (kn->kn_data != 0);
+ VI_UNLOCK(vp);
+ return (res);
}
/*ARGSUSED*/
static int
filt_vfswrite(struct knote *kn, long hint)
{
+ struct vnode *vp = (struct vnode *)kn->kn_hook;
+
+ VI_LOCK(vp);
+
/*
* filesystem is gone, so set the EOF flag and schedule
* the knote for deletion.
@@ -4186,19 +4209,27 @@ filt_vfswrite(struct knote *kn, long hint)
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
kn->kn_data = 0;
+ VI_UNLOCK(vp);
return (1);
}
static int
filt_vfsvnode(struct knote *kn, long hint)
{
+ struct vnode *vp = (struct vnode *)kn->kn_hook;
+ int res;
+
+ VI_LOCK(vp);
if (kn->kn_sfflags & hint)
kn->kn_fflags |= hint;
if (hint == NOTE_REVOKE) {
kn->kn_flags |= EV_EOF;
+ VI_UNLOCK(vp);
return (1);
}
- return (kn->kn_fflags != 0);
+ res = (kn->kn_fflags != 0);
+ VI_UNLOCK(vp);
+ return (res);
}
int
OpenPOWER on IntegriCloud