From: Jeremy Allison Date: Wed, 4 Mar 2015 01:02:47 +0000 (-0800) Subject: lib: talloc: Allow destructors to reparent the object they're called on. X-Git-Url: http://git.samba.org/?p=metze%2Fsamba%2Fwip.git;a=commitdiff_plain;h=024dd8368da2b2e01754f9ca7339a24b47ba0dd7 lib: talloc: Allow destructors to reparent the object they're called on. If a destructor returns failure (-1) when freeing a child, talloc must then reparent the child. Firstly it tries the owner of any reference, next the parent of the current object calling _talloc_free_children_internal(), and finally the null context in the last resort. If a destructor reparented its own object, which can be a very desirable thing to do (a destructor can make a decision it isn't time to die yet, and as the parent may be going away it might want to move itself to longer-term storage) then this new parent gets overwritten by the existing reparenting logic. This patch checks when freeing a child if it already reparented itself, and if it did doesn't then overwrite the new parent. Makes destructors more flexible. Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Reviewed-by: Ira Cooper (cherry picked from commit cc4e5481ea060db7f6d8a83619d859b2e002eb90) --- diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 1ccb039ff744..46f10f4697cf 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -1470,6 +1470,13 @@ static inline void _talloc_free_children_internal(struct talloc_chunk *tc, if (p) new_parent = TC_PTR_FROM_CHUNK(p); } if (unlikely(_talloc_free_internal(child, location) == -1)) { + if (talloc_parent_chunk(child) != tc) { + /* + * Destructor already reparented this child. + * No further reparenting needed. + */ + return; + } if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); if (p) new_parent = TC_PTR_FROM_CHUNK(p);