diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/sctp_constants.h | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_lock_bsd.h | 7 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 13 | ||||
-rw-r--r-- | sys/netinet/sctp_sysctl.c | 13 |
4 files changed, 28 insertions, 7 deletions
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index abf5826..078981d 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -894,7 +894,7 @@ __FBSDID("$FreeBSD$"); /* third argument */ #define SCTP_CALLED_DIRECTLY_NOCMPSET 0 #define SCTP_CALLED_AFTER_CMPSET_OFCLOSE 1 -#define SCTP_CALLED_FROM_INPKILL_TIMER 2 +#define SCTP_CALLED_FROM_INPKILL_TIMER 2 /* second argument */ #define SCTP_FREE_SHOULD_USE_ABORT 1 #define SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE 0 diff --git a/sys/netinet/sctp_lock_bsd.h b/sys/netinet/sctp_lock_bsd.h index 75c382b..dd9c2ce 100644 --- a/sys/netinet/sctp_lock_bsd.h +++ b/sys/netinet/sctp_lock_bsd.h @@ -185,6 +185,13 @@ extern int sctp_logoff_stuff; #define SCTP_INP_LOCK_DESTROY(_inp) \ mtx_destroy(&(_inp)->inp_mtx) +#define SCTP_INP_LOCK_CONTENDED(_inp) ((_inp)->inp_mtx.mtx_lock & MTX_CONTESTED) + +#define SCTP_INP_READ_CONTENDED(_inp) ((_inp)->inp_rdata_mtx.mtx_lock & MTX_CONTESTED) + +#define SCTP_ASOC_CREATE_LOCK_CONTENDED(_inp) ((_inp)->inp_create_mtx.mtx_lock & MTX_CONTESTED) + + #define SCTP_ASOC_CREATE_LOCK_DESTROY(_inp) \ mtx_destroy(&(_inp)->inp_create_mtx) diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index f9e029a..8547584 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3096,7 +3096,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct sctp_laddr *laddr, *nladdr; struct inpcb *ip_pcb; struct socket *so; - + int being_refed = 0; struct sctp_queued_to_read *sq; @@ -3423,9 +3423,16 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) #endif return; } + if (SCTP_INP_LOCK_CONTENDED(inp)) + being_refed++; + if (SCTP_INP_READ_CONTENDED(inp)) + being_refed++; + if (SCTP_ASOC_CREATE_LOCK_CONTENDED(inp)) + being_refed++; + if ((inp->refcount) || - (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP) || - (from != SCTP_CALLED_FROM_INPKILL_TIMER)) { + (being_refed) || + (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) { (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); sctp_timer_start(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL); SCTP_INP_WUNLOCK(inp); 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(); |