diff options
author | rrs <rrs@FreeBSD.org> | 2010-06-06 20:34:17 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2010-06-06 20:34:17 +0000 |
commit | 3bcf4834bbfb8c8c8023e0c832e654f827c1ff0d (patch) | |
tree | c75fb516496af43a786e1c0f886c80957c2cdcf8 /sys/netinet/sctp_sysctl.c | |
parent | 6bf375889db714097da8272c8ad55ea17dc466ae (diff) | |
download | FreeBSD-src-3bcf4834bbfb8c8c8023e0c832e654f827c1ff0d.zip FreeBSD-src-3bcf4834bbfb8c8c8023e0c832e654f827c1ff0d.tar.gz |
1) Optimize the cleanup and don't always depend on
the timer. This is done by considering the locks
we will destroy and if they are contended we consider
it the same as a reference count being up. Fixing this
appears to cleanup another crash that was appearing with
all the timers where the socket buf lock got corrupted.
2) Fix the sysctl code to take a lot more care when looking
at INP's that are in the GONE or ALLGONE state.
MFC after: 1 week
Diffstat (limited to 'sys/netinet/sctp_sysctl.c')
-rw-r--r-- | sys/netinet/sctp_sysctl.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index c9967ea..9ba7dd4 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -331,6 +331,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) struct xsctp_inpcb xinpcb; struct xsctp_tcb xstcb; struct xsctp_raddr xraddr; + struct socket *so; number_of_endpoints = 0; number_of_local_addresses = 0; @@ -369,6 +370,10 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) } LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { SCTP_INP_RLOCK(inp); + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { + /* if its allgone it is being freed - skip it */ + goto skip; + } xinpcb.last = 0; xinpcb.local_port = ntohs(inp->sctp_lport); xinpcb.flags = inp->sctp_flags; @@ -377,13 +382,14 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) xinpcb.total_recvs = inp->total_recvs; xinpcb.total_nospaces = inp->total_nospaces; xinpcb.fragmentation_point = inp->sctp_frag_point; - if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || + so = inp->sctp_socket; + if ((so == NULL) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { xinpcb.qlen = 0; xinpcb.maxqlen = 0; } else { - xinpcb.qlen = inp->sctp_socket->so_qlen; - xinpcb.maxqlen = inp->sctp_socket->so_qlimit; + xinpcb.qlen = so->so_qlen; + xinpcb.maxqlen = so->so_qlimit; } SCTP_INP_INCR_REF(inp); SCTP_INP_RUNLOCK(inp); @@ -501,6 +507,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) if (error) { return error; } +skip: SCTP_INP_INFO_RLOCK(); } SCTP_INP_INFO_RUNLOCK(); |