]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: buffers: Move small buffers management from quic to dynbuf part
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 9 Mar 2026 06:38:22 +0000 (07:38 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 23 Mar 2026 13:02:42 +0000 (14:02 +0100)
Because small buffers were only used by QUIC streams, the pool used to alloc
these buffers was located in the quic code. However, their usage will be
extended to other parts. So, the small buffers pool was moved into the
dynbuf part.

include/haproxy/dynbuf.h
src/cfgparse.c
src/dynbuf.c
src/quic_stream.c

index 42e4d1f4b656d7c8585ceef5f734c595d640b27c..d487e1068ab44e34fe4e3783513d4f90a42a7aeb 100644 (file)
@@ -37,6 +37,7 @@
 
 extern struct pool_head *pool_head_buffer;
 extern struct pool_head *pool_head_large_buffer;
+extern struct pool_head *pool_head_small_buffer;
 
 int init_buffer(void);
 void buffer_dump(FILE *o, struct buffer *b, int from, int to);
@@ -66,6 +67,12 @@ static inline int b_is_large_sz(size_t sz)
        return (pool_head_large_buffer && sz == pool_head_large_buffer->size);
 }
 
+/* Return 1 if <sz> is the size of a small buffer */
+static inline int b_is_small_sz(size_t sz)
+{
+       return (pool_head_small_buffer && sz == pool_head_small_buffer->size);
+}
+
 /* Return 1 if <bug> is a  default buffer */
 static inline int b_is_default(struct buffer *buf)
 {
@@ -78,6 +85,12 @@ static inline int b_is_large(struct buffer *buf)
        return b_is_large_sz(b_size(buf));
 }
 
+/* Return 1 if <buf> is a small buffer */
+static inline int b_is_small(struct buffer *buf)
+{
+       return b_is_small_sz(b_size(buf));
+}
+
 /**************************************************/
 /* Functions below are used for buffer allocation */
 /**************************************************/
@@ -172,6 +185,8 @@ static inline char *__b_get_emergency_buf(void)
                 * than the default buffers */                          \
                if (unlikely(b_is_large_sz(sz)))                        \
                        pool_free(pool_head_large_buffer, area);        \
+               else if (unlikely(b_is_small_sz(sz)))                   \
+                       pool_free(pool_head_small_buffer, area);        \
                else if (th_ctx->emergency_bufs_left < global.tune.reserved_bufs) \
                        th_ctx->emergency_bufs[th_ctx->emergency_bufs_left++] = area; \
                else                                                    \
index d89acfeb68398147a90f8189f3fc2d7c77c1d493..f36e5719d4b3619c7e8f18ae5dfa1849f4699bc2 100644 (file)
@@ -2322,6 +2322,17 @@ int check_config_validity()
                }
        }
 
+       if (global.tune.bufsize_small > 0) {
+               if (global.tune.bufsize_small == global.tune.bufsize)
+                       global.tune.bufsize_small = 0;
+               else if (global.tune.bufsize_small > global.tune.bufsize) {
+                       ha_warning("invalid small buffer size %d bytes which is greater to default bufsize %d bytes.\n",
+                                  global.tune.bufsize_small, global.tune.bufsize);
+                       err_code |=  ERR_FATAL | ERR_ABORT;
+                       goto out;
+               }
+       }
+
        /* in the worst case these were supposed to be set in thread_detect_count() */
        BUG_ON(!global.nbthread);
        BUG_ON(!global.nbtgroups);
index ff80b8198ad5f7004ad60e8b9e791e1b5648cdbc..5c299edbd82a9333838ed0e30ede72baf40e176a 100644 (file)
@@ -24,6 +24,7 @@
 
 struct pool_head *pool_head_buffer __read_mostly;
 struct pool_head *pool_head_large_buffer __read_mostly = NULL;
+struct pool_head *pool_head_small_buffer __read_mostly;
 
 /* perform minimal initializations, report 0 in case of error, 1 if OK. */
 int init_buffer()
@@ -43,6 +44,12 @@ int init_buffer()
                        return 0;
        }
 
+       if (global.tune.bufsize_small) {
+               pool_head_small_buffer = create_aligned_pool("small_buffer", global.tune.bufsize_small, 64, MEM_F_SHARED|MEM_F_EXACT);
+               if (!pool_head_small_buffer)
+                       return 0;
+       }
+
        /* make sure any change to the queues assignment isn't overlooked */
        BUG_ON(DB_PERMANENT - DB_UNLIKELY - 1 != DYNBUF_NBQ);
        BUG_ON(DB_MUX_RX_Q  < DB_SE_RX_Q   || DB_MUX_RX_Q  >= DYNBUF_NBQ);
index 3640304777a726c11d829c3168a5bbbfc3e889e0..407ca1efeb8a1f7980e9543262c168f9a08b6c56 100644 (file)
@@ -16,8 +16,6 @@ DECLARE_STATIC_TYPED_POOL(pool_head_quic_stream_desc, "qc_stream_desc", struct q
 DECLARE_STATIC_TYPED_POOL(pool_head_quic_stream_buf, "qc_stream_buf", struct qc_stream_buf);
 DECLARE_STATIC_TYPED_POOL(pool_head_quic_stream_ack, "qc_stream_ack", struct qc_stream_ack);
 
-static struct pool_head *pool_head_sbuf;
-
 static void qc_stream_buf_free(struct qc_stream_desc *stream,
                                struct qc_stream_buf **stream_buf)
 {
@@ -39,13 +37,10 @@ static void qc_stream_buf_free(struct qc_stream_desc *stream,
                room = b_data(buf);
        }
 
-       if ((*stream_buf)->sbuf) {
-               pool_free(pool_head_sbuf, buf->area);
-       }
-       else {
+       b_free(buf);
+       if (!(*stream_buf)->sbuf) {
                bdata_ctr_del(&stream->data, b_data(buf));
                bdata_ctr_bdec(&stream->data);
-               b_free(buf);
                offer_buffers(NULL, 1);
        }
        pool_free(pool_head_quic_stream_buf, *stream_buf);
@@ -412,10 +407,7 @@ void qc_stream_desc_free(struct qc_stream_desc *stream, int closing)
                        pool_free(pool_head_quic_stream_ack, ack);
                }
 
-               if (buf->sbuf)
-                       pool_free(pool_head_sbuf, buf->buf.area);
-               else
-                       b_free(&buf->buf);
+               b_free(&buf->buf);
 
                eb64_delete(&buf->offset_node);
                pool_free(pool_head_quic_stream_buf, buf);
@@ -461,7 +453,7 @@ struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream,
        stream->buf->buf = BUF_NULL;
        stream->buf->offset_node.key = offset;
 
-       if (!small) {
+       if (!small || !global.tune.bufsize_small) {
                stream->buf->sbuf = 0;
                if (!b_alloc(&stream->buf->buf, DB_MUX_TX)) {
                        pool_free(pool_head_quic_stream_buf, stream->buf);
@@ -472,7 +464,7 @@ struct buffer *qc_stream_buf_alloc(struct qc_stream_desc *stream,
        else {
                char *area;
 
-               if (!(area = pool_alloc(pool_head_sbuf))) {
+               if (!(area = pool_alloc(pool_head_small_buffer))) {
                        pool_free(pool_head_quic_stream_buf, stream->buf);
                        stream->buf = NULL;
                        return NULL;
@@ -502,7 +494,7 @@ struct buffer *qc_stream_buf_realloc(struct qc_stream_desc *stream)
        BUG_ON(b_data(&stream->buf->buf));
 
        /* Release buffer */
-       pool_free(pool_head_sbuf, stream->buf->buf.area);
+       b_free(&stream->buf->buf);
        stream->buf->buf = BUF_NULL;
        stream->buf->sbuf = 0;
 
@@ -536,23 +528,3 @@ void qc_stream_buf_release(struct qc_stream_desc *stream)
        if (stream->notify_room && room)
                stream->notify_room(stream, room);
 }
-
-static int create_sbuf_pool(void)
-{
-       if (global.tune.bufsize_small > global.tune.bufsize) {
-               ha_warning("invalid small buffer size %d bytes which is greater to default bufsize %d bytes.\n",
-                          global.tune.bufsize_small, global.tune.bufsize);
-               return ERR_FATAL|ERR_ABORT;
-       }
-
-       pool_head_sbuf = create_pool("sbuf", global.tune.bufsize_small,
-                                    MEM_F_SHARED|MEM_F_EXACT);
-       if (!pool_head_sbuf) {
-               ha_warning("error on small buffer pool allocation.\n");
-               return ERR_FATAL|ERR_ABORT;
-       }
-
-       return ERR_NONE;
-}
-
-REGISTER_POST_CHECK(create_sbuf_pool);