xref: /linux/include/linux/ref_tracker.h (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
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 
ref_tracker_dir_debugfs(struct ref_tracker_dir * dir)35 static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir)
36 {
37 }
38 
39 static inline __ostream_printf
ref_tracker_dir_symlink(struct ref_tracker_dir * dir,const char * fmt,...)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  */
ref_tracker_dir_init(struct ref_tracker_dir * dir,unsigned int quarantine_count,const char * class)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 
ref_tracker_dir_init(struct ref_tracker_dir * dir,unsigned int quarantine_count,const char * class)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 
ref_tracker_dir_debugfs(struct ref_tracker_dir * dir)98 static inline void ref_tracker_dir_debugfs(struct ref_tracker_dir *dir)
99 {
100 }
101 
102 static inline __ostream_printf
ref_tracker_dir_symlink(struct ref_tracker_dir * dir,const char * fmt,...)103 void ref_tracker_dir_symlink(struct ref_tracker_dir *dir, const char *fmt, ...)
104 {
105 }
106 
ref_tracker_dir_exit(struct ref_tracker_dir * dir)107 static inline void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
108 {
109 }
110 
ref_tracker_dir_print_locked(struct ref_tracker_dir * dir,unsigned int display_limit)111 static inline void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir,
112 						unsigned int display_limit)
113 {
114 }
115 
ref_tracker_dir_print(struct ref_tracker_dir * dir,unsigned int display_limit)116 static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir,
117 					 unsigned int display_limit)
118 {
119 }
120 
ref_tracker_dir_snprint(struct ref_tracker_dir * dir,char * buf,size_t size)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 
ref_tracker_alloc(struct ref_tracker_dir * dir,struct ref_tracker ** trackerp,gfp_t gfp)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 
ref_tracker_free(struct ref_tracker_dir * dir,struct ref_tracker ** trackerp)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