summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorjmg <jmg@FreeBSD.org>2004-08-15 06:24:42 +0000
committerjmg <jmg@FreeBSD.org>2004-08-15 06:24:42 +0000
commitbc1805c6e871c178d0b6516c3baa774ffd77224a (patch)
tree1172b68a7c9e7fa73090ae134eb98825bdab8ad6 /sys/net/if.c
parent57da12d01618c3ef2590eab07e71f69d16ead13a (diff)
downloadFreeBSD-src-bc1805c6e871c178d0b6516c3baa774ffd77224a.zip
FreeBSD-src-bc1805c6e871c178d0b6516c3baa774ffd77224a.tar.gz
Add locking to the kqueue subsystem. This also makes the kqueue subsystem
a more complete subsystem, and removes the knowlege of how things are implemented from the drivers. Include locking around filter ops, so a module like aio will know when not to be unloaded if there are outstanding knotes using it's filter ops. Currently, it uses the MTX_DUPOK even though it is not always safe to aquire duplicate locks. Witness currently doesn't support the ability to discover if a dup lock is ok (in some cases). Reviewed by: green, rwatson (both earlier versions)
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c42
1 files changed, 23 insertions, 19 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 9f560d3..b2f365c 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -109,7 +109,7 @@ struct ifnethead ifnet; /* depend on static init XXX */
struct mtx ifnet_lock;
static int if_indexlim = 8;
-static struct klist ifklist;
+static struct knlist ifklist;
static void filt_netdetach(struct knote *kn);
static int filt_netdev(struct knote *kn, long hint);
@@ -185,10 +185,18 @@ netioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td
static int
netkqfilter(struct cdev *dev, struct knote *kn)
{
- struct klist *klist;
+ struct knlist *klist;
struct ifnet *ifp;
int idx;
+ switch (kn->kn_filter) {
+ case EVFILT_NETDEV:
+ kn->kn_fop = &netdev_filtops;
+ break;
+ default:
+ return (1);
+ }
+
idx = minor(dev);
if (idx == 0) {
klist = &ifklist;
@@ -199,18 +207,9 @@ netkqfilter(struct cdev *dev, struct knote *kn)
klist = &ifp->if_klist;
}
- switch (kn->kn_filter) {
- case EVFILT_NETDEV:
- kn->kn_fop = &netdev_filtops;
- break;
- default:
- return (1);
- }
-
kn->kn_hook = (caddr_t)klist;
- /* XXX locking? */
- SLIST_INSERT_HEAD(klist, kn, kn_selnext);
+ knlist_add(klist, kn, 0);
return (0);
}
@@ -218,27 +217,30 @@ netkqfilter(struct cdev *dev, struct knote *kn)
static void
filt_netdetach(struct knote *kn)
{
- struct klist *klist = (struct klist *)kn->kn_hook;
+ struct knlist *klist = (struct knlist *)kn->kn_hook;
if (kn->kn_status & KN_DETACHED)
return;
- SLIST_REMOVE(klist, kn, knote, kn_selnext);
+
+ knlist_remove(klist, kn, 0);
}
static int
filt_netdev(struct knote *kn, long hint)
{
+ struct knlist *klist = (struct knlist *)kn->kn_hook;
/*
* Currently NOTE_EXIT is abused to indicate device detach.
*/
if (hint == NOTE_EXIT) {
kn->kn_data = NOTE_LINKINV;
- kn->kn_status |= KN_DETACHED;
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+ knlist_remove_inevent(klist, kn);
return (1);
}
- kn->kn_data = hint; /* current status */
+ if (hint != 0)
+ kn->kn_data = hint; /* current status */
if (kn->kn_sfflags & hint)
kn->kn_fflags |= hint;
return (kn->kn_fflags != 0);
@@ -257,7 +259,7 @@ if_init(void *dummy __unused)
IFNET_LOCK_INIT();
TAILQ_INIT(&ifnet);
- SLIST_INIT(&ifklist);
+ knlist_init(&ifklist, NULL);
if_grow(); /* create initial table */
ifdev_byindex(0) = make_dev(&net_cdevsw, 0,
UID_ROOT, GID_WHEEL, 0600, "network");
@@ -383,7 +385,7 @@ if_attach(struct ifnet *ifp)
TAILQ_INIT(&ifp->if_addrhead);
TAILQ_INIT(&ifp->if_prefixhead);
TAILQ_INIT(&ifp->if_multiaddrs);
- SLIST_INIT(&ifp->if_klist);
+ knlist_init(&ifp->if_klist, NULL);
getmicrotime(&ifp->if_lastchange);
#ifdef MAC
@@ -620,7 +622,9 @@ if_detach(struct ifnet *ifp)
#ifdef MAC
mac_destroy_ifnet(ifp);
#endif /* MAC */
- KNOTE(&ifp->if_klist, NOTE_EXIT);
+ KNOTE_UNLOCKED(&ifp->if_klist, NOTE_EXIT);
+ knlist_clear(&ifp->if_klist, 0);
+ knlist_destroy(&ifp->if_klist);
IFNET_WLOCK();
found = 0;
TAILQ_FOREACH(iter, &ifnet, if_link)
OpenPOWER on IntegriCloud