[SCM] Samba Shared Repository - branch master updated
Volker Lendecke
vlendec at samba.org
Sun Sep 8 05:40:03 MDT 2013
The branch, master has been updated
via 8f4069c tevent: Use talloc_pooled_object for tevent_req_create
via 7f9bdab smbd: Use talloc_pooled_object in cp_smb_filename
via 256d10f talloc: Test the pooled object
via e82320e talloc: Add talloc_pooled_object
via 20ad6d7 talloc: Allow nested pools.
via a3d9099 talloc: Add a separate pool size
via b87c8fd talloc: Put pool-specific data before the chunk
via 9887f38 talloc: Introduce __talloc_with_prefix
via 1334c74 talloc: Decouple the dual use of chunk->pool
from 81f8b9c s3: include/smb : changing smb server version
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 8f4069c7cd10a143286c7a32c1b612380afd7c72
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 15:37:56 2013 -0700
tevent: Use talloc_pooled_object for tevent_req_create
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Autobuild-User(master): Volker Lendecke <vl at samba.org>
Autobuild-Date(master): Sun Sep 8 13:39:25 CEST 2013 on sn-devel-104
commit 7f9bdabda53b63497d67d844198a28bf3ba04693
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 15:34:44 2013 -0700
smbd: Use talloc_pooled_object in cp_smb_filename
Requires new talloc
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 256d10f5792a37d20cbb45f2af3f8578bd354110
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 15:30:38 2013 -0700
talloc: Test the pooled object
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit e82320e5197bcdd0330bc829c0963ad09854a36c
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 15:15:32 2013 -0700
talloc: Add talloc_pooled_object
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 20ad6d7aa3dc5e7db4d886202f757ac1f68287d4
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 14:52:28 2013 -0700
talloc: Allow nested pools.
Signed-off-by: Volker Lendecke <vl at samba.org>
Signed-off-by: Jeremy Allison <jra at samba.org>
commit a3d9099d9a96b36df21ee0733adc5210438fe9dc
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 14:20:20 2013 -0700
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?
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit b87c8fd435d1863d6efcec03830ecd85ddfcd7fb
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 14:08:43 2013 -0700
talloc: Put pool-specific data before the chunk
This is a preparation to make talloc pool real objects themselves.
Signed-off-by: Volker Lendecke <vl at samba.org>
Signed-off-by: Jeremy Allison <jra at samba.org>
commit 9887f387a10e94f71790c0c3c7dc5f8cde7e4eb2
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 12:18:26 2013 -0700
talloc: Introduce __talloc_with_prefix
This will allow to exchange the extra talloc pool header with the
talloc_chunk structure
Signed-off-by: Volker Lendecke <vl at samba.org>
Signed-off-by: Jeremy Allison <jra at samba.org>
commit 1334c745e1f2157b66e14f9d8b4f6f7750238717
Author: Volker Lendecke <vl at samba.org>
Date: Fri Sep 6 10:54:43 2013 -0700
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.
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
-----------------------------------------------------------------------
Summary of changes:
...oc-util-2.0.6.sigs => pytalloc-util-2.1.0.sigs} | 0
.../ABI/{talloc-2.0.8.sigs => talloc-2.1.0.sigs} | 1 +
lib/talloc/talloc.c | 346 ++++++++++++++------
lib/talloc/talloc.h | 40 +++-
lib/talloc/testsuite.c | 62 ++++
lib/talloc/wscript | 2 +-
lib/tevent/tevent_req.c | 5 +-
source3/lib/filename_util.c | 48 ++-
8 files changed, 379 insertions(+), 125 deletions(-)
copy lib/talloc/ABI/{pytalloc-util-2.0.6.sigs => pytalloc-util-2.1.0.sigs} (100%)
copy lib/talloc/ABI/{talloc-2.0.8.sigs => talloc-2.1.0.sigs} (97%)
Changeset truncated at 500 lines:
diff --git a/lib/talloc/ABI/pytalloc-util-2.0.6.sigs b/lib/talloc/ABI/pytalloc-util-2.1.0.sigs
similarity index 100%
copy from lib/talloc/ABI/pytalloc-util-2.0.6.sigs
copy to lib/talloc/ABI/pytalloc-util-2.1.0.sigs
diff --git a/lib/talloc/ABI/talloc-2.0.8.sigs b/lib/talloc/ABI/talloc-2.1.0.sigs
similarity index 97%
copy from lib/talloc/ABI/talloc-2.0.8.sigs
copy to lib/talloc/ABI/talloc-2.1.0.sigs
index 15a9e95..eae12cc 100644
--- a/lib/talloc/ABI/talloc-2.0.8.sigs
+++ b/lib/talloc/ABI/talloc-2.1.0.sigs
@@ -4,6 +4,7 @@ _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 *)
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 69d5a16..1cb4d7d 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -244,6 +244,8 @@ static void talloc_memlimit_update_on_free(struct talloc_chunk *tc);
typedef int (*talloc_destructor_t)(void *);
+struct talloc_pool_hdr;
+
struct talloc_chunk {
struct talloc_chunk *next, *prev;
struct talloc_chunk *parent, *child;
@@ -263,17 +265,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;
+ struct talloc_pool_hdr *pool;
};
/* 16 byte alignment seems to keep everyone happy */
@@ -461,30 +458,33 @@ _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;
- 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;
+ size_t poolsize;
};
-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 (struct talloc_pool_hdr *)((char *)c - TP_HDR_SIZE);
+}
+
+static struct talloc_chunk *talloc_chunk_from_pool(struct talloc_pool_hdr *h)
{
- return (char *)pool_tc + TC_HDR_SIZE + pool_tc->hdr.c.size;
+ return (struct talloc_chunk *)((char *)h + TP_HDR_SIZE);
}
-static size_t tc_pool_space_left(union talloc_pool_chunk *pool_tc)
+static void *tc_pool_end(struct talloc_pool_hdr *pool_hdr)
{
- return (char *)tc_pool_end(pool_tc) - (char *)pool_tc->hdr.c.pool;
+ struct talloc_chunk *tc = talloc_chunk_from_pool(pool_hdr);
+ return (char *)tc + TC_HDR_SIZE + pool_hdr->poolsize;
}
-static void *tc_pool_first_chunk(union talloc_pool_chunk *pool_tc)
+static size_t tc_pool_space_left(struct talloc_pool_hdr *pool_hdr)
{
- return pool_tc + 1;
+ return (char *)tc_pool_end(pool_hdr) - (char *)pool_hdr->end;
}
/* If tc is inside a pool, this gives the next neighbour. */
@@ -493,17 +493,23 @@ 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(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.c.pool, 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.c.pool, flen);
+ VALGRIND_MAKE_MEM_NOACCESS(pool_hdr->end, flen);
#endif
}
@@ -512,9 +518,9 @@ 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;
+ struct talloc_pool_hdr *pool_hdr = NULL;
size_t space_left;
struct talloc_chunk *result;
size_t chunk_size;
@@ -524,39 +530,39 @@ 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 = (union talloc_pool_chunk *)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
*/
- 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.c.pool;
+ 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.c.pool = (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;
}
@@ -564,10 +570,12 @@ 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;
+ size_t total_len = TC_HDR_SIZE + size + prefix_len;
if (unlikely(context == NULL)) {
context = null_context;
@@ -577,6 +585,10 @@ static inline void *__talloc(const void *context, size_t size)
return NULL;
}
+ if (unlikely(total_len < TC_HDR_SIZE)) {
+ return NULL;
+ }
+
if (context != NULL) {
struct talloc_chunk *ptc = talloc_chunk_from_ptr(context);
@@ -584,24 +596,29 @@ static inline void *__talloc(const void *context, size_t size)
limit = ptc->limit;
}
- tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size);
+ tc = talloc_alloc_pool(ptc, TC_HDR_SIZE+size, prefix_len);
}
if (tc == NULL) {
+ char *ptr;
+
/*
* Only do the memlimit check/update on actual allocation.
*/
- if (!talloc_memlimit_check(limit, TC_HDR_SIZE + size)) {
+ if (!talloc_memlimit_check(limit, total_len)) {
errno = ENOMEM;
return NULL;
}
- tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
- if (unlikely(tc == NULL)) return NULL;
+ ptr = malloc(total_len);
+ if (unlikely(ptr == NULL)) {
+ return NULL;
+ }
+ tc = (struct talloc_chunk *)(ptr + prefix_len);
tc->flags = TALLOC_MAGIC;
tc->pool = NULL;
- talloc_memlimit_grow(limit, TC_HDR_SIZE + size);
+ talloc_memlimit_grow(limit, total_len);
}
tc->limit = limit;
@@ -631,35 +648,106 @@ 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
*/
_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)) {
- /* 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);
+ tc = talloc_chunk_from_ptr(result);
+ pool_hdr = talloc_pool_from_chunk(tc);
+
+ 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);
+
+ return result;
+}
+
+/*
+ * Create a talloc pool correctly sized for a basic size plus
+ * a number of subobjects whose total size is given. Essentially
+ * a custom allocator for talloc to reduce fragmentation.
+ */
+
+_PUBLIC_ void *_talloc_pooled_object(const void *ctx,
+ size_t type_size,
+ const char *type_name,
+ unsigned num_subobjects,
+ size_t total_subobjects_size)
+{
+ size_t poolsize, subobjects_slack, tmp;
+ struct talloc_chunk *tc;
+ struct talloc_pool_hdr *pool_hdr;
+ void *ret;
+
+ poolsize = type_size + total_subobjects_size;
+
+ if ((poolsize < type_size) || (poolsize < total_subobjects_size)) {
+ goto overflow;
+ }
+
+ if (num_subobjects == UINT_MAX) {
+ goto overflow;
+ }
+ num_subobjects += 1; /* the object body itself */
+
+ /*
+ * Alignment can increase the pool size by at most 15 bytes per object
+ * plus alignment for the object itself
+ */
+ subobjects_slack = (TC_HDR_SIZE + TP_HDR_SIZE + 15) * num_subobjects;
+ if (subobjects_slack < num_subobjects) {
+ goto overflow;
+ }
+
+ tmp = poolsize + subobjects_slack;
+ if ((tmp < poolsize) || (tmp < subobjects_slack)) {
+ goto overflow;
+ }
+ poolsize = tmp;
+
+ ret = talloc_pool(ctx, poolsize);
+ if (ret == NULL) {
return NULL;
}
- pool_tc->hdr.c.flags |= TALLOC_FLAG_POOL;
- pool_tc->hdr.c.pool = tc_pool_first_chunk(pool_tc);
- pool_tc->hdr.object_count = 1;
+ tc = talloc_chunk_from_ptr(ret);
+ tc->size = type_size;
- tc_invalidate_pool(pool_tc);
+ pool_hdr = talloc_pool_from_chunk(tc);
- return result;
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+ VALGRIND_MAKE_MEM_UNDEFINED(pool_hdr->end, type_size);
+#endif
+
+ pool_hdr->end = ((char *)pool_hdr->end + TC_ALIGN16(type_size));
+
+ talloc_set_name_const(ret, type_name);
+ return ret;
+
+overflow:
+ return NULL;
}
/*
@@ -760,10 +848,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 = (union talloc_pool_chunk *)tc->pool;
+ pool = tc->pool;
+ pool_tc = talloc_chunk_from_pool(pool);
next_tc = tc_next_chunk(tc);
tc->flags |= TALLOC_FLAG_FREE;
@@ -776,15 +866,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,
@@ -792,33 +882,42 @@ 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->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;
-
- talloc_memlimit_update_on_free(&pool->hdr.c);
+ pool_tc->name = location;
- TC_INVALIDATE_FULL_CHUNK(&pool->hdr.c);
- free(pool);
+ if (pool_tc->flags & TALLOC_FLAG_POOLMEM) {
+ _talloc_free_poolmem(pool_tc, location);
+ } else {
+ /*
+ * The talloc_memlimit_update_on_free()
+ * call takes into account the
+ * prefix TP_HDR_SIZE allocated before
+ * the pool talloc_chunk.
+ */
+ talloc_memlimit_update_on_free(pool_tc);
+ TC_INVALIDATE_FULL_CHUNK(pool_tc);
+ free(pool);
+ }
return;
}
- if (pool->hdr.c.pool == 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.c.pool = tc;
+ pool->end = tc;
return;
}
@@ -838,6 +937,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;
@@ -914,24 +1014,29 @@ 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;
+
+ pool = talloc_pool_from_chunk(tc);
- if (unlikely(pool->hdr.object_count == 0)) {
+ 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;
}
- talloc_memlimit_update_on_free(tc);
-
- TC_INVALIDATE_FULL_CHUNK(tc);
- free(tc);
- 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;
--
Samba Shared Repository
More information about the samba-cvs
mailing list