Skip to content

Commit 08549ff

Browse files
committed
cleanup: Provide retain_ptr()
In cases where an allocation is consumed by another function, the allocation needs to be retained on success or freed on failure. The code pattern is usually: struct foo *f = kzalloc(sizeof(*f), GFP_KERNEL); struct bar *b; ,,, // Initialize f ... if (ret) goto free; ... bar = bar_create(f); if (!bar) { ret = -ENOMEM; goto free; } ... return 0; free: kfree(f); return ret; This prevents using __free(kfree) on @f because there is no canonical way to tell the cleanup code that the allocation should not be freed. Abusing no_free_ptr() by force ignoring the return value is not really a sensible option either. Provide an explicit macro retain_ptr(), which NULLs the cleanup pointer. That makes it easy to analyze and reason about. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 5376252 commit 08549ff

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

include/linux/cleanup.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ const volatile void * __must_check_fn(const volatile void *val)
216216

217217
#define return_ptr(p) return no_free_ptr(p)
218218

219+
/*
220+
* Only for situations where an allocation is handed in to another function
221+
* and consumed by that function on success.
222+
*
223+
* struct foo *f __free(kfree) = kzalloc(sizeof(*f), GFP_KERNEL);
224+
*
225+
* setup(f);
226+
* if (some_condition)
227+
* return -EINVAL;
228+
* ....
229+
* ret = bar(f);
230+
* if (!ret)
231+
* retain_ptr(f);
232+
* return ret;
233+
*/
234+
#define retain_ptr(p) \
235+
__get_and_null(p, NULL)
219236

220237
/*
221238
* DEFINE_CLASS(name, type, exit, init, init_args...):

0 commit comments

Comments
 (0)