talloc_pooled_object patchset
Volker Lendecke
Volker.Lendecke at SerNet.DE
Mon Aug 5 23:47:22 MDT 2013
Hi!
Attached find a patchset that implements
talloc_pooled_object. The idea is basically that
tevent_req_create only does one malloc instead of three, and
for example cp_smb_filename also does just one:
talloc_pooled_object allocates a basic object as a pool
similar to talloc(). Additionally, this object itself is a
pool that will host num_members of user-visible size
member_size.
A very simple test fetching a 1G file with aio read size = 1
with smbclient according to valgrind's callgrind gives a
reduction of user-space instructions of roughly 7%. In more
complex tests, I think this has also the potential to reduce
malloc fragmentation.
This is not yet ready for pushing, with valgrind I still see
invalid writes. But I suspect this is due to invalid
valgrind instrumentation, this patchset does survive
autobuild.
Comments?
Volker
P.S.: To me, this is really complex stuff, so if you have
time and want to get your hands dirty, please do a thorough
review!
--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From f60ae1a97b7634e34e6e68fa3a797e98ed19f9da Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 5 May 2013 17:39:45 +0200
Subject: [PATCH 01/10] talloc: Slightly simplify __talloc
We don't do the for loop anyway if limit==NULL
---
lib/talloc/talloc.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 76f0aee..9a27b78 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -565,6 +565,7 @@ static inline void *__talloc(const void *context, size_t size)
{
struct talloc_chunk *tc = NULL;
struct talloc_memlimit *limit = NULL;
+ struct talloc_memlimit *l;
if (unlikely(context == NULL)) {
context = null_context;
@@ -596,12 +597,8 @@ static inline void *__talloc(const void *context, size_t size)
tc->pool = NULL;
}
- if (limit != NULL) {
- struct talloc_memlimit *l;
-
- for (l = limit; l != NULL; l = l->upper) {
- l->cur_size += TC_HDR_SIZE+size;
- }
+ for (l = limit; l != NULL; l = l->upper) {
+ l->cur_size += TC_HDR_SIZE+size;
}
tc->limit = limit;
--
1.7.9.5
From 59f5c7dd906e572b2a8c2ed426ed7f60a9483850 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 18 Apr 2013 10:58:40 +0200
Subject: [PATCH 02/10] talloc: Decouple the dual use of chunk->pool
If we want nested pools, we will have pools that are pool members. So
we will have to have a separate "next object" pointer for pools. As
we have struct talloc_pool_chunk now, this additional pointer does not
affect normal talloc objects.
---
lib/talloc/talloc.c | 48 +++++++++++++++++++++++-------------------------
1 file changed, 23 insertions(+), 25 deletions(-)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 9a27b78..cf31d67 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -241,6 +241,8 @@ static bool talloc_memlimit_update(struct talloc_memlimit *limit,
typedef int (*talloc_destructor_t)(void *);
+union talloc_pool_chunk;
+
struct talloc_chunk {
struct talloc_chunk *next, *prev;
struct talloc_chunk *parent, *child;
@@ -260,17 +262,12 @@ struct talloc_chunk {
struct talloc_memlimit *limit;
/*
- * "pool" has dual use:
- *
- * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
- * marks the end of the currently allocated area.
- *
- * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
+ * For members of a pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
* is a pointer to the struct talloc_chunk of the pool that it was
* allocated from. This way children can quickly find the pool to chew
* from.
*/
- void *pool;
+ union talloc_pool_chunk *pool;
};
/* 16 byte alignment seems to keep everyone happy */
@@ -463,6 +460,7 @@ union talloc_pool_chunk {
* on 32-bit platforms. */
struct tc_pool_hdr {
struct talloc_chunk c;
+ void *next;
unsigned int object_count;
} hdr;
/* This makes it always 16 byte aligned. */
@@ -476,7 +474,7 @@ static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
{
- return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
+ return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.next;
}
static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
@@ -496,11 +494,11 @@ static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
size_t flen = tc_pool_space_left(pool_tc);
if (unlikely(talloc_fill.enabled)) {
- memset(pool_tc->hdr.c.pool, talloc_fill.fill_value, flen);
+ memset(pool_tc->hdr.next, talloc_fill.fill_value, flen);
}
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
- VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.c.pool, flen);
+ VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.next, flen);
#endif
}
@@ -524,7 +522,7 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
pool_ctx = (union talloc_pool_chunk *)parent;
}
else if (parent->flags & TALLOC_FLAG_POOLMEM) {
- pool_ctx = (union talloc_pool_chunk *)parent->pool;
+ pool_ctx = parent->pool;
}
if (pool_ctx == NULL) {
@@ -542,13 +540,13 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
return NULL;
}
- result = (struct talloc_chunk *)pool_ctx->hdr.c.pool;
+ result = (struct talloc_chunk *)pool_ctx->hdr.next;
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED(result, size);
#endif
- pool_ctx->hdr.c.pool = (void *)((char *)result + chunk_size);
+ pool_ctx->hdr.next = (void *)((char *)result + chunk_size);
result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
result->pool = pool_ctx;
@@ -650,7 +648,7 @@ _PUBLIC_ void *talloc_pool(const void *context, size_t size)
return NULL;
}
pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
- pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
+ pool_tc->hdr.next = tc_pool_first_chunk(pool_tc);
pool_tc->hdr.object_count = 1;
@@ -760,7 +758,7 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
union talloc_pool_chunk *pool;
void *next_tc;
- pool = (union talloc_pool_chunk *)tc->pool;
+ pool = tc->pool;
next_tc = tc_next_chunk(tc);
tc->flags |= TALLOC_FLAG_FREE;
@@ -789,7 +787,7 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
* the rest is available for new objects
* again.
*/
- pool->hdr.c.pool = tc_pool_first_chunk(pool);
+ pool->hdr.next = tc_pool_first_chunk(pool);
tc_invalidate_pool(pool);
return;
}
@@ -807,13 +805,13 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
return;
}
- if (pool->hdr.c.pool == next_tc) {
+ if (pool->hdr.next == next_tc) {
/*
* if pool->pool still points to end of
* 'tc' (which is stored in the 'next_tc' variable),
* we can reclaim the memory of 'tc'.
*/
- pool->hdr.c.pool = tc;
+ pool->hdr.next = tc;
return;
}
@@ -1535,7 +1533,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
/* handle realloc inside a talloc_pool */
if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
- pool_tc = (union talloc_pool_chunk *)tc->pool;
+ pool_tc = tc->pool;
}
#if (ALWAYS_REALLOC == 0)
@@ -1545,9 +1543,9 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
void *next_tc = tc_next_chunk(tc);
TC_INVALIDATE_SHRINK_CHUNK(tc, size);
tc->size = size;
- if (next_tc == pool_tc->hdr.c.pool) {
+ if (next_tc == pool_tc->hdr.next) {
/* note: tc->size has changed, so this works */
- pool_tc->hdr.c.pool = tc_next_chunk(tc);
+ pool_tc->hdr.next = tc_next_chunk(tc);
}
return ptr;
} else if ((tc->size - size) < 1024) {
@@ -1634,11 +1632,11 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
* because we want to invalidate the padding
* too.
*/
- pool_tc->hdr.c.pool = new_used + (char *)new_ptr;
+ pool_tc->hdr.next = new_used + (char *)new_ptr;
tc_invalidate_pool(pool_tc);
/* now the aligned pointer */
- pool_tc->hdr.c.pool = new_chunk_size + (char *)new_ptr;
+ pool_tc->hdr.next = new_chunk_size + (char *)new_ptr;
goto got_new_ptr;
}
@@ -1660,7 +1658,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
return ptr;
}
- if (next_tc == pool_tc->hdr.c.pool) {
+ if (next_tc == pool_tc->hdr.next) {
/*
* optimize for the case where 'tc' is the last
* chunk in the pool.
@@ -1679,7 +1677,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
return NULL;
}
tc->size = size;
- pool_tc->hdr.c.pool = tc_next_chunk(tc);
+ pool_tc->hdr.next = tc_next_chunk(tc);
return ptr;
}
}
--
1.7.9.5
From dd13fcaf26a1c7278137af4e9fdf654284f35ad9 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 5 May 2013 17:30:34 +0200
Subject: [PATCH 03/10] talloc: Introduce __talloc_with_prefix
This will allow to exchange the extra talloc pool header with the
talloc_chunk structure
---
lib/talloc/talloc.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index cf31d67..376da09 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -507,7 +507,7 @@ static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
*/
static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
- size_t size)
+ size_t size, size_t prefix_len)
{
union talloc_pool_chunk *pool_ctx = NULL;
size_t space_left;
@@ -534,13 +534,14 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
/*
* Align size to 16 bytes
*/
- chunk_size = TC_ALIGN16(size);
+ chunk_size = TC_ALIGN16(size + prefix_len);
if (space_left < chunk_size) {
return NULL;
}
- result = (struct talloc_chunk *)pool_ctx->hdr.next;
+ result = (struct talloc_chunk *)
+ ((char *)pool_ctx->hdr.next + prefix_len);
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED(result, size);
@@ -559,11 +560,13 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
/*
Allocate a bit of memory as a child of an existing pointer
*/
-static inline void *__talloc(const void *context, size_t size)
+static inline void *__talloc_with_prefix(const void *context, size_t size,
+ size_t prefix_len)
{
struct talloc_chunk *tc = NULL;
struct talloc_memlimit *limit = NULL;
struct talloc_memlimit *l;
+ size_t total_len;
if (unlikely(context == NULL)) {
context = null_context;
@@ -573,6 +576,8 @@ static inline void *__talloc(const void *context, size_t size)
return NULL;
}
+ total_len = TC_HDR_SIZE + size;
+
if (context != NULL) {
struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
@@ -580,23 +585,25 @@ static inline void *__talloc(const void *context, size_t size)
limit = ptc->limit;
}
- if (!talloc_memlimit_check(limit, (TC_HDR_SIZE+size))) {
+ if (!talloc_memlimit_check(limit, total_len)) {
errno = ENOMEM;
return NULL;
}
- tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
+ tc = talloc_alloc_pool(ptc, total_len, prefix_len);
}
+ total_len += prefix_len;
+
if (tc == NULL) {
- tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
+ tc = (struct talloc_chunk *)malloc(total_len);
if (unlikely(tc == NULL)) return NULL;
tc->flags = TALLOC_MAGIC;
tc->pool = NULL;
}
for (l = limit; l != NULL; l = l->upper) {
- l->cur_size += TC_HDR_SIZE+size;
+ l->cur_size += total_len;
}
tc->limit = limit;
@@ -626,6 +633,11 @@ static inline void *__talloc(const void *context, size_t size)
return TC_PTR_FROM_CHUNK(tc);
}
+static inline void *__talloc(const void *context, size_t size)
+{
+ return __talloc_with_prefix(context, size, 0);
+}
+
/*
* Create a talloc pool
*/
@@ -1577,7 +1589,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
#if ALWAYS_REALLOC
if (pool_tc) {
- new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
+ new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
pool_tc->hdr.object_count--;
if (new_ptr == NULL) {
@@ -1682,7 +1694,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
}
}
- new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
+ new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
if (new_ptr == NULL) {
new_ptr = malloc(TC_HDR_SIZE+size);
--
1.7.9.5
From 4b6dc7b7aba851c41c8887e06f8449b3962b8e74 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 8 May 2013 14:26:48 +0200
Subject: [PATCH 04/10] talloc: Put pool-specific data before the cunk
This is a preparation to make talloc pool real objects themselves
---
lib/talloc/talloc.c | 176 +++++++++++++++++++++++++++++----------------------
1 file changed, 99 insertions(+), 77 deletions(-)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 376da09..1d37f67 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -241,7 +241,7 @@ static bool talloc_memlimit_update(struct talloc_memlimit *limit,
typedef int (*talloc_destructor_t)(void *);
-union talloc_pool_chunk;
+struct talloc_pool_hdr;
struct talloc_chunk {
struct talloc_chunk *next, *prev;
@@ -267,7 +267,7 @@ struct talloc_chunk {
* allocated from. This way children can quickly find the pool to chew
* from.
*/
- union talloc_pool_chunk *pool;
+ struct talloc_pool_hdr *pool;
};
/* 16 byte alignment seems to keep everyone happy */
@@ -455,31 +455,37 @@ _PUBLIC_ const char *talloc_parent_name(const void *ptr)
memory footprint of each talloc chunk by those 16 bytes.
*/
-union talloc_pool_chunk {
- /* This lets object_count nestle into 16-byte padding of talloc_chunk,
- * on 32-bit platforms. */
- struct tc_pool_hdr {
- struct talloc_chunk c;
- void *next;
- unsigned int object_count;
- } hdr;
- /* This makes it always 16 byte aligned. */
- char pad[TC_ALIGN16(sizeof(struct tc_pool_hdr))];
+struct talloc_pool_hdr {
+ void *end;
+ unsigned int object_count;
};
-static void *tc_pool_end(union talloc_pool_chunk *pool_tc)
+#define TP_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_pool_hdr))
+
+static struct talloc_pool_hdr *talloc_pool_from_chunk(struct talloc_chunk *c)
{
- return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
+ return (struct talloc_pool_hdr *)((char *)c - TP_HDR_SIZE);
}
-static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
+static struct talloc_chunk *talloc_chunk_from_pool(struct talloc_pool_hdr *h)
{
- return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.next;
+ return (struct talloc_chunk *)((char *)h + TP_HDR_SIZE);
}
-static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
+static void *tc_pool_end(struct talloc_pool_hdr *pool_hdr)
{
- return pool_tc + 1;
+ struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
+ return (char *)tc + TC_HDR_SIZE + tc->size;
+}
+
+static size_t tc_pool_space_left(struct talloc_pool_hdr *pool_hdr)
+{
+ return (char *)tc_pool_end(pool_hdr) - (char *)pool_hdr->end;
+}
+
+static void *tc_pool_first_chunk(struct talloc_pool_hdr *pool_hdr)
+{
+ return TC_PTR_FROM_CHUNK(talloc_chunk_from_pool(pool_hdr));
}
/* If tc is inside a pool, this gives the next neighbour. */
@@ -489,16 +495,16 @@ static void *tc_next_chunk(struct talloc_chunk *tc)
}
/* Mark the whole remaining pool as not accessable */
-static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
+static void tc_invalidate_pool(struct talloc_pool_hdr *pool_hdr)
{
- size_t flen = tc_pool_space_left(pool_tc);
+ size_t flen = tc_pool_space_left(pool_hdr);
if (unlikely(talloc_fill.enabled)) {
- memset(pool_tc->hdr.next, talloc_fill.fill_value, flen);
+ memset(pool_hdr->end, talloc_fill.fill_value, flen);
}
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
- VALGRIND_MAKE_MEM_NOACCESS(pool_tc->hdr.next, flen);
+ VALGRIND_MAKE_MEM_NOACCESS(pool_hdr->end, flen);
#endif
}
@@ -509,7 +515,7 @@ static void tc_invalidate_pool(union talloc_pool_chunk *pool_tc)
static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
size_t size, size_t prefix_len)
{
- union talloc_pool_chunk *pool_ctx = NULL;
+ struct talloc_pool_hdr *pool_hdr = NULL;
size_t space_left;
struct talloc_chunk *result;
size_t chunk_size;
@@ -519,17 +525,17 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
}
if (parent->flags & TALLOC_FLAG_POOL) {
- pool_ctx = (union talloc_pool_chunk *)parent;
+ pool_hdr = talloc_pool_from_chunk(parent);
}
else if (parent->flags & TALLOC_FLAG_POOLMEM) {
- pool_ctx = parent->pool;
+ pool_hdr = parent->pool;
}
- if (pool_ctx == NULL) {
+ if (pool_hdr == NULL) {
return NULL;
}
- space_left = tc_pool_space_left(pool_ctx);
+ space_left = tc_pool_space_left(pool_hdr);
/*
* Align size to 16 bytes
@@ -540,19 +546,18 @@ static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
return NULL;
}
- result = (struct talloc_chunk *)
- ((char *)pool_ctx->hdr.next + prefix_len);
+ result = (struct talloc_chunk *)((char *)pool_hdr->end + prefix_len);
#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
- VALGRIND_MAKE_MEM_UNDEFINED(result, size);
+ VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, chunk_size);
#endif
- pool_ctx->hdr.next = (void *)((char *)result + chunk_size);
+ pool_hdr->end = (void *)((char *)pool_hdr->end + chunk_size);
result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
- result->pool = pool_ctx;
+ result->pool = pool_hdr;
- pool_ctx->hdr.object_count++;
+ pool_hdr->object_count++;
return result;
}
@@ -596,8 +601,13 @@ static inline void *__talloc_with_prefix(const void *context, size_t size,
total_len += prefix_len;
if (tc == NULL) {
- tc = (struct talloc_chunk *)malloc(total_len);
- if (unlikely(tc == NULL)) return NULL;
+ char *ptr = malloc(total_len);
+
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+
+ tc = (struct talloc_chunk *)(ptr + prefix_len);
tc->flags = TALLOC_MAGIC;
tc->pool = NULL;
}
@@ -644,27 +654,32 @@ static inline void *__talloc(const void *context, size_t size)
_PUBLIC_ void *talloc_pool(const void *context, size_t size)
{
- union talloc_pool_chunk *pool_tc;
- void *result = __talloc(context, sizeof(*pool_tc) - TC_HDR_SIZE + size);
+ struct talloc_chunk *tc;
+ struct talloc_pool_hdr *pool_hdr;
+ void *result;
+
+ result = __talloc_with_prefix(context, size, TP_HDR_SIZE);
if (unlikely(result == NULL)) {
return NULL;
}
- pool_tc = (union talloc_pool_chunk *)talloc_chunk_from_ptr(result);
- if (unlikely(pool_tc->hdr.c.flags & TALLOC_FLAG_POOLMEM)) {
+ tc = talloc_chunk_from_ptr(result);
+ pool_hdr = talloc_pool_from_chunk(tc);
+
+ if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
/* We don't handle this correctly, so fail. */
talloc_log("talloc: cannot allocate pool off another pool %s\n",
talloc_get_name(context));
talloc_free(result);
return NULL;
}
- pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
- pool_tc->hdr.next = tc_pool_first_chunk(pool_tc);
+ tc->flags |= TALLOC_FLAG_POOL;
- pool_tc->hdr.object_count = 1;
+ pool_hdr->object_count = 1;
+ pool_hdr->end = result;
- tc_invalidate_pool(pool_tc);
+ tc_invalidate_pool(pool_hdr);
return result;
}
@@ -767,10 +782,12 @@ static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
const char *location)
{
- union talloc_pool_chunk *pool;
+ struct talloc_pool_hdr *pool;
+ struct talloc_chunk *pool_tc;
void *next_tc;
pool = tc->pool;
+ pool_tc = talloc_chunk_from_pool(pool);
next_tc = tc_next_chunk(tc);
tc->flags |= TALLOC_FLAG_FREE;
@@ -783,15 +800,15 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
TC_INVALIDATE_FULL_CHUNK(tc);
- if (unlikely(pool->hdr.object_count == 0)) {
+ if (unlikely(pool->object_count == 0)) {
talloc_abort("Pool object count zero!");
return;
}
- pool->hdr.object_count--;
+ pool->object_count--;
- if (unlikely(pool->hdr.object_count == 1
- && !(pool->hdr.c.flags & TALLOC_FLAG_FREE))) {
+ if (unlikely(pool->object_count == 1
+ && !(pool_tc->flags & TALLOC_FLAG_FREE))) {
/*
* if there is just one object left in the pool
* and pool->flags does not have TALLOC_FLAG_FREE,
@@ -799,31 +816,31 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
* the rest is available for new objects
* again.
*/
- pool->hdr.next = tc_pool_first_chunk(pool);
+ pool->end = tc_pool_first_chunk(pool);
tc_invalidate_pool(pool);
return;
}
- if (unlikely(pool->hdr.object_count == 0)) {
+ if (unlikely(pool->object_count == 0)) {
/*
* we mark the freed memory with where we called the free
* from. This means on a double free error we can report where
* the first free came from
*/
- pool->hdr.c.name = location;
+ pool_tc->name = location;
- TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
+ TC_INVALIDATE_FULL_CHUNK(pool_tc);
free(pool);
return;
}
- if (pool->hdr.next == next_tc) {
+ if (pool->end == next_tc) {
/*
* if pool->pool still points to end of
* 'tc' (which is stored in the 'next_tc' variable),
* we can reclaim the memory of 'tc'.
*/
- pool->hdr.next = tc;
+ pool->end = tc;
return;
}
@@ -942,21 +959,23 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
tc->name = location;
if (tc->flags & TALLOC_FLAG_POOL) {
- union talloc_pool_chunk *pool = (union talloc_pool_chunk *)tc;
+ struct talloc_pool_hdr *pool;
- if (unlikely(pool->hdr.object_count == 0)) {
+ pool = talloc_pool_from_chunk(tc);
+
+ if (unlikely(pool->object_count == 0)) {
talloc_abort("Pool object count zero!");
return 0;
}
- pool->hdr.object_count--;
+ pool->object_count--;
- if (likely(pool->hdr.object_count != 0)) {
+ if (likely(pool->object_count != 0)) {
return 0;
}
TC_INVALIDATE_FULL_CHUNK(tc);
- free(tc);
+ free(pool);
return 0;
}
@@ -1507,7 +1526,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
struct talloc_chunk *tc;
void *new_ptr;
bool malloced = false;
- union talloc_pool_chunk *pool_tc = NULL;
+ struct talloc_pool_hdr *pool_hdr = NULL;
/* size zero is equivalent to free() */
if (unlikely(size == 0)) {
@@ -1545,19 +1564,19 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
/* handle realloc inside a talloc_pool */
if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
- pool_tc = tc->pool;
+ pool_hdr = tc->pool;
}
#if (ALWAYS_REALLOC == 0)
/* don't shrink if we have less than 1k to gain */
if (size < tc->size && tc->limit == NULL) {
- if (pool_tc) {
+ if (pool_hdr) {
void *next_tc = tc_next_chunk(tc);
TC_INVALIDATE_SHRINK_CHUNK(tc, size);
tc->size = size;
- if (next_tc == pool_tc->hdr.next) {
+ if (next_tc == pool_hdr->end) {
/* note: tc->size has changed, so this works */
- pool_tc->hdr.next = tc_next_chunk(tc);
+ pool_hdr->end = tc_next_chunk(tc);
}
return ptr;
} else if ((tc->size - size) < 1024) {
@@ -1588,9 +1607,9 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
tc->flags |= TALLOC_FLAG_FREE;
#if ALWAYS_REALLOC
- if (pool_tc) {
+ if (pool_hdr) {
new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE, 0);
- pool_tc->hdr.object_count--;
+ pool_hdr->object_count--;
if (new_ptr == NULL) {
new_ptr = malloc(TC_HDR_SIZE+size);
@@ -1609,15 +1628,17 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
}
}
#else
- if (pool_tc) {
+ if (pool_hdr) {
+ struct talloc_chunk *pool_tc;
void *next_tc = tc_next_chunk(tc);
size_t old_chunk_size = TC_ALIGN16(TC_HDR_SIZE + tc->size);
size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
size_t space_needed;
size_t space_left;
- unsigned int chunk_count = pool_tc->hdr.object_count;
+ unsigned int chunk_count = pool_hdr->object_count;
- if (!(pool_tc->hdr.c.flags & TALLOC_FLAG_FREE)) {
+ pool_tc = talloc_chunk_from_pool(pool_hdr);
+ if (!(pool_tc->flags & TALLOC_FLAG_FREE)) {
chunk_count -= 1;
}
@@ -1626,9 +1647,9 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
* optimize for the case where 'tc' is the only
* chunk in the pool.
*/
- char *start = tc_pool_first_chunk(pool_tc);
+ char *start = tc_pool_first_chunk(pool_hdr);
space_needed = new_chunk_size;
- space_left = (char *)tc_pool_end(pool_tc) - start;
+ space_left = (char *)tc_pool_end(pool_hdr) - start;
if (space_left >= space_needed) {
size_t old_used = TC_HDR_SIZE + tc->size;
@@ -1644,11 +1665,12 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
* because we want to invalidate the padding
* too.
*/
- pool_tc->hdr.next = new_used + (char *)new_ptr;
- tc_invalidate_pool(pool_tc);
+ pool_hdr->end = new_used + (char *)new_ptr;
+ tc_invalidate_pool(pool_hdr);
/* now the aligned pointer */
- pool_tc->hdr.next = new_chunk_size + (char *)new_ptr;
+ pool_hdr->end =
+ new_chunk_size + (char *)new_ptr;
goto got_new_ptr;
}
@@ -1670,13 +1692,13 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
return ptr;
}
- if (next_tc == pool_tc->hdr.next) {
+ if (next_tc == pool_hdr->end) {
/*
* optimize for the case where 'tc' is the last
* chunk in the pool.
*/
space_needed = new_chunk_size - old_chunk_size;
- space_left = tc_pool_space_left(pool_tc);
+ space_left = tc_pool_space_left(pool_hdr);
if (space_left >= space_needed) {
TC_UNDEFINE_GROW_CHUNK(tc, size);
@@ -1689,7 +1711,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons
return NULL;
}
tc->size = size;
- pool_tc->hdr.next = tc_next_chunk(tc);
+ pool_hdr->end = tc_next_chunk(tc);
return ptr;
}
}
--
1.7.9.5
From 0453a46bcb458e961abc13c299bc31d06b37422c Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 22 May 2013 17:18:01 +0200
Subject: [PATCH 05/10] talloc: Add a separate pool size
This is necessary to allow talloc pools to be objects on their own. It
is an incompatible change in the sense that talloc_get_size(pool) now
returns 0 instead of the pool size. When the talloc_pooled_object()
call is added, this will start to make sense again.
Maybe we should add a talloc_pool_size call? Or is that overkill?
---
lib/talloc/talloc.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 1d37f67..94e63fb 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -458,6 +458,7 @@ _PUBLIC_ const char *talloc_parent_name(const void *ptr)
struct talloc_pool_hdr {
void *end;
unsigned int object_count;
+ size_t poolsize;
};
#define TP_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_pool_hdr))
@@ -475,7 +476,7 @@ static struct talloc_chunk *talloc_chunk_from_pool(struct talloc_pool_hdr *h)
static void *tc_pool_end(struct talloc_pool_hdr *pool_hdr)
{
struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
- return (char *)tc + TC_HDR_SIZE + tc->size;
+ return (char *)tc + TC_HDR_SIZE + pool_hdr->poolsize;
}
static size_t tc_pool_space_left(struct talloc_pool_hdr *pool_hdr)
@@ -483,17 +484,18 @@ static size_t tc_pool_space_left(struct talloc_pool_hdr *pool_hdr)
return (char *)tc_pool_end(pool_hdr) - (char *)pool_hdr->end;
}
-static void *tc_pool_first_chunk(struct talloc_pool_hdr *pool_hdr)
-{
- return TC_PTR_FROM_CHUNK(talloc_chunk_from_pool(pool_hdr));
-}
-
/* If tc is inside a pool, this gives the next neighbour. */
static void *tc_next_chunk(struct talloc_chunk *tc)
{
return (char *)tc + TC_ALIGN16(TC_HDR_SIZE + tc->size);
}
+static void *tc_pool_first_chunk(struct talloc_pool_hdr *pool_hdr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
+ return tc_next_chunk(tc);
+}
+
/* Mark the whole remaining pool as not accessable */
static void tc_invalidate_pool(struct talloc_pool_hdr *pool_hdr)
{
@@ -674,10 +676,13 @@ _PUBLIC_ void *talloc_pool(const void *context, size_t size)
talloc_free(result);
return NULL;
}
+
tc->flags |= TALLOC_FLAG_POOL;
+ tc->size = 0;
pool_hdr->object_count = 1;
pool_hdr->end = result;
+ pool_hdr->poolsize = size;
tc_invalidate_pool(pool_hdr);
--
1.7.9.5
From f06844ee44bd88cca3d2c4e9e17a9165159a4c4d Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 9 May 2013 13:30:52 +0200
Subject: [PATCH 06/10] talloc: Allow nested pools
---
lib/talloc/talloc.c | 29 ++++++++++++++++-------------
lib/talloc/testsuite.c | 26 ++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 94e63fb..5431646 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -669,14 +669,6 @@ _PUBLIC_ void *talloc_pool(const void *context, size_t size)
tc = talloc_chunk_from_ptr(result);
pool_hdr = talloc_pool_from_chunk(tc);
- if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
- /* We don't handle this correctly, so fail. */
- talloc_log("talloc: cannot allocate pool off another pool %s\n",
- talloc_get_name(context));
- talloc_free(result);
- return NULL;
- }
-
tc->flags |= TALLOC_FLAG_POOL;
tc->size = 0;
@@ -835,7 +827,12 @@ static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
pool_tc->name = location;
TC_INVALIDATE_FULL_CHUNK(pool_tc);
- free(pool);
+
+ if (pool_tc->flags & TALLOC_FLAG_POOLMEM) {
+ _talloc_free_poolmem(pool_tc, location);
+ } else {
+ free(pool);
+ }
return;
}
@@ -865,6 +862,7 @@ static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
static inline int _talloc_free_internal(void *ptr, const char *location)
{
struct talloc_chunk *tc;
+ void *ptr_to_free;
if (unlikely(ptr == NULL)) {
return -1;
@@ -979,9 +977,14 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
return 0;
}
- TC_INVALIDATE_FULL_CHUNK(tc);
- free(pool);
- return 0;
+ /*
+ * With object_count==0, a pool becomes a normal piece of
+ * memory to free. If it's allocated inside a pool, it needs
+ * to be freed as poolmem, else it needs to be just freed.
+ */
+ ptr_to_free = pool;
+ } else {
+ ptr_to_free = tc;
}
if (tc->flags & TALLOC_FLAG_POOLMEM) {
@@ -990,7 +993,7 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
}
TC_INVALIDATE_FULL_CHUNK(tc);
- free(tc);
+ free(ptr_to_free);
return 0;
}
diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c
index d456cbb..5501d17 100644
--- a/lib/talloc/testsuite.c
+++ b/lib/talloc/testsuite.c
@@ -1267,6 +1267,30 @@ static bool test_pool_steal(void)
return true;
}
+static bool test_pool_nest(void)
+{
+ void *p1, *p2, *p3;
+ void *e = talloc_new(NULL);
+
+ p1 = talloc_pool(NULL, 1024);
+ torture_assert("talloc_pool", p1 != NULL, "failed");
+
+ p2 = talloc_pool(p1, 500);
+ torture_assert("talloc_pool", p2 != NULL, "failed");
+
+ p3 = talloc_size(p2, 10);
+
+ talloc_steal(e, p3);
+
+ talloc_free(p2);
+
+ talloc_free(p3);
+
+ talloc_free(p1);
+
+ return true;
+}
+
static bool test_free_ref_null_context(void)
{
void *p1, *p2, *p3;
@@ -1540,6 +1564,8 @@ bool torture_local_talloc(struct torture_context *tctx)
setlinebuf(stdout);
test_reset();
+ ret &= test_pool_nest();
+ test_reset();
ret &= test_ref1();
test_reset();
ret &= test_ref2();
--
1.7.9.5
From 2d7dc53f7d323680ee021d69120609e142f99ac9 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 9 May 2013 13:54:51 +0200
Subject: [PATCH 07/10] talloc: Add talloc_pooled_object
---
lib/talloc/ABI/pytalloc-util-2.0.9.sigs | 6 +++
lib/talloc/ABI/talloc-2.0.9.sigs | 64 +++++++++++++++++++++++++++++++
lib/talloc/talloc.c | 59 ++++++++++++++++++++++++++++
lib/talloc/talloc.h | 11 ++++++
lib/talloc/wscript | 2 +-
5 files changed, 141 insertions(+), 1 deletion(-)
create mode 100644 lib/talloc/ABI/pytalloc-util-2.0.9.sigs
create mode 100644 lib/talloc/ABI/talloc-2.0.9.sigs
diff --git a/lib/talloc/ABI/pytalloc-util-2.0.9.sigs b/lib/talloc/ABI/pytalloc-util-2.0.9.sigs
new file mode 100644
index 0000000..961c1a8
--- /dev/null
+++ b/lib/talloc/ABI/pytalloc-util-2.0.9.sigs
@@ -0,0 +1,6 @@
+pytalloc_CObject_FromTallocPtr: PyObject *(void *)
+pytalloc_Check: int (PyObject *)
+pytalloc_GetObjectType: PyTypeObject *(void)
+pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
+pytalloc_steal: PyObject *(PyTypeObject *, void *)
+pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *)
diff --git a/lib/talloc/ABI/talloc-2.0.9.sigs b/lib/talloc/ABI/talloc-2.0.9.sigs
new file mode 100644
index 0000000..eae12cc
--- /dev/null
+++ b/lib/talloc/ABI/talloc-2.0.9.sigs
@@ -0,0 +1,64 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_memlimit: int (const void *, size_t)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 5431646..8d8e621 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -681,6 +681,65 @@ _PUBLIC_ void *talloc_pool(const void *context, size_t size)
return result;
}
+_PUBLIC_ void *_talloc_pooled_object(const void *ctx, size_t size,
+ const char *name,
+ unsigned num_members, size_t member_size)
+{
+ size_t poolsize, member_slack, tmp;
+ struct talloc_chunk *tc;
+ struct talloc_pool_hdr *pool_hdr;
+ void *ret;
+
+ poolsize = size + member_size;
+
+ if ((poolsize < size) || (poolsize < member_size)) {
+ goto overflow;
+ }
+
+ if (num_members == UINT_MAX) {
+ goto overflow;
+ }
+ num_members += 1; /* the object body itself */
+
+ /*
+ * Alignment can increase the pool size by at most 15 bytes per object
+ * plus alignment for the object itself
+ */
+ member_slack = (TC_HDR_SIZE + TP_HDR_SIZE + 15) * num_members;
+ if (member_slack < num_members) {
+ goto overflow;
+ }
+
+ tmp = poolsize + member_slack;
+ if ((tmp < poolsize) || (tmp < member_slack)) {
+ goto overflow;
+ }
+ poolsize = tmp;
+
+ ret = talloc_pool(ctx, poolsize);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ tc = talloc_chunk_from_ptr(ret);
+ tc->size = size;
+
+ pool_hdr = talloc_pool_from_chunk(tc);
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+ VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, size);
+#endif
+ memset(pool_hdr->end, 0, size);
+
+ pool_hdr->end = ((char *)pool_hdr->end + TC_ALIGN16(size));
+
+ talloc_set_name_const(ret, name);
+ return ret;
+
+overflow:
+ return NULL;
+}
+
/*
setup a destructor to be called on free of a pointer
the destructor should return 0 on success, or -1 on failure.
diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h
index f3cbcd0..45af352 100644
--- a/lib/talloc/talloc.h
+++ b/lib/talloc/talloc.h
@@ -848,6 +848,17 @@ void *talloc_find_parent_bytype(const void *ptr, #type);
*/
void *talloc_pool(const void *context, size_t size);
+#ifdef DOXYGEN
+void *talloc_pooled_object(const void *ctx, #type,
+ unsigned num_members, size_t member_size);
+#else
+#define talloc_pooled_object(_ctx, _type, _num_members, _member_size) \
+ (_type *)_talloc_pooled_object((_ctx), sizeof(_type), #_type, \
+ (_num_members), (_member_size))
+void *_talloc_pooled_object(const void *ctx, size_t size, const char *name,
+ unsigned num_members, size_t member_size);
+#endif
+
/**
* @brief Free a talloc chunk and NULL out the pointer.
*
diff --git a/lib/talloc/wscript b/lib/talloc/wscript
index ecc5e24..8c13b1d 100644
--- a/lib/talloc/wscript
+++ b/lib/talloc/wscript
@@ -1,7 +1,7 @@
#!/usr/bin/env python
APPNAME = 'talloc'
-VERSION = '2.0.8'
+VERSION = '2.0.9'
blddir = 'bin'
--
1.7.9.5
From be189b0b2ae6f92080cfb8429e21c0c3816adf75 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 12 May 2013 09:22:23 +0200
Subject: [PATCH 08/10] talloc: Test the pooled object
---
lib/talloc/testsuite.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c
index 5501d17..be8f076 100644
--- a/lib/talloc/testsuite.c
+++ b/lib/talloc/testsuite.c
@@ -1291,6 +1291,40 @@ static bool test_pool_nest(void)
return true;
}
+struct pooled {
+ char *s1;
+ char *s2;
+ char *s3;
+};
+
+static bool test_pooled_object(void)
+{
+ struct pooled *p;
+ const char *s1 = "hello";
+ const char *s2 = "world";
+ const char *s3 = "";
+
+ p = talloc_pooled_object(NULL, struct pooled, 3,
+ strlen(s1)+strlen(s2)+strlen(s3)+3);
+
+ if (talloc_get_size(p) != sizeof(struct pooled)) {
+ return false;
+ }
+
+ p->s1 = talloc_strdup(p, s1);
+
+ TALLOC_FREE(p->s1);
+ p->s1 = talloc_strdup(p, s2);
+ TALLOC_FREE(p->s1);
+
+ p->s1 = talloc_strdup(p, s1);
+ p->s2 = talloc_strdup(p, s2);
+ p->s3 = talloc_strdup(p, s3);
+
+ TALLOC_FREE(p);
+ return true;
+}
+
static bool test_free_ref_null_context(void)
{
void *p1, *p2, *p3;
@@ -1564,6 +1598,8 @@ bool torture_local_talloc(struct torture_context *tctx)
setlinebuf(stdout);
test_reset();
+ ret &= test_pooled_object();
+ test_reset();
ret &= test_pool_nest();
test_reset();
ret &= test_ref1();
--
1.7.9.5
From cf4fea559a395322e658933c88c3f894135db1e8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 9 May 2013 13:55:08 +0200
Subject: [PATCH 09/10] smbd: Use talloc_pooled_object in cp_smb_filename
Requires new talloc
---
source3/lib/filename_util.c | 42 ++++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c
index 19ffcc3..ace09d9 100644
--- a/source3/lib/filename_util.c
+++ b/source3/lib/filename_util.c
@@ -161,39 +161,49 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
const struct smb_filename *in)
{
struct smb_filename *out;
+ size_t base_len = 0;
+ size_t stream_len = 0;
+ size_t lcomp_len = 0;
+ int num = 0;
/* stream_name must always be NULL if there is no stream. */
if (in->stream_name) {
SMB_ASSERT(in->stream_name[0] != '\0');
}
- out = talloc_zero(mem_ctx, struct smb_filename);
+ if (in->base_name != NULL) {
+ base_len = strlen(in->base_name) + 1;
+ num += 1;
+ }
+ if (in->stream_name != NULL) {
+ stream_len = strlen(in->stream_name) + 1;
+ num += 1;
+ }
+ if (in->original_lcomp != NULL) {
+ lcomp_len = strlen(in->original_lcomp) + 1;
+ num += 1;
+ }
+
+ out = talloc_pooled_object(mem_ctx, struct smb_filename,
+ num, stream_len + base_len + lcomp_len);
if (out == NULL) {
return NULL;
}
+
if (in->base_name != NULL) {
- out->base_name = talloc_strdup(out, in->base_name);
- if (out->base_name == NULL) {
- goto fail;
- }
+ out->base_name = talloc_memdup(
+ out, in->base_name, base_len);
}
if (in->stream_name != NULL) {
- out->stream_name = talloc_strdup(out, in->stream_name);
- if (out->stream_name == NULL) {
- goto fail;
- }
+ out->stream_name = talloc_memdup(
+ out, in->stream_name, stream_len);
}
if (in->original_lcomp != NULL) {
- out->original_lcomp = talloc_strdup(out, in->original_lcomp);
- if (out->original_lcomp == NULL) {
- goto fail;
- }
+ out->original_lcomp = talloc_memdup(
+ out, in->original_lcomp, lcomp_len);
}
out->st = in->st;
return out;
-fail:
- TALLOC_FREE(out);
- return NULL;
}
/****************************************************************************
--
1.7.9.5
From e863801ba74d770ab784515f82be2f5a7907bf1a Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 3 Aug 2013 15:49:59 +0200
Subject: [PATCH 10/10] tevent: Use talloc_pooled_object for tevent_req_create
---
lib/tevent/tevent_req.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c
index d8d0c5f..a280dd3 100644
--- a/lib/tevent/tevent_req.c
+++ b/lib/tevent/tevent_req.c
@@ -61,7 +61,9 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
void **ppdata = (void **)pdata;
void *data;
- req = talloc_zero(mem_ctx, struct tevent_req);
+ req = talloc_pooled_object(
+ mem_ctx, struct tevent_req, 2,
+ sizeof(struct tevent_immediate) + data_size);
if (req == NULL) {
return NULL;
}
--
1.7.9.5
More information about the samba-technical
mailing list