Skip to content

Commit

Permalink
cleanup: Provide retain_ptr()
Browse files Browse the repository at this point in the history
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 <tglx@linutronix.de>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/all/20250313130321.442025758@linutronix.de
  • Loading branch information
Thomas Gleixner committed Mar 13, 2025
1 parent 5376252 commit 08549ff
Showing 1 changed file with 17 additions and 0 deletions.
17 changes: 17 additions & 0 deletions include/linux/cleanup.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,23 @@ const volatile void * __must_check_fn(const volatile void *val)

#define return_ptr(p) return no_free_ptr(p)

/*
* Only for situations where an allocation is handed in to another function
* and consumed by that function on success.
*
* struct foo *f __free(kfree) = kzalloc(sizeof(*f), GFP_KERNEL);
*
* setup(f);
* if (some_condition)
* return -EINVAL;
* ....
* ret = bar(f);
* if (!ret)
* retain_ptr(f);
* return ret;
*/
#define retain_ptr(p) \
__get_and_null(p, NULL)

/*
* DEFINE_CLASS(name, type, exit, init, init_args...):
Expand Down

0 comments on commit 08549ff

Please sign in to comment.