From: Christopher Faulet Date: Tue, 3 Feb 2026 06:45:03 +0000 (+0100) Subject: MEDIUM: cache: Don't rely on a chunk to store messages payload X-Git-Tag: v3.4-dev5~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5965a6e1d2afa8041c4b518f878f3d22066e20e4;p=thirdparty%2Fhaproxy.git MEDIUM: cache: Don't rely on a chunk to store messages payload When the response payload is stored in the cache, we can avoid to use a trash chunk as temporary space area before copying everything in the cache in one call. Instead we can directly write each HTX block in the cache, one by one. It should not be an issue because, most of time, there is only one DATA block. This commit depends on "BUG/MEDIUM: shctx: Use the next block when data exactly filled a block". --- diff --git a/src/cache.c b/src/cache.c index 5fd254059..fd3d7c5d7 100644 --- a/src/cache.c +++ b/src/cache.c @@ -755,7 +755,6 @@ cache_store_http_payload(struct stream *s, struct filter *filter, struct http_ms struct htx_blk *blk; struct shared_block *fb; struct htx_ret htxret; - size_t data_len = 0; unsigned int orig_len, to_forward; int ret; @@ -767,7 +766,6 @@ cache_store_http_payload(struct stream *s, struct filter *filter, struct http_ms return len; } - chunk_reset(&trash); orig_len = len; to_forward = 0; @@ -789,10 +787,17 @@ cache_store_http_payload(struct stream *s, struct filter *filter, struct http_ms v = isttrim(v, len); info = (type << 28) + v.len; - chunk_memcat(&trash, (char *)&info, sizeof(info)); - chunk_istcat(&trash, v); + fb = shctx_row_reserve_hot(shctx, st->first_block, sizeof(info)+v.len); + if (!fb) + goto no_cache; + ret = shctx_row_data_append(shctx, st->first_block, (unsigned char *)&info, sizeof(info)); + if (ret < 0) + goto no_cache; + ret = shctx_row_data_append(shctx, st->first_block, (unsigned char *)istptr(v), istlen(v)); + if (ret < 0) + goto no_cache; + ASSUME_NONNULL((struct cache_entry *)st->first_block->data)->body_size += v.len; to_forward += v.len; - data_len += v.len; len -= v.len; break; @@ -804,8 +809,15 @@ cache_store_http_payload(struct stream *s, struct filter *filter, struct http_ms if (sz > len) goto end; - chunk_memcat(&trash, (char *)&blk->info, sizeof(blk->info)); - chunk_memcat(&trash, htx_get_blk_ptr(htx, blk), sz); + fb = shctx_row_reserve_hot(shctx, st->first_block, sizeof(blk->info)+sz); + if (!fb) + goto no_cache; + ret = shctx_row_data_append(shctx, st->first_block, (unsigned char *)&(blk->info), sizeof(blk->info)); + if (ret < 0) + goto no_cache; + ret = shctx_row_data_append(shctx, st->first_block, (unsigned char *)htx_get_blk_ptr(htx, blk), sz); + if (ret < 0) + goto no_cache; to_forward += sz; len -= sz; break; @@ -815,18 +827,6 @@ cache_store_http_payload(struct stream *s, struct filter *filter, struct http_ms } end: - - fb = shctx_row_reserve_hot(shctx, st->first_block, trash.data); - if (!fb) { - goto no_cache; - } - - ASSUME_NONNULL((struct cache_entry *)st->first_block->data)->body_size += data_len; - ret = shctx_row_data_append(shctx, st->first_block, - (unsigned char *)b_head(&trash), b_data(&trash)); - if (ret < 0) - goto no_cache; - return to_forward; no_cache: