]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: compression: correctly report zlib_mem
authorWilly Tarreau <w@1wt.eu>
Wed, 24 Dec 2014 17:07:55 +0000 (18:07 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 24 Dec 2014 17:19:50 +0000 (18:19 +0100)
In zlib we track memory usage. The problem is that the way alloc_zlib()
and free_zlib() account for memory is different, resulting in variations
that can lead to negative zlib_mem being reported. The alloc() function
uses the requested size while the free() function uses the pool size. The
difference can happen when pools are shared with other pools of similar
size. The net effect is that zlib_mem can be reported negative with a
slowly decreasing count, and over the long term the limit will not be
enforced anymore.

The fix is simple : let's use the pool size in both cases, which is also
the exact value when it comes to memory usage.

This fix must be backported to 1.5.

src/compression.c

index 09bc4a6e9f2b50c5fff6921004cbae3f40314c92..3d6085e84ab446fd4ec4510dd3c18294fe443a02 100644 (file)
@@ -412,6 +412,7 @@ static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
        struct comp_ctx *ctx = opaque;
        static char round = 0; /* order in deflateInit2 */
        void *buf = NULL;
+       struct pool_head *pool = NULL;
 
        if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < (long)(items * size))
                goto end;
@@ -420,35 +421,40 @@ static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
                case 0:
                        if (zlib_pool_deflate_state == NULL)
                                zlib_pool_deflate_state = create_pool("zlib_state", size * items, MEM_F_SHARED);
-                       ctx->zlib_deflate_state = buf = pool_alloc2(zlib_pool_deflate_state);
+                       pool = zlib_pool_deflate_state;
+                       ctx->zlib_deflate_state = buf = pool_alloc2(pool);
                break;
 
                case 1:
                        if (zlib_pool_window == NULL)
                                zlib_pool_window = create_pool("zlib_window", size * items, MEM_F_SHARED);
-                       ctx->zlib_window = buf = pool_alloc2(zlib_pool_window);
+                       pool = zlib_pool_window;
+                       ctx->zlib_window = buf = pool_alloc2(pool);
                break;
 
                case 2:
                        if (zlib_pool_prev == NULL)
                                zlib_pool_prev = create_pool("zlib_prev", size * items, MEM_F_SHARED);
-                       ctx->zlib_prev = buf = pool_alloc2(zlib_pool_prev);
+                       pool = zlib_pool_prev;
+                       ctx->zlib_prev = buf = pool_alloc2(pool);
                break;
 
                case 3:
                        if (zlib_pool_head == NULL)
                                zlib_pool_head = create_pool("zlib_head", size * items, MEM_F_SHARED);
-                       ctx->zlib_head = buf = pool_alloc2(zlib_pool_head);
+                       pool = zlib_pool_head;
+                       ctx->zlib_head = buf = pool_alloc2(pool);
                break;
 
                case 4:
                        if (zlib_pool_pending_buf == NULL)
                                zlib_pool_pending_buf = create_pool("zlib_pending_buf", size * items, MEM_F_SHARED);
-                       ctx->zlib_pending_buf = buf = pool_alloc2(zlib_pool_pending_buf);
+                       pool = zlib_pool_pending_buf;
+                       ctx->zlib_pending_buf = buf = pool_alloc2(pool);
                break;
        }
        if (buf != NULL)
-               zlib_used_memory += items * size;
+               zlib_used_memory += pool->size;
 
 end: