Source-Changes-D archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: CVS commit: src/sys/net
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?
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!
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.
@@ -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.
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
Home |
Main Index |
Thread Index |
Old Index