15
15
#include <linux/module.h>
16
16
#include <linux/slab.h>
17
17
#include <linux/types.h>
18
+ #include <linux/kref.h>
18
19
19
20
struct kunit_resource ;
20
21
@@ -23,13 +24,19 @@ typedef void (*kunit_resource_free_t)(struct kunit_resource *);
23
24
24
25
/**
25
26
* struct kunit_resource - represents a *test managed resource*
26
- * @allocation : for the user to store arbitrary data.
27
+ * @data : for the user to store arbitrary data.
27
28
* @free: a user supplied function to free the resource. Populated by
28
- * kunit_alloc_resource ().
29
+ * kunit_resource_alloc ().
29
30
*
30
31
* Represents a *test managed resource*, a resource which will automatically be
31
32
* cleaned up at the end of a test case.
32
33
*
34
+ * Resources are reference counted so if a resource is retrieved via
35
+ * kunit_alloc_and_get_resource() or kunit_find_resource(), we need
36
+ * to call kunit_put_resource() to reduce the resource reference count
37
+ * when finished with it. Note that kunit_alloc_resource() does not require a
38
+ * kunit_resource_put() because it does not retrieve the resource itself.
39
+ *
33
40
* Example:
34
41
*
35
42
* .. code-block:: c
@@ -42,40 +49,42 @@ typedef void (*kunit_resource_free_t)(struct kunit_resource *);
42
49
* static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
43
50
* {
44
51
* struct kunit_kmalloc_params *params = context;
45
- * res->allocation = kmalloc(params->size, params->gfp);
52
+ * res->data = kmalloc(params->size, params->gfp);
46
53
*
47
- * if (!res->allocation )
54
+ * if (!res->data )
48
55
* return -ENOMEM;
49
56
*
50
57
* return 0;
51
58
* }
52
59
*
53
60
* static void kunit_kmalloc_free(struct kunit_resource *res)
54
61
* {
55
- * kfree(res->allocation );
62
+ * kfree(res->data );
56
63
* }
57
64
*
58
65
* void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
59
66
* {
60
67
* struct kunit_kmalloc_params params;
61
- * struct kunit_resource *res;
62
68
*
63
69
* params.size = size;
64
70
* params.gfp = gfp;
65
71
*
66
- * res = kunit_alloc_resource(test, kunit_kmalloc_init,
72
+ * return kunit_alloc_resource(test, kunit_kmalloc_init,
67
73
* kunit_kmalloc_free, ¶ms);
68
- * if (res)
69
- * return res->allocation;
70
- *
71
- * return NULL;
72
74
* }
75
+ *
76
+ * Resources can also be named, with lookup/removal done on a name
77
+ * basis also. kunit_add_named_resource(), kunit_find_named_resource()
78
+ * and kunit_destroy_named_resource(). Resource names must be
79
+ * unique within the test instance.
73
80
*/
74
81
struct kunit_resource {
75
- void * allocation ;
76
- kunit_resource_free_t free ;
82
+ void * data ;
83
+ const char * name ; /* optional name */
77
84
78
85
/* private: internal use only. */
86
+ kunit_resource_free_t free ;
87
+ struct kref refcount ;
79
88
struct list_head node ;
80
89
};
81
90
@@ -283,6 +292,79 @@ struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
283
292
gfp_t internal_gfp ,
284
293
void * context );
285
294
295
+ /**
296
+ * kunit_get_resource() - Hold resource for use. Should not need to be used
297
+ * by most users as we automatically get resources
298
+ * retrieved by kunit_find_resource*().
299
+ * @res: resource
300
+ */
301
+ static inline void kunit_get_resource (struct kunit_resource * res )
302
+ {
303
+ kref_get (& res -> refcount );
304
+ }
305
+
306
+ /*
307
+ * Called when refcount reaches zero via kunit_put_resources();
308
+ * should not be called directly.
309
+ */
310
+ static inline void kunit_release_resource (struct kref * kref )
311
+ {
312
+ struct kunit_resource * res = container_of (kref , struct kunit_resource ,
313
+ refcount );
314
+
315
+ /* If free function is defined, resource was dynamically allocated. */
316
+ if (res -> free ) {
317
+ res -> free (res );
318
+ kfree (res );
319
+ }
320
+ }
321
+
322
+ /**
323
+ * kunit_put_resource() - When caller is done with retrieved resource,
324
+ * kunit_put_resource() should be called to drop
325
+ * reference count. The resource list maintains
326
+ * a reference count on resources, so if no users
327
+ * are utilizing a resource and it is removed from
328
+ * the resource list, it will be freed via the
329
+ * associated free function (if any). Only
330
+ * needs to be used if we alloc_and_get() or
331
+ * find() resource.
332
+ * @res: resource
333
+ */
334
+ static inline void kunit_put_resource (struct kunit_resource * res )
335
+ {
336
+ kref_put (& res -> refcount , kunit_release_resource );
337
+ }
338
+
339
+ /**
340
+ * kunit_add_resource() - Add a *test managed resource*.
341
+ * @test: The test context object.
342
+ * @init: a user-supplied function to initialize the result (if needed). If
343
+ * none is supplied, the resource data value is simply set to @data.
344
+ * If an init function is supplied, @data is passed to it instead.
345
+ * @free: a user-supplied function to free the resource (if needed).
346
+ * @data: value to pass to init function or set in resource data field.
347
+ */
348
+ int kunit_add_resource (struct kunit * test ,
349
+ kunit_resource_init_t init ,
350
+ kunit_resource_free_t free ,
351
+ struct kunit_resource * res ,
352
+ void * data );
353
+
354
+ /**
355
+ * kunit_add_named_resource() - Add a named *test managed resource*.
356
+ * @test: The test context object.
357
+ * @init: a user-supplied function to initialize the resource data, if needed.
358
+ * @free: a user-supplied function to free the resource data, if needed.
359
+ * @name_data: name and data to be set for resource.
360
+ */
361
+ int kunit_add_named_resource (struct kunit * test ,
362
+ kunit_resource_init_t init ,
363
+ kunit_resource_free_t free ,
364
+ struct kunit_resource * res ,
365
+ const char * name ,
366
+ void * data );
367
+
286
368
/**
287
369
* kunit_alloc_resource() - Allocates a *test managed resource*.
288
370
* @test: The test context object.
@@ -295,7 +377,7 @@ struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
295
377
* cleaned up at the end of a test case. See &struct kunit_resource for an
296
378
* example.
297
379
*
298
- * NOTE : KUnit needs to allocate memory for each kunit_resource object. You must
380
+ * Note : KUnit needs to allocate memory for a kunit_resource object. You must
299
381
* specify an @internal_gfp that is compatible with the use context of your
300
382
* resource.
301
383
*/
@@ -307,54 +389,122 @@ static inline void *kunit_alloc_resource(struct kunit *test,
307
389
{
308
390
struct kunit_resource * res ;
309
391
310
- res = kunit_alloc_and_get_resource (test , init , free , internal_gfp ,
311
- context );
392
+ res = kzalloc (sizeof (* res ), internal_gfp );
393
+ if (!res )
394
+ return NULL ;
312
395
313
- if (res )
314
- return res -> allocation ;
396
+ if (! kunit_add_resource ( test , init , free , res , context ) )
397
+ return res -> data ;
315
398
316
399
return NULL ;
317
400
}
318
401
319
402
typedef bool (* kunit_resource_match_t )(struct kunit * test ,
320
- const void * res ,
403
+ struct kunit_resource * res ,
321
404
void * match_data );
322
405
323
406
/**
324
407
* kunit_resource_instance_match() - Match a resource with the same instance.
325
408
* @test: Test case to which the resource belongs.
326
- * @res: The data stored in kunit_resource->allocation .
409
+ * @res: The resource .
327
410
* @match_data: The resource pointer to match against.
328
411
*
329
412
* An instance of kunit_resource_match_t that matches a resource whose
330
413
* allocation matches @match_data.
331
414
*/
332
415
static inline bool kunit_resource_instance_match (struct kunit * test ,
333
- const void * res ,
416
+ struct kunit_resource * res ,
334
417
void * match_data )
335
418
{
336
- return res == match_data ;
419
+ return res -> data == match_data ;
337
420
}
338
421
339
422
/**
340
- * kunit_resource_destroy() - Find a kunit_resource and destroy it.
423
+ * kunit_resource_name_match() - Match a resource with the same name.
424
+ * @test: Test case to which the resource belongs.
425
+ * @res: The resource.
426
+ * @match_name: The name to match against.
427
+ */
428
+ static inline bool kunit_resource_name_match (struct kunit * test ,
429
+ struct kunit_resource * res ,
430
+ void * match_name )
431
+ {
432
+ return res -> name && strcmp (res -> name , match_name ) == 0 ;
433
+ }
434
+
435
+ /**
436
+ * kunit_find_resource() - Find a resource using match function/data.
437
+ * @test: Test case to which the resource belongs.
438
+ * @match: match function to be applied to resources/match data.
439
+ * @match_data: data to be used in matching.
440
+ */
441
+ static inline struct kunit_resource *
442
+ kunit_find_resource (struct kunit * test ,
443
+ kunit_resource_match_t match ,
444
+ void * match_data )
445
+ {
446
+ struct kunit_resource * res , * found = NULL ;
447
+
448
+ spin_lock (& test -> lock );
449
+
450
+ list_for_each_entry_reverse (res , & test -> resources , node ) {
451
+ if (match (test , res , (void * )match_data )) {
452
+ found = res ;
453
+ kunit_get_resource (found );
454
+ break ;
455
+ }
456
+ }
457
+
458
+ spin_unlock (& test -> lock );
459
+
460
+ return found ;
461
+ }
462
+
463
+ /**
464
+ * kunit_find_named_resource() - Find a resource using match name.
465
+ * @test: Test case to which the resource belongs.
466
+ * @name: match name.
467
+ */
468
+ static inline struct kunit_resource *
469
+ kunit_find_named_resource (struct kunit * test ,
470
+ const char * name )
471
+ {
472
+ return kunit_find_resource (test , kunit_resource_name_match ,
473
+ (void * )name );
474
+ }
475
+
476
+ /**
477
+ * kunit_destroy_resource() - Find a kunit_resource and destroy it.
341
478
* @test: Test case to which the resource belongs.
342
479
* @match: Match function. Returns whether a given resource matches @match_data.
343
- * @free: Must match free on the kunit_resource to free.
344
480
* @match_data: Data passed into @match.
345
481
*
346
- * Free the latest kunit_resource of @test for which @free matches the
347
- * kunit_resource_free_t associated with the resource and for which @match
348
- * returns true.
349
- *
350
482
* RETURNS:
351
483
* 0 if kunit_resource is found and freed, -ENOENT if not found.
352
484
*/
353
- int kunit_resource_destroy (struct kunit * test ,
485
+ int kunit_destroy_resource (struct kunit * test ,
354
486
kunit_resource_match_t match ,
355
- kunit_resource_free_t free ,
356
487
void * match_data );
357
488
489
+ static inline int kunit_destroy_named_resource (struct kunit * test ,
490
+ const char * name )
491
+ {
492
+ return kunit_destroy_resource (test , kunit_resource_name_match ,
493
+ (void * )name );
494
+ }
495
+
496
+ /**
497
+ * kunit_remove_resource: remove resource from resource list associated with
498
+ * test.
499
+ * @test: The test context object.
500
+ * @res: The resource to be removed.
501
+ *
502
+ * Note that the resource will not be immediately freed since it is likely
503
+ * the caller has a reference to it via alloc_and_get() or find();
504
+ * in this case a final call to kunit_put_resource() is required.
505
+ */
506
+ void kunit_remove_resource (struct kunit * test , struct kunit_resource * res );
507
+
358
508
/**
359
509
* kunit_kmalloc() - Like kmalloc() except the allocation is *test managed*.
360
510
* @test: The test context object.
0 commit comments