svn commit: r310302 - head/sys/kern

Konstantin Belousov kib at FreeBSD.org
Mon Dec 19 22:18:37 UTC 2016


Author: kib
Date: Mon Dec 19 22:18:36 2016
New Revision: 310302
URL: https://svnweb.freebsd.org/changeset/base/310302

Log:
  Do not clear KN_INFLUX when not owning influx state.
  
  For notes in KN_INFLUX|KN_SCAN state, the influx bit is set by a
  parallel scan.  When knote() reports event for the vnode filters,
  which require kqueue unlocked, it unconditionally sets and then clears
  influx to keep note around kqueue unlock.  There, do not clear influx
  flag if a scan set it, since we do not own it, instead we prevent scan
  from executing by holding knlist lock.
  
  The knote_fork() function has somewhat similar problem, it might set
  KN_INFLUX for scanned note, drop kqueue and list locks, and then clear
  the flag after relock.  A solution there would be different enough, as
  well as the test program, so close the reported issue first.
  
  Reported and test case provided by:	yjh0502 at gmail.com
  PR:	214923
  Tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/kern/kern_event.c

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c	Mon Dec 19 22:15:29 2016	(r310301)
+++ head/sys/kern/kern_event.c	Mon Dec 19 22:18:36 2016	(r310302)
@@ -2006,6 +2006,7 @@ knote(struct knlist *list, long hint, in
 	struct kqueue *kq;
 	struct knote *kn, *tkn;
 	int error;
+	bool own_influx;
 
 	if (list == NULL)
 		return;
@@ -2036,11 +2037,14 @@ knote(struct knlist *list, long hint, in
 			 */
 			KQ_UNLOCK(kq);
 		} else if ((lockflags & KNF_NOKQLOCK) != 0) {
-			kn->kn_status |= KN_INFLUX;
+			own_influx = (kn->kn_status & KN_INFLUX) == 0;
+			if (own_influx)
+				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 (own_influx)
+				kn->kn_status &= ~KN_INFLUX;
 			if (error)
 				KNOTE_ACTIVATE(kn, 1);
 			KQ_UNLOCK_FLUX(kq);


More information about the svn-src-head mailing list