| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 
|---|
| 2 | #ifndef _LINUX_REF_TRACKER_H | 
|---|
| 3 | #define _LINUX_REF_TRACKER_H | 
|---|
| 4 | #include <linux/refcount.h> | 
|---|
| 5 | #include <linux/types.h> | 
|---|
| 6 | #include <linux/spinlock.h> | 
|---|
| 7 | #include <linux/stackdepot.h> | 
|---|
| 8 |  | 
|---|
| 9 | #define __ostream_printf __printf(2, 3) | 
|---|
| 10 |  | 
|---|
| 11 | struct ref_tracker; | 
|---|
| 12 |  | 
|---|
| 13 | struct ref_tracker_dir { | 
|---|
| 14 | #ifdef CONFIG_REF_TRACKER | 
|---|
| 15 | spinlock_t		lock; | 
|---|
| 16 | unsigned int		quarantine_avail; | 
|---|
| 17 | refcount_t		untracked; | 
|---|
| 18 | refcount_t		no_tracker; | 
|---|
| 19 | bool			dead; | 
|---|
| 20 | struct list_head	list; /* List of active trackers */ | 
|---|
| 21 | struct list_head	quarantine; /* List of dead trackers */ | 
|---|
| 22 | const char		*class; /* object classname */ | 
|---|
| 23 | #endif | 
|---|
| 24 | }; | 
|---|
| 25 |  | 
|---|
| 26 | #ifdef CONFIG_REF_TRACKER | 
|---|
| 27 |  | 
|---|
| 28 | #ifdef CONFIG_DEBUG_FS | 
|---|
| 29 |  | 
|---|
| 30 | void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir); | 
|---|
| 31 | void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...); | 
|---|
| 32 |  | 
|---|
| 33 | #else /* CONFIG_DEBUG_FS */ | 
|---|
| 34 |  | 
|---|
| 35 | static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir) | 
|---|
| 36 | { | 
|---|
| 37 | } | 
|---|
| 38 |  | 
|---|
| 39 | static inline __ostream_printf | 
|---|
| 40 | void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...) | 
|---|
| 41 | { | 
|---|
| 42 | } | 
|---|
| 43 |  | 
|---|
| 44 | #endif /* CONFIG_DEBUG_FS */ | 
|---|
| 45 |  | 
|---|
| 46 | /** | 
|---|
| 47 | * ref_tracker_dir_init - initialize a ref_tracker dir | 
|---|
| 48 | * @dir: ref_tracker_dir to be initialized | 
|---|
| 49 | * @quarantine_count: max number of entries to be tracked | 
|---|
| 50 | * @class: pointer to static string that describes object type | 
|---|
| 51 | * | 
|---|
| 52 | * Initialize a ref_tracker_dir. If debugfs is configured, then a file | 
|---|
| 53 | * will also be created for it under the top-level ref_tracker debugfs | 
|---|
| 54 | * directory. | 
|---|
| 55 | * | 
|---|
| 56 | * Note that @class must point to a static string. | 
|---|
| 57 | */ | 
|---|
| 58 | static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir, | 
|---|
| 59 | unsigned int quarantine_count, | 
|---|
| 60 | const char *class) | 
|---|
| 61 | { | 
|---|
| 62 | INIT_LIST_HEAD(&dir->list); | 
|---|
| 63 | INIT_LIST_HEAD(&dir->quarantine); | 
|---|
| 64 | spin_lock_init(&dir->lock); | 
|---|
| 65 | dir->quarantine_avail = quarantine_count; | 
|---|
| 66 | dir->dead = false; | 
|---|
| 67 | refcount_set(&dir->untracked, 1); | 
|---|
| 68 | refcount_set(&dir->no_tracker, 1); | 
|---|
| 69 | dir->class = class; | 
|---|
| 70 | ref_tracker_dir_debugfs(dir); | 
|---|
| 71 | stack_depot_init(); | 
|---|
| 72 | } | 
|---|
| 73 |  | 
|---|
| 74 | void ref_tracker_dir_exit(struct ref_tracker_dir *dir); | 
|---|
| 75 |  | 
|---|
| 76 | void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir, | 
|---|
| 77 | unsigned int display_limit); | 
|---|
| 78 |  | 
|---|
| 79 | void ref_tracker_dir_print(struct ref_tracker_dir *dir, | 
|---|
| 80 | unsigned int display_limit); | 
|---|
| 81 |  | 
|---|
| 82 | int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size); | 
|---|
| 83 |  | 
|---|
| 84 | int ref_tracker_alloc(struct ref_tracker_dir *dir, | 
|---|
| 85 | struct ref_tracker **trackerp, gfp_t gfp); | 
|---|
| 86 |  | 
|---|
| 87 | int ref_tracker_free(struct ref_tracker_dir *dir, | 
|---|
| 88 | struct ref_tracker **trackerp); | 
|---|
| 89 |  | 
|---|
| 90 | #else /* CONFIG_REF_TRACKER */ | 
|---|
| 91 |  | 
|---|
| 92 | static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir, | 
|---|
| 93 | unsigned int quarantine_count, | 
|---|
| 94 | const char *class) | 
|---|
| 95 | { | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir) | 
|---|
| 99 | { | 
|---|
| 100 | } | 
|---|
| 101 |  | 
|---|
| 102 | static inline __ostream_printf | 
|---|
| 103 | void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...) | 
|---|
| 104 | { | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | static inline void ref_tracker_dir_exit(struct ref_tracker_dir *dir) | 
|---|
| 108 | { | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | static inline void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir, | 
|---|
| 112 | unsigned int display_limit) | 
|---|
| 113 | { | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir, | 
|---|
| 117 | unsigned int display_limit) | 
|---|
| 118 | { | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|
| 121 | static inline int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, | 
|---|
| 122 | char *buf, size_t size) | 
|---|
| 123 | { | 
|---|
| 124 | return 0; | 
|---|
| 125 | } | 
|---|
| 126 |  | 
|---|
| 127 | static inline int ref_tracker_alloc(struct ref_tracker_dir *dir, | 
|---|
| 128 | struct ref_tracker **trackerp, | 
|---|
| 129 | gfp_t gfp) | 
|---|
| 130 | { | 
|---|
| 131 | return 0; | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | static inline int ref_tracker_free(struct ref_tracker_dir *dir, | 
|---|
| 135 | struct ref_tracker **trackerp) | 
|---|
| 136 | { | 
|---|
| 137 | return 0; | 
|---|
| 138 | } | 
|---|
| 139 |  | 
|---|
| 140 | #endif | 
|---|
| 141 |  | 
|---|
| 142 | #endif /* _LINUX_REF_TRACKER_H */ | 
|---|
| 143 |  | 
|---|