Source-Changes-D archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: CVS commit: src/sys/net
On Mon, Apr 11, 2016 at 12:31 PM, Taylor R Campbell
<campbell+netbsd-source-changes-d%mumble.net@localhost> wrote:
> Date: Mon, 11 Apr 2016 02:04:14 +0000
> From: Ryota Ozaki <ozaki-r%netbsd.org@localhost>
>
> Module Name: src
> Committed By: ozaki-r
> Date: Mon Apr 11 02:04:14 UTC 2016
>
> Modified Files:
> src/sys/net: bridgestp.c if_bridge.c if_bridgevar.h
>
> Log Message:
> Use pslist(9) in bridge(4)
>
> This adds missing memory barriers to list operations for pserialize.
>
> Nice, thanks for doing this! Have you tried subjecting it to load,
> with options DIAGNOSTIC?
Yes. It passes ATF tests (that enable DIAGNOSTIC).
>
> Index: src/sys/net/bridgestp.c
> diff -u src/sys/net/bridgestp.c:1.19 src/sys/net/bridgestp.c:1.20
> --- src/sys/net/bridgestp.c:1.19 Mon Feb 15 01:11:41 2016
> +++ src/sys/net/bridgestp.c Mon Apr 11 02:04:14 2016
> @@ -341,7 +341,8 @@ bstp_config_bpdu_generation(struct bridg
> {
> struct bridge_iflist *bif;
>
> - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
> + PSLIST_READER_FOREACH(bif, &sc->sc_iflist, struct bridge_iflist,
> + bif_next) {
>
> I'm pretty sure everything in bridgestp.c runs under a writer lock, so
> you should use PSLIST_WRITER_FOREACH here, not PSLIST_READER_FOREACH.
>
> (PSLIST_WRITER_FOREACH is faster on alpha -- but more important is the
> statement of intent that this is in an exclusive write section, not a
> shared read section.)
>
> @@ -828,7 +833,8 @@ bstp_initialization(struct bridge_softc
>
> BRIDGE_LOCK(sc);
>
> - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
> + PSLIST_READER_FOREACH(bif, &sc->sc_iflist, struct bridge_iflist,
> + bif_next) {
>
> For example, this one is definitely done under a writer lock!
Oh yes. I think I already forgot bridgestp.c at all!
>
> Index: src/sys/net/if_bridge.c
> diff -u src/sys/net/if_bridge.c:1.111 src/sys/net/if_bridge.c:1.112
> --- src/sys/net/if_bridge.c:1.111 Mon Mar 28 04:38:04 2016
> +++ src/sys/net/if_bridge.c Mon Apr 11 02:04:14 2016
> @@ -447,8 +447,14 @@ bridge_clone_destroy(struct ifnet *ifp)
> bridge_stop(ifp, 1);
>
> BRIDGE_LOCK(sc);
> - while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL)
> + for (;;) {
> + bif = PSLIST_WRITER_FIRST(&sc->sc_iflist, struct bridge_iflist,
> + bif_next);
> + if (bif == NULL)
> + break;
> bridge_delete_member(sc, bif);
> + }
> + PSLIST_DESTROY(&sc->sc_iflist);
>
> Any particular reason you switched from `while ((bif = ...) != NULL)'
> to `for (;;) { bif = ...; if (bif == NULL) break;'? I find the while
> construct clearer, myself.
Just because it's too long (for me) to put it in the condition.
>
> @@ -705,7 +712,8 @@ bridge_delete_member(struct bridge_softc
> ifs->if_bridge = NULL;
> ifs->if_bridgeif = NULL;
>
> - LIST_REMOVE(bif, bif_next);
> + PSLIST_WRITER_REMOVE(bif, bif_next);
> + PSLIST_ENTRY_DESTROY(bif, bif_next);
>
> BRIDGE_PSZ_PERFORM(sc);
>
> This order is incorrect. You cannot destroy the entry until you have
> confirmed all readers are done with it. You must pserialize_perform
> before doing PSLIST_ENTRY_DESTROY. See the note in the pslist(9) man
> page about this:
>
> `Either _element_ must never have been inserted into a list, or it
> must have been inserted and removed, and the caller must have waited
> for all parallel readers to finish reading it first.'
>
> The reason is that PSLIST_WRITER_REMOVE only changes the next pointer
> of the *previous* element so that no new readers can discover the
> current element, but leaves the next pointer of the *current* element
> intact so that readers that are still active can get to the next
> element. Then PSLIST_ENTRY_DESTROY nullifies the next pointer of the
> current element and kasserts that you removed the entry.
I see. (I should be claimed RTFM :-/)
>
> Maybe PSLIST_ENTRY_DESTROY should really set it to some non-null
> poison pointer like QUEUEDEBUG does, so that anyone trying to use it
> afterward will actually crash instead of just thinking they hit the
> end of the list.
>
> @@ -939,7 +949,8 @@ bridge_ioctl_gifs(struct bridge_softc *s
> retry:
> BRIDGE_LOCK(sc);
> count = 0;
> - LIST_FOREACH(bif, &sc->sc_iflist, bif_next)
> + PSLIST_READER_FOREACH(bif, &sc->sc_iflist, struct bridge_iflist,
> + bif_next)
>
> Use PSLIST_WRITER_FOREACH here too.
>
> @@ -959,7 +970,8 @@ retry:
> BRIDGE_LOCK(sc);
>
> i = 0;
> - LIST_FOREACH(bif, &sc->sc_iflist, bif_next)
> + PSLIST_READER_FOREACH(bif, &sc->sc_iflist, struct bridge_iflist,
> + bif_next)
>
> PSLIST_WRITER_FOREACH
>
> i++;
> if (i > count) {
> /*
> @@ -972,7 +984,8 @@ retry:
> }
>
> i = 0;
> - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
> + PSLIST_READER_FOREACH(bif, &sc->sc_iflist, struct bridge_iflist,
> + bif_next) {
>
> PSLIST_WRITER_FOREACH
Hm, so we need to choose a macro not what we do in the loop but how the loop
is protected. Indeed in terms of use of membar.
Thanks for reviewing!
ozaki-r
Home |
Main Index |
Thread Index |
Old Index