// SPDX-License-Identifier: GPL-2.0 /* * KUnit resource API for test managed resources (allocations, etc.). * * Copyright (C) 2022, Google LLC. * Author: Daniel Latypov */ #include #include #include /* * Used for static resources and when a kunit_resource * has been created by * kunit_alloc_resource(). When an init function is supplied, @data is passed * into the init function; otherwise, we simply set the resource data field to * the data value passed in. Doesn't initialize res->should_kfree. */ int __kunit_add_resource(struct kunit *test, kunit_resource_init_t init, kunit_resource_free_t free, struct kunit_resource *res, void *data) { int ret = 0; unsigned long flags; res->free = free; kref_init(&res->refcount); if (init) { ret = init(res, data); if (ret) return ret; } else { res->data = data; } spin_lock_irqsave(&test->lock, flags); list_add_tail(&res->node, &test->resources); /* refcount for list is established by kref_init() */ spin_unlock_irqrestore(&test->lock, flags); return ret; } EXPORT_SYMBOL_GPL(__kunit_add_resource); void kunit_remove_resource(struct kunit *test, struct kunit_resource *res) { unsigned long flags; bool was_linked; spin_lock_irqsave(&test->lock, flags); was_linked = !list_empty(&res->node); list_del_init(&res->node); spin_unlock_irqrestore(&test->lock, flags); if (was_linked) kunit_put_resource(res); } EXPORT_SYMBOL_GPL(kunit_remove_resource); int kunit_destroy_resource(struct kunit *test, kunit_resource_match_t match, void *match_data) { struct kunit_resource *res = kunit_find_resource(test, match, match_data); if (!res) return -ENOENT; kunit_remove_resource(test, res); /* We have a reference also via _find(); drop it. */ kunit_put_resource(res); return 0; } EXPORT_SYMBOL_GPL(kunit_destroy_resource);