Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Jun 2009 21:49:43 +0000 (UTC)
From:      Stanislav Sedov <stas@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r195148 - in head/sys: kern netgraph sys
Message-ID:  <200906282149.n5SLnhm8022783@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: stas
Date: Sun Jun 28 21:49:43 2009
New Revision: 195148
URL: http://svn.freebsd.org/changeset/base/195148

Log:
  - Turn the third (islocked) argument of the knote call into flags parameter.
    Introduce the new flag KNF_NOKQLOCK to allow event callers to be called
    without KQ_LOCK mtx held.
  - Modify VFS knote calls to always use KNF_NOKQLOCK flag.  This is required
    for ZFS as its getattr implementation may sleep.
  
  Approved by:	re (rwatson)
  Reviewed by:	kib
  MFC after:	2 weeks

Modified:
  head/sys/kern/kern_event.c
  head/sys/netgraph/ng_ksocket.c
  head/sys/sys/event.h
  head/sys/sys/mount.h
  head/sys/sys/vnode.h

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c	Sun Jun 28 21:01:00 2009	(r195147)
+++ head/sys/kern/kern_event.c	Sun Jun 28 21:49:43 2009	(r195148)
@@ -1606,17 +1606,18 @@ kqueue_wakeup(struct kqueue *kq)
  * first.
  */
 void
-knote(struct knlist *list, long hint, int islocked)
+knote(struct knlist *list, long hint, int lockflags)
 {
 	struct kqueue *kq;
 	struct knote *kn;
+	int error;
 
 	if (list == NULL)
 		return;
 
-	KNL_ASSERT_LOCK(list, islocked);
+	KNL_ASSERT_LOCK(list, lockflags & KNF_LISTLOCKED);
 
-	if (!islocked) 
+	if ((lockflags & KNF_LISTLOCKED) == 0)
 		list->kl_lock(list->kl_lockarg); 
 
 	/*
@@ -1631,17 +1632,28 @@ knote(struct knlist *list, long hint, in
 		kq = kn->kn_kq;
 		if ((kn->kn_status & KN_INFLUX) != KN_INFLUX) {
 			KQ_LOCK(kq);
-			if ((kn->kn_status & KN_INFLUX) != KN_INFLUX) {
+			if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) {
+				KQ_UNLOCK(kq);
+			} else if ((lockflags & KNF_NOKQLOCK) != 0) {
+				kn->kn_status |= KN_INFLUX;
+				KQ_UNLOCK(kq);
+				error = kn->kn_fop->f_event(kn, hint);
+				KQ_LOCK(kq);
+				kn->kn_status &= ~KN_INFLUX;
+				if (error)
+					KNOTE_ACTIVATE(kn, 1);
+				KQ_UNLOCK_FLUX(kq);
+			} else {
 				kn->kn_status |= KN_HASKQLOCK;
 				if (kn->kn_fop->f_event(kn, hint))
 					KNOTE_ACTIVATE(kn, 1);
 				kn->kn_status &= ~KN_HASKQLOCK;
+				KQ_UNLOCK(kq);
 			}
-			KQ_UNLOCK(kq);
 		}
 		kq = NULL;
 	}
-	if (!islocked)
+	if ((lockflags & KNF_LISTLOCKED) == 0)
 		list->kl_unlock(list->kl_lockarg); 
 }
 

Modified: head/sys/netgraph/ng_ksocket.c
==============================================================================
--- head/sys/netgraph/ng_ksocket.c	Sun Jun 28 21:01:00 2009	(r195147)
+++ head/sys/netgraph/ng_ksocket.c	Sun Jun 28 21:49:43 2009	(r195148)
@@ -1212,7 +1212,7 @@ ng_ksocket_finish_accept(priv_p priv)
 	SOCK_UNLOCK(so);
 	ACCEPT_UNLOCK();
 
-	/* XXX KNOTE(&head->so_rcv.sb_sel.si_note, 0); */
+	/* XXX KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0); */
 
 	soaccept(so, &sa);
 

Modified: head/sys/sys/event.h
==============================================================================
--- head/sys/sys/event.h	Sun Jun 28 21:01:00 2009	(r195147)
+++ head/sys/sys/event.h	Sun Jun 28 21:49:43 2009	(r195148)
@@ -136,8 +136,14 @@ struct knlist {
 MALLOC_DECLARE(M_KQUEUE);
 #endif
 
-#define KNOTE(list, hist, lock)		knote(list, hist, lock)
-#define KNOTE_LOCKED(list, hint)	knote(list, hint, 1)
+/*
+ * Flags for knote call
+ */
+#define	KNF_LISTLOCKED	0x0001			/* knlist is locked */
+#define	KNF_NOKQLOCK	0x0002			/* do not keep KQ_LOCK */
+
+#define KNOTE(list, hist, flags)	knote(list, hist, flags)
+#define KNOTE_LOCKED(list, hint)	knote(list, hint, KNF_LISTLOCKED)
 #define KNOTE_UNLOCKED(list, hint)	knote(list, hint, 0)
 
 #define	KNLIST_EMPTY(list)		SLIST_EMPTY(&(list)->kl_list)
@@ -206,7 +212,7 @@ struct proc;
 struct knlist;
 struct mtx;
 
-extern void	knote(struct knlist *list, long hint, int islocked);
+extern void	knote(struct knlist *list, long hint, int lockflags);
 extern void	knote_fork(struct knlist *list, int pid);
 extern void	knlist_add(struct knlist *knl, struct knote *kn, int islocked);
 extern void	knlist_remove(struct knlist *knl, struct knote *kn, int islocked);

Modified: head/sys/sys/mount.h
==============================================================================
--- head/sys/sys/mount.h	Sun Jun 28 21:01:00 2009	(r195147)
+++ head/sys/sys/mount.h	Sun Jun 28 21:49:43 2009	(r195148)
@@ -657,7 +657,7 @@ vfs_statfs_t	__vfs_statfs;
 #define VFS_KNOTE_LOCKED(vp, hint) do					\
 {									\
 	if (((vp)->v_vflag & VV_NOKNOTE) == 0)				\
-		VN_KNOTE((vp), (hint), 1);				\
+		VN_KNOTE((vp), (hint), KNF_LISTLOCKED);			\
 } while (0)
 
 #define VFS_KNOTE_UNLOCKED(vp, hint) do					\

Modified: head/sys/sys/vnode.h
==============================================================================
--- head/sys/sys/vnode.h	Sun Jun 28 21:01:00 2009	(r195147)
+++ head/sys/sys/vnode.h	Sun Jun 28 21:49:43 2009	(r195148)
@@ -219,9 +219,10 @@ struct xvnode {
 #define VN_KNOTE(vp, b, a)					\
 	do {							\
 		if (!VN_KNLIST_EMPTY(vp))			\
-			KNOTE(&vp->v_pollinfo->vpi_selinfo.si_note, (b), (a)); \
+			KNOTE(&vp->v_pollinfo->vpi_selinfo.si_note, (b), \
+			    (a) | KNF_NOKQLOCK);		\
 	} while (0)
-#define	VN_KNOTE_LOCKED(vp, b)		VN_KNOTE(vp, b, 1)
+#define	VN_KNOTE_LOCKED(vp, b)		VN_KNOTE(vp, b, KNF_LISTLOCKED)
 #define	VN_KNOTE_UNLOCKED(vp, b)	VN_KNOTE(vp, b, 0)
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906282149.n5SLnhm8022783>