sctp: improve consistency when calling stream scheduler

Hold always the stcb send lock when calling sctp_ss_init() and
sctp_ss_remove_from_stream().

MFC after:	1 week
This commit is contained in:
Michael Tuexen 2021-09-21 00:54:13 +02:00
parent 5572fda3a2
commit 0b79a76f84
3 changed files with 16 additions and 13 deletions

View file

@ -7207,13 +7207,13 @@ one_more_time:
sp->put_last_out,
send_lock_up);
}
if ((TAILQ_NEXT(sp, next) == NULL) && (send_lock_up == 0)) {
if (send_lock_up == 0) {
SCTP_TCB_SEND_LOCK(stcb);
send_lock_up = 1;
}
atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&strq->outqueue, sp, next);
stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up);
stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, 1);
if ((strq->state == SCTP_STREAM_RESET_PENDING) &&
(strq->chunks_on_queues == 0) &&
TAILQ_EMPTY(&strq->outqueue)) {
@ -7638,13 +7638,13 @@ dont_do_it:
sp->put_last_out,
send_lock_up);
}
if ((send_lock_up == 0) && (TAILQ_NEXT(sp, next) == NULL)) {
if (send_lock_up == 0) {
SCTP_TCB_SEND_LOCK(stcb);
send_lock_up = 1;
}
atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&strq->outqueue, sp, next);
stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up);
stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, 1);
if ((strq->state == SCTP_STREAM_RESET_PENDING) &&
(strq->chunks_on_queues == 0) &&
TAILQ_EMPTY(&strq->outqueue)) {

View file

@ -1344,18 +1344,18 @@ sctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
static void
sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
struct sctp_tcb *stcb)
sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
{
struct sctp_stream_queue_pending *sp;
unsigned int i, chks_in_queue = 0;
int being_filled = 0;
/*
* This function is ONLY called when the send/sent queues are empty.
*/
if ((stcb == NULL) || (inp == NULL))
return;
KASSERT(inp != NULL, ("inp is NULL"));
KASSERT(stcb != NULL, ("stcb is NULL"));
SCTP_TCB_SEND_LOCK(stcb);
KASSERT(TAILQ_EMPTY(&stcb->asoc.send_queue), ("send_queue not empty"));
KASSERT(TAILQ_EMPTY(&stcb->asoc.sent_queue), ("sent_queue not empty"));
if (stcb->asoc.sent_queue_retran_cnt) {
SCTP_PRINTF("Hmm, sent_queue_retran_cnt is non-zero %d\n",
@ -1364,7 +1364,7 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
}
if (stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) {
/* No stream scheduler information, initialize scheduler */
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 0);
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) {
/* yep, we lost a stream or two */
SCTP_PRINTF("Found additional streams NOT managed by scheduler, corrected\n");
@ -1406,6 +1406,7 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
(u_long)stcb->asoc.total_output_queue_size);
stcb->asoc.total_output_queue_size = 0;
}
SCTP_TCB_SEND_UNLOCK(stcb);
}
int

View file

@ -1288,6 +1288,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
return (ENOMEM);
}
SCTP_TCB_SEND_LOCK(stcb);
for (i = 0; i < asoc->streamoutcnt; i++) {
/*
* inbound side must be set to 0xffff, also NOTE when we get
@ -1315,7 +1316,8 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->strmout[i].last_msg_incomplete = 0;
asoc->strmout[i].state = SCTP_STREAM_OPENING;
}
asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
asoc->ss_functions.sctp_ss_init(stcb, asoc, 1);
SCTP_TCB_SEND_UNLOCK(stcb);
/* Now the mapping array */
asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;