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
11struct ref_tracker;
12
13struct 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
30void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir);
31void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...);
32
33#else /* CONFIG_DEBUG_FS */
34
35static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir)
36{
37}
38
39static inline __ostream_printf
40void 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 */
58static 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
74void ref_tracker_dir_exit(struct ref_tracker_dir *dir);
75
76void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir,
77 unsigned int display_limit);
78
79void ref_tracker_dir_print(struct ref_tracker_dir *dir,
80 unsigned int display_limit);
81
82int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size);
83
84int ref_tracker_alloc(struct ref_tracker_dir *dir,
85 struct ref_tracker **trackerp, gfp_t gfp);
86
87int ref_tracker_free(struct ref_tracker_dir *dir,
88 struct ref_tracker **trackerp);
89
90#else /* CONFIG_REF_TRACKER */
91
92static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir,
93 unsigned int quarantine_count,
94 const char *class)
95{
96}
97
98static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir)
99{
100}
101
102static inline __ostream_printf
103void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...)
104{
105}
106
107static inline void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
108{
109}
110
111static inline void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir,
112 unsigned int display_limit)
113{
114}
115
116static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir,
117 unsigned int display_limit)
118{
119}
120
121static inline int ref_tracker_dir_snprint(struct ref_tracker_dir *dir,
122 char *buf, size_t size)
123{
124 return 0;
125}
126
127static 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
134static 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