Date: Tue, 16 Dec 2008 17:03:22 +0000 (UTC) From: Robert Watson <rwatson@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r186187 - head/sys/net Message-ID: <200812161703.mBGH3M7m042955@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rwatson Date: Tue Dec 16 17:03:22 2008 New Revision: 186187 URL: http://svn.freebsd.org/changeset/base/186187 Log: A few locking fixes and cleanups to pfil hook registration, unregistration, and execution: - Add some brackets for clarity and trim a bit of vertical whitespace. - Remove comments that may not contribute to clarity, such as "Lock" before acquiring a lock and "Get memory" before allocating memory. - During hook registration, don't drop pfil_list_lock between checking for a duplicate and registering the hook, as this leaves a race condition by failing to enforce the "no duplicate hooks" invariant. - Don't lock the hook during registration, since it's not yet in use. - Document assumption that hooks will be quiesced before being unregistered. - Don't write-lock hooks during removal because they are assumed quiesced. - Rename "done" label to "locked_error" to be clear that it's an error path on the way out of hook execution. MFC after: pretty soon Modified: head/sys/net/pfil.c Modified: head/sys/net/pfil.c ============================================================================== --- head/sys/net/pfil.c Tue Dec 16 17:01:52 2008 (r186186) +++ head/sys/net/pfil.c Tue Dec 16 17:03:22 2008 (r186187) @@ -97,33 +97,26 @@ pfil_head_register(struct pfil_head *ph) struct pfil_head *lph; PFIL_LIST_LOCK(); - LIST_FOREACH(lph, &pfil_head_list, ph_list) + LIST_FOREACH(lph, &pfil_head_list, ph_list) { if (ph->ph_type == lph->ph_type && ph->ph_un.phu_val == lph->ph_un.phu_val) { PFIL_LIST_UNLOCK(); return EEXIST; } - PFIL_LIST_UNLOCK(); - + } PFIL_LOCK_INIT(ph); - PFIL_WLOCK(ph); ph->ph_nhooks = 0; - TAILQ_INIT(&ph->ph_in); TAILQ_INIT(&ph->ph_out); - - PFIL_LIST_LOCK(); LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list); PFIL_LIST_UNLOCK(); - - PFIL_WUNLOCK(ph); - return (0); } /* - * pfil_head_unregister() removes a pfil_head from the packet filter - * hook mechanism. + * pfil_head_unregister() removes a pfil_head from the packet filter hook + * mechanism. The producer of the hook promises that all outstanding + * invocations of the hook have completed before it unregisters the hook. */ int pfil_head_unregister(struct pfil_head *ph) @@ -131,21 +124,13 @@ pfil_head_unregister(struct pfil_head *p struct packet_filter_hook *pfh, *pfnext; PFIL_LIST_LOCK(); - /* - * LIST_REMOVE is safe for unlocked pfil_heads in ph_list. - * No need to WLOCK all of them. - */ LIST_REMOVE(ph, ph_list); PFIL_LIST_UNLOCK(); - - PFIL_WLOCK(ph); - TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_link, pfnext) free(pfh, M_IFADDR); TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext) free(pfh, M_IFADDR); PFIL_LOCK_DESTROY(ph); - return (0); } @@ -175,14 +160,13 @@ pfil_head_get(int type, u_long val) * PFIL_WAITOK OK to call malloc with M_WAITOK. */ int -pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), - void *arg, int flags, struct pfil_head *ph) +pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, + struct inpcb *), void *arg, int flags, struct pfil_head *ph) { struct packet_filter_hook *pfh1 = NULL; struct packet_filter_hook *pfh2 = NULL; int err; - /* Get memory */ if (flags & PFIL_IN) { pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1), M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); @@ -199,17 +183,13 @@ pfil_add_hook(int (*func)(void *, struct goto error; } } - - /* Lock */ PFIL_WLOCK(ph); - - /* Add */ if (flags & PFIL_IN) { pfh1->pfil_func = func; pfh1->pfil_arg = arg; err = pfil_list_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT); if (err) - goto done; + goto locked_error; ph->ph_nhooks++; } if (flags & PFIL_OUT) { @@ -219,15 +199,13 @@ pfil_add_hook(int (*func)(void *, struct if (err) { if (flags & PFIL_IN) pfil_list_remove(&ph->ph_in, func, arg); - goto done; + goto locked_error; } ph->ph_nhooks++; } - PFIL_WUNLOCK(ph); - return 0; -done: +locked_error: PFIL_WUNLOCK(ph); error: if (pfh1 != NULL)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812161703.mBGH3M7m042955>