summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/sctp_constants.h2
-rw-r--r--sys/netinet/sctp_lock_bsd.h7
-rw-r--r--sys/netinet/sctp_pcb.c13
-rw-r--r--sys/netinet/sctp_sysctl.c13
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();
OpenPOWER on IntegriCloud