MINOR: quic: extract qc_stream_buf free in a dedicated function

On ACK reception, data are removed from buffer via qc_stream_desc_ack().
The buffer can be freed if no more data are left. A new slot is also
accounted in buffer connection pool. Extract this operation in a
dedicated private function qc_stream_buf_free().

This change should have no functional change. However it will be useful
for the next patch which needs to remove a buffer from another function.

This patch is necessary for the following bugfix. As such, it must be
backported with it up to 2.6.
This commit is contained in:
Amaury Denoyelle 2024-01-26 14:30:16 +01:00
parent 96385f40b5
commit 1da5787db4
1 changed files with 35 additions and 30 deletions

View File

@ -17,6 +17,34 @@ DECLARE_STATIC_POOL(pool_head_quic_stream_buf, "qc_stream_buf",
sizeof(struct qc_stream_buf)); sizeof(struct qc_stream_buf));
static void qc_stream_buf_free(struct qc_stream_desc *stream,
struct qc_stream_buf **stream_buf)
{
struct quic_conn *qc = stream->qc;
struct buffer *buf = &(*stream_buf)->buf;
LIST_DEL_INIT(&(*stream_buf)->list);
if (*stream_buf == stream->buf) {
/* current buf must always be last entry in buflist */
BUG_ON(!LIST_ISEMPTY(&stream->buf_list));
stream->buf = NULL;
}
b_free(buf);
offer_buffers(NULL, 1);
pool_free(pool_head_quic_stream_buf, *stream_buf);
*stream_buf = NULL;
/* notify MUX about available buffers. */
--qc->stream_buf_count;
if (qc->mux_state == QC_MUX_READY) {
if (qc->qcc->flags & QC_CF_CONN_FULL) {
qc->qcc->flags &= ~QC_CF_CONN_FULL;
tasklet_wakeup(qc->qcc->wait_event.tasklet);
}
}
}
/* Allocate a new stream descriptor with id <id>. The caller is responsible to /* Allocate a new stream descriptor with id <id>. The caller is responsible to
* store the stream in the appropriate tree. -1 special value must be used for * store the stream in the appropriate tree. -1 special value must be used for
* a CRYPTO data stream, the type being ignored. * a CRYPTO data stream, the type being ignored.
@ -92,7 +120,6 @@ int qc_stream_desc_ack(struct qc_stream_desc **stream, size_t offset, size_t len
{ {
struct qc_stream_desc *s = *stream; struct qc_stream_desc *s = *stream;
struct qc_stream_buf *stream_buf; struct qc_stream_buf *stream_buf;
struct quic_conn *qc = s->qc;
struct buffer *buf; struct buffer *buf;
size_t diff; size_t diff;
@ -110,38 +137,16 @@ int qc_stream_desc_ack(struct qc_stream_desc **stream, size_t offset, size_t len
s->ack_offset += diff; s->ack_offset += diff;
b_del(buf, diff); b_del(buf, diff);
/* nothing more to do if buf still not empty. */ /* Free oldest buffer if all data acknowledged. */
if (b_data(buf)) if (!b_data(buf)) {
return diff; qc_stream_buf_free(s, &stream_buf);
/* buf is empty and can now be freed. Do not forget to reset current
* buf ptr if we were working on it.
*/
LIST_DELETE(&stream_buf->list);
if (stream_buf == s->buf) {
/* current buf must always be last entry in buflist */
BUG_ON(!LIST_ISEMPTY(&s->buf_list));
s->buf = NULL;
}
b_free(buf);
pool_free(pool_head_quic_stream_buf, stream_buf);
offer_buffers(NULL, 1);
/* notify MUX about available buffers. */
--qc->stream_buf_count;
if (qc->mux_state == QC_MUX_READY) {
if (qc->qcc->flags & QC_CF_CONN_FULL) {
qc->qcc->flags &= ~QC_CF_CONN_FULL;
tasklet_wakeup(qc->qcc->wait_event.tasklet);
}
}
/* Free stream instance if already released and no buffers left. */ /* Free stream instance if already released and no buffers left. */
if (s->release && LIST_ISEMPTY(&s->buf_list)) { if (s->release && LIST_ISEMPTY(&s->buf_list)) {
qc_stream_desc_free(s, 0); qc_stream_desc_free(s, 0);
*stream = NULL; *stream = NULL;
} }
}
return diff; return diff;
} }