From 079a5e628b535d4cb94e71a1899021986f3b657d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Aug 2013 12:36:23 -0700 Subject: [PATCH] Start to fix talloc memlimits with talloc pools. Add the functions: talloc_memlimit_grow(), talloc_memlimit_shrink(), talloc_memlimit_update_on_free(). as replacements for talloc_memlimit_update(). The interface to talloc_memlimit_update() is very hard to understand and use. The above functions are (to me) much clearer. The goal of these changes is to only update the memlimits on malloc/free/realloc, not on every pool allocation. That way we only count pool creation as allocation from any imposed limits, not allocation from an already created pool. Signed-off-by: Jeremy Allison Reviewed-by: Simo Sorce (cherry picked from commit fe790f6cbc9b888a8d613cfb515f0d0c76daad47) --- lib/talloc/talloc.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 76f0aeedfd4..067d46f97d3 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -238,6 +238,11 @@ struct talloc_memlimit { static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size); static bool talloc_memlimit_update(struct talloc_memlimit *limit, size_t old_size, size_t new_size); +static void talloc_memlimit_grow(struct talloc_memlimit *limit, + size_t size); +static void talloc_memlimit_shrink(struct talloc_memlimit *limit, + size_t size); +static void talloc_memlimit_update_on_free(struct talloc_chunk *tc); typedef int (*talloc_destructor_t)(void *); @@ -2564,6 +2569,73 @@ static bool talloc_memlimit_check(struct talloc_memlimit *limit, size_t size) return true; } +/* + Update memory limits when freeing a talloc_chunk. +*/ +static void talloc_memlimit_update_on_free(struct talloc_chunk *tc) +{ + if (!tc->limit) { + return; + } + + /* + * Pool entries don't count. Only the pools + * themselves are counted as part of the memory + * limits. + */ + if (tc->flags & TALLOC_FLAG_POOLMEM) { + return; + } + + /* + * If we are part of a memory limited context hierarchy + * we need to subtract the memory used from the counters + */ + + talloc_memlimit_shrink(tc->limit, tc->size+TC_HDR_SIZE); + + if (tc->limit->parent == tc) { + free(tc->limit); + } + + tc->limit = NULL; +} + +/* + Increase memory limit accounting after a malloc/realloc. +*/ +static void talloc_memlimit_grow(struct talloc_memlimit *limit, + size_t size) +{ + struct talloc_memlimit *l; + + for (l = limit; l != NULL; l = l->upper) { + size_t new_cur_size = l->cur_size + size; + if (new_cur_size < l->cur_size) { + talloc_abort("logic error in talloc_memlimit_grow\n"); + return; + } + l->cur_size = new_cur_size; + } +} + +/* + Decrease memory limit accounting after a free/realloc. +*/ +static void talloc_memlimit_shrink(struct talloc_memlimit *limit, + size_t size) +{ + struct talloc_memlimit *l; + + for (l = limit; l != NULL; l = l->upper) { + if (l->cur_size < size) { + talloc_abort("logic error in talloc_memlimit_shrink\n"); + return; + } + l->cur_size = l->cur_size - size; + } +} + static bool talloc_memlimit_update(struct talloc_memlimit *limit, size_t old_size, size_t new_size) { -- 2.11.4.GIT