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 struct ref_tracker;
10 
11 struct ref_tracker_dir {
12 #ifdef CONFIG_REF_TRACKER
13 	spinlock_t		lock;
14 	unsigned int		quarantine_avail;
15 	refcount_t		untracked;
16 	refcount_t		no_tracker;
17 	bool			dead;
18 	struct list_head	list; /* List of active trackers */
19 	struct list_head	quarantine; /* List of dead trackers */
20 	char			name[32];
21 #endif
22 };
23 
24 #ifdef CONFIG_REF_TRACKER
25 
ref_tracker_dir_init(struct ref_tracker_dir * dir,unsigned int quarantine_count,const char * name)26 static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir,
27 					unsigned int quarantine_count,
28 					const char *name)
29 {
30 	INIT_LIST_HEAD(&dir->list);
31 	INIT_LIST_HEAD(&dir->quarantine);
32 	spin_lock_init(&dir->lock);
33 	dir->quarantine_avail = quarantine_count;
34 	dir->dead = false;
35 	refcount_set(&dir->untracked, 1);
36 	refcount_set(&dir->no_tracker, 1);
37 	strscpy(dir->name, name, sizeof(dir->name));
38 	stack_depot_init();
39 }
40 
41 void ref_tracker_dir_exit(struct ref_tracker_dir *dir);
42 
43 void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir,
44 				  unsigned int display_limit);
45 
46 void ref_tracker_dir_print(struct ref_tracker_dir *dir,
47 			   unsigned int display_limit);
48 
49 int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size);
50 
51 int ref_tracker_alloc(struct ref_tracker_dir *dir,
52 		      struct ref_tracker **trackerp, gfp_t gfp);
53 
54 int ref_tracker_free(struct ref_tracker_dir *dir,
55 		     struct ref_tracker **trackerp);
56 
57 #else /* CONFIG_REF_TRACKER */
58 
ref_tracker_dir_init(struct ref_tracker_dir * dir,unsigned int quarantine_count,const char * name)59 static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir,
60 					unsigned int quarantine_count,
61 					const char *name)
62 {
63 }
64 
ref_tracker_dir_exit(struct ref_tracker_dir * dir)65 static inline void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
66 {
67 }
68 
ref_tracker_dir_print_locked(struct ref_tracker_dir * dir,unsigned int display_limit)69 static inline void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir,
70 						unsigned int display_limit)
71 {
72 }
73 
ref_tracker_dir_print(struct ref_tracker_dir * dir,unsigned int display_limit)74 static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir,
75 					 unsigned int display_limit)
76 {
77 }
78 
ref_tracker_dir_snprint(struct ref_tracker_dir * dir,char * buf,size_t size)79 static inline int ref_tracker_dir_snprint(struct ref_tracker_dir *dir,
80 					  char *buf, size_t size)
81 {
82 	return 0;
83 }
84 
ref_tracker_alloc(struct ref_tracker_dir * dir,struct ref_tracker ** trackerp,gfp_t gfp)85 static inline int ref_tracker_alloc(struct ref_tracker_dir *dir,
86 				    struct ref_tracker **trackerp,
87 				    gfp_t gfp)
88 {
89 	return 0;
90 }
91 
ref_tracker_free(struct ref_tracker_dir * dir,struct ref_tracker ** trackerp)92 static inline int ref_tracker_free(struct ref_tracker_dir *dir,
93 				   struct ref_tracker **trackerp)
94 {
95 	return 0;
96 }
97 
98 #endif
99 
100 #endif /* _LINUX_REF_TRACKER_H */
101