[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Import the current version of talloc from the Samba 3 source base. This gives
# HG changeset patch # User emellor@xxxxxxxxxxxxxxxxxxxxxx # Node ID 40e3df4cffe44b69131b3372d992238c06f6956c # Parent a594a5b2407c9b47fed717ca16844be53ed65284 Import the current version of talloc from the Samba 3 source base. This gives us greater confidence that our talloc implementation is "known good". Remove the OOM handling from consider_message: talloc_set_fail_handler is no longer supported. Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx> diff -r a594a5b2407c -r 40e3df4cffe4 tools/xenstore/talloc.c --- a/tools/xenstore/talloc.c Thu Mar 23 13:26:38 2006 +++ b/tools/xenstore/talloc.c Thu Mar 23 13:32:15 2006 @@ -1,4 +1,4 @@ -/* +/* Samba Unix SMB/CIFS implementation. Samba trivial allocation library - new interface @@ -6,26 +6,29 @@ NOTE: Please read talloc_guide.txt for full documentation Copyright (C) Andrew Tridgell 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* inspired by http://swapped.cc/halloc/ */ - #ifdef _SAMBA_BUILD_ #include "includes.h" @@ -52,15 +55,13 @@ /* use this to force every realloc to change the pointer, to stress test code that might not cope */ -#ifdef TESTING -#define ALWAYS_REALLOC 1 -void *test_malloc(size_t size); -#define malloc test_malloc -#endif +#define ALWAYS_REALLOC 0 + #define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0xe814ec4f -#define TALLOC_MAGIC_FREE 0x7faebef3 +#define TALLOC_MAGIC 0xe814ec70 +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 #define TALLOC_MAGIC_REFERENCE ((const char *)1) /* by default we abort when given a bad pointer (such as when talloc_free() is called @@ -83,8 +84,7 @@ */ static const void *null_context; static void *cleanup_context; -static int (*malloc_fail_handler)(void *); -static void *malloc_fail_data; + struct talloc_reference_handle { struct talloc_reference_handle *next, *prev; @@ -97,24 +97,27 @@ struct talloc_chunk *next, *prev; struct talloc_chunk *parent, *child; struct talloc_reference_handle *refs; - size_t size; - unsigned magic; talloc_destructor_t destructor; const char *name; + size_t size; + unsigned flags; }; + +/* 16 byte alignment seems to keep everyone happy */ +#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) /* panic if we get a bad magic value */ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if (tc->magic != TALLOC_MAGIC) { - if (tc->magic == TALLOC_MAGIC_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); - } else { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } - } - + const char *pp = ptr; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); + if ((tc->flags & ~0xF) != TALLOC_MAGIC) { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } + if (tc->flags & TALLOC_FLAG_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); + } return tc; } @@ -159,7 +162,7 @@ void *talloc_parent(const void *ptr) { struct talloc_chunk *tc = talloc_parent_chunk(ptr); - return (void *)(tc+1); + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; } /* @@ -177,17 +180,11 @@ return NULL; } - tc = malloc(sizeof(*tc)+size); - if (tc == NULL) { - if (malloc_fail_handler) - if (malloc_fail_handler(malloc_fail_data)) - tc = malloc(sizeof(*tc)+size); - if (!tc) - return NULL; - } + tc = malloc(TC_HDR_SIZE+size); + if (tc == NULL) return NULL; tc->size = size; - tc->magic = TALLOC_MAGIC; + tc->flags = TALLOC_MAGIC; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; @@ -207,7 +204,7 @@ tc->next = tc->prev = tc->parent = NULL; } - return (void *)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } @@ -292,7 +289,11 @@ for (h=tc->refs;h;h=h->next) { struct talloc_chunk *p = talloc_parent_chunk(h); - if ((p==NULL && context==NULL) || p+1 == context) break; + if (p == NULL) { + if (context == NULL) break; + } else if (TC_PTR_FROM_CHUNK(p) == context) { + break; + } } if (h == NULL) { return -1; @@ -343,7 +344,7 @@ new_p = talloc_parent_chunk(tc_p->refs); if (new_p) { - new_parent = new_p+1; + new_parent = TC_PTR_FROM_CHUNK(new_p); } else { new_parent = NULL; } @@ -470,6 +471,8 @@ { va_list ap; void *ptr; + + talloc_enable_null_tracking(); ptr = _talloc(NULL, 0); if (ptr == NULL) return NULL; @@ -502,16 +505,16 @@ choice is owner of any remaining reference to this pointer, the second choice is our parent, and the final choice is the null context. */ - void *child = tc->child+1; + void *child = TC_PTR_FROM_CHUNK(tc->child); const void *new_parent = null_context; if (tc->child->refs) { struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } if (talloc_free(child) == -1) { if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } talloc_steal(new_parent, child); } @@ -539,6 +542,11 @@ if (tc->refs) { talloc_reference_destructor(tc->refs); return -1; + } + + if (tc->flags & TALLOC_FLAG_LOOP) { + /* we have a free loop - stop looping */ + return 0; } if (tc->destructor) { @@ -554,6 +562,8 @@ tc->destructor = NULL; } + tc->flags |= TALLOC_FLAG_LOOP; + talloc_free_children(ptr); if (tc->parent) { @@ -566,7 +576,7 @@ if (tc->next) tc->next->prev = tc->prev; } - tc->magic = TALLOC_MAGIC_FREE; + tc->flags |= TALLOC_FLAG_FREE; free(tc); return 0; @@ -606,36 +616,24 @@ } /* by resetting magic we catch users of the old memory */ - tc->magic = TALLOC_MAGIC_FREE; + tc->flags |= TALLOC_FLAG_FREE; #if ALWAYS_REALLOC - new_ptr = malloc(size + sizeof(*tc)); - if (!new_ptr) { - tc->magic = TALLOC_MAGIC; - if (malloc_fail_handler) - if (malloc_fail_handler(malloc_fail_data)) - new_ptr = malloc(size + sizeof(*tc)); - } + new_ptr = malloc(size + TC_HDR_SIZE); if (new_ptr) { - memcpy(new_ptr, tc, tc->size + sizeof(*tc)); + memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE); free(tc); } #else - new_ptr = realloc(tc, size + sizeof(*tc)); - if (!new_ptr) { - tc->magic = TALLOC_MAGIC; - if (malloc_fail_handler) - if (malloc_fail_handler(malloc_fail_data)) - new_ptr = realloc(tc, size + sizeof(*tc)); - } + new_ptr = realloc(tc, size + TC_HDR_SIZE); #endif if (!new_ptr) { - tc->magic = TALLOC_MAGIC; + tc->flags &= ~TALLOC_FLAG_FREE; return NULL; } tc = new_ptr; - tc->magic = TALLOC_MAGIC; + tc->flags &= ~TALLOC_FLAG_FREE; if (tc->parent) { tc->parent->child = new_ptr; } @@ -651,9 +649,9 @@ } tc->size = size; - talloc_set_name_const(tc+1, name); - - return (void *)(tc+1); + talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); + + return TC_PTR_FROM_CHUNK(tc); } /* @@ -730,10 +728,19 @@ tc = talloc_chunk_from_ptr(ptr); + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + total = tc->size; for (c=tc->child;c;c=c->next) { - total += talloc_total_size(c+1); - } + total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -743,20 +750,21 @@ off_t talloc_total_blocks(const void *ptr) { off_t total = 0; - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) { + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { return 0; } - tc = talloc_chunk_from_ptr(ptr); + + tc->flags |= TALLOC_FLAG_LOOP; total++; for (c=tc->child;c;c=c->next) { - total += talloc_total_blocks(c+1); - } + total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -782,23 +790,29 @@ { struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = (void *)(c+1); + struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); const char *name2 = talloc_get_name(handle->ptr); fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); } else { - const char *name = talloc_get_name(c+1); + const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", depth*4, "", name, - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1), - talloc_reference_count(c+1)); - talloc_report_depth(c+1, f, depth+1); - } - } - + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), + talloc_reference_count(TC_PTR_FROM_CHUNK(c))); + talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; } /* @@ -841,9 +855,9 @@ for (c=tc->child;c;c=c->next) { fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(c+1), - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1)); + talloc_get_name(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c))); } fflush(f); } @@ -877,6 +891,74 @@ null_context = talloc_named_const(NULL, 0, "null_context"); } } + +#ifdef _SAMBA_BUILD_ +/* Ugly calls to Samba-specific sprintf_append... JRA. */ + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth) +{ + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); + const char *name2 = talloc_get_name(handle->ptr); + + sprintf_append(NULL, pps, plen, pbuflen, + "%*sreference to: %s\n", depth*4, "", name2); + + } else { + const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); + + sprintf_append(NULL, pps, plen, pbuflen, + "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), + talloc_reference_count(TC_PTR_FROM_CHUNK(c))); + + talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; +} + +/* + report on memory usage by all children of a pointer +*/ +char *talloc_describe_all(void) +{ + ssize_t len = 0; + size_t buflen = 512; + char *s = NULL; + + if (null_context == NULL) { + return NULL; + } + + sprintf_append(NULL, &s, &len, &buflen, + "full talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(null_context), + (unsigned long)talloc_total_size(null_context), + (unsigned long)talloc_total_blocks(null_context)); + + if (!s) { + return NULL; + } + talloc_report_depth_str(null_context, &s, &len, &buflen, 1); + return s; +} +#endif /* enable leak reporting on exit @@ -942,6 +1024,30 @@ } /* + append to a talloced string +*/ +char *talloc_append_string(const void *t, char *orig, const char *append) +{ + char *ret; + size_t olen = strlen(orig); + size_t alenz; + + if (!append) + return orig; + + alenz = strlen(append) + 1; + + ret = talloc_realloc(t, orig, char, olen + alenz); + if (!ret) + return NULL; + + /* append the string with the trailing \0 */ + memcpy(&ret[olen], append, alenz); + + return ret; +} + +/* strndup with a talloc */ char *talloc_strndup(const void *t, const char *p, size_t n) @@ -949,7 +1055,7 @@ size_t len; char *ret; - for (len=0; p[len] && len<n; len++) ; + for (len=0; len<n && p[len]; len++) ; ret = _talloc(t, len + 1); if (!ret) { return NULL; } @@ -974,10 +1080,14 @@ int len; char *ret; va_list ap2; + char c; VA_COPY(ap2, ap); - len = vsnprintf(NULL, 0, fmt, ap2); + /* this call looks strange, but it makes it work on older solaris boxes */ + if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) { + return NULL; + } ret = _talloc(t, len+1); if (ret) { @@ -1029,7 +1139,15 @@ VA_COPY(ap2, ap); s_len = tc->size - 1; - len = vsnprintf(NULL, 0, fmt, ap2); + if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) { + /* Either the vsnprintf failed or the format resulted in + * no characters being formatted. In the former case, we + * ought to return NULL, in the latter we ought to return + * the original string. Most current callers of this + * function expect it to never return NULL. + */ + return s; + } s = talloc_realloc(NULL, s, char, s_len + len+1); if (!s) return NULL; @@ -1133,11 +1251,45 @@ return tc->size; } -talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *handler, - void *data) -{ - talloc_fail_handler *old = malloc_fail_handler; - malloc_fail_handler = handler; - malloc_fail_data = data; - return old; -} +/* + find a parent of this context that has the given name, if any +*/ +void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return TC_PTR_FROM_CHUNK(tc); + } + while (tc && tc->prev) tc = tc->prev; + tc = tc->parent; + } + return NULL; +} + +/* + show the parentage of a context +*/ +void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); + while (tc && tc->prev) tc = tc->prev; + tc = tc->parent; + } +} diff -r a594a5b2407c -r 40e3df4cffe4 tools/xenstore/talloc.h --- a/tools/xenstore/talloc.h Thu Mar 23 13:26:38 2006 +++ b/tools/xenstore/talloc.h Thu Mar 23 13:32:15 2006 @@ -6,19 +6,23 @@ Copyright (C) Andrew Tridgell 2004-2005 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* this is only needed for compatibility with the old talloc */ @@ -58,12 +62,17 @@ #define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) #define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) +#if 0 +/* Not correct for Samba3. */ #define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) #define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) #define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) +#endif #define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) + +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) #if TALLOC_DEPRECATED @@ -117,6 +126,7 @@ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); char *talloc_strdup(const void *t, const char *p); char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_append_string(const void *t, char *orig, const char *append); char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); char *talloc_asprintf_append(char *s, @@ -127,8 +137,8 @@ void *talloc_realloc_fn(const void *context, void *ptr, size_t size); void *talloc_autofree_context(void); size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); -typedef int talloc_fail_handler(void *); -talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *, void *); #endif diff -r a594a5b2407c -r 40e3df4cffe4 tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Thu Mar 23 13:26:38 2006 +++ b/tools/xenstore/xenstored_core.c Thu Mar 23 13:32:15 2006 @@ -1231,39 +1231,17 @@ conn->transaction = NULL; } -static int out_of_mem(void *data) -{ - longjmp(*(jmp_buf *)data, 1); -} - static void consider_message(struct connection *conn) { - jmp_buf talloc_fail; - if (verbose) xprintf("Got message %s len %i from %p\n", sockmsg_string(conn->in->hdr.msg.type), conn->in->hdr.msg.len, conn); - /* For simplicity, we kill the connection on OOM. */ - talloc_set_fail_handler(out_of_mem, &talloc_fail); - if (setjmp(talloc_fail)) { - talloc_free(conn); - goto end; - } - process_message(conn, conn->in); talloc_free(conn->in); conn->in = new_buffer(conn); - -end: - talloc_set_fail_handler(NULL, NULL); - if (talloc_total_blocks(NULL) - != talloc_total_blocks(talloc_autofree_context()) + 1) { - talloc_report_full(NULL, stderr); - abort(); - } } /* Errors in reading or allocating here mean we get out of sync, so we diff -r a594a5b2407c -r 40e3df4cffe4 tools/xenstore/README --- /dev/null Thu Mar 23 13:26:38 2006 +++ b/tools/xenstore/README Thu Mar 23 13:32:15 2006 @@ -0,0 +1,5 @@ +The following files are imported from the Samba project. We use the versions +from Samba 3, the current stable branch. + +talloc.c: samba-trunk/source/lib/talloc.c r14291 2006-03-13 04:27:47 +0000 +talloc.h: samba-trunk/source/include/talloc.h r11986 2005-12-01 00:43:36 +0000 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |