14e66934eSEric Dumazet // SPDX-License-Identifier: GPL-2.0-or-later
24e66934eSEric Dumazet #ifndef _LINUX_REF_TRACKER_H
34e66934eSEric Dumazet #define _LINUX_REF_TRACKER_H
44e66934eSEric Dumazet #include <linux/refcount.h>
54e66934eSEric Dumazet #include <linux/types.h>
64e66934eSEric Dumazet #include <linux/spinlock.h>
72dba5eb1SVlastimil Babka #include <linux/stackdepot.h>
84e66934eSEric Dumazet
94e66934eSEric Dumazet struct ref_tracker;
104e66934eSEric Dumazet
114e66934eSEric Dumazet struct ref_tracker_dir {
124e66934eSEric Dumazet #ifdef CONFIG_REF_TRACKER
134e66934eSEric Dumazet spinlock_t lock;
144e66934eSEric Dumazet unsigned int quarantine_avail;
154e66934eSEric Dumazet refcount_t untracked;
168fd5522fSEric Dumazet refcount_t no_tracker;
17e3ececfeSEric Dumazet bool dead;
184e66934eSEric Dumazet struct list_head list; /* List of active trackers */
194e66934eSEric Dumazet struct list_head quarantine; /* List of dead trackers */
20b6d7c0ebSAndrzej Hajda char name[32];
214e66934eSEric Dumazet #endif
224e66934eSEric Dumazet };
234e66934eSEric Dumazet
244e66934eSEric Dumazet #ifdef CONFIG_REF_TRACKER
25b6d7c0ebSAndrzej Hajda
ref_tracker_dir_init(struct ref_tracker_dir * dir,unsigned int quarantine_count,const char * name)264e66934eSEric Dumazet static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir,
27b6d7c0ebSAndrzej Hajda unsigned int quarantine_count,
28b6d7c0ebSAndrzej Hajda const char *name)
294e66934eSEric Dumazet {
304e66934eSEric Dumazet INIT_LIST_HEAD(&dir->list);
314e66934eSEric Dumazet INIT_LIST_HEAD(&dir->quarantine);
324e66934eSEric Dumazet spin_lock_init(&dir->lock);
334e66934eSEric Dumazet dir->quarantine_avail = quarantine_count;
34e3ececfeSEric Dumazet dir->dead = false;
354e66934eSEric Dumazet refcount_set(&dir->untracked, 1);
368fd5522fSEric Dumazet refcount_set(&dir->no_tracker, 1);
37b6d7c0ebSAndrzej Hajda strscpy(dir->name, name, sizeof(dir->name));
382dba5eb1SVlastimil Babka stack_depot_init();
394e66934eSEric Dumazet }
404e66934eSEric Dumazet
414e66934eSEric Dumazet void ref_tracker_dir_exit(struct ref_tracker_dir *dir);
424e66934eSEric Dumazet
437a113ff6SAndrzej Hajda void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir,
447a113ff6SAndrzej Hajda unsigned int display_limit);
457a113ff6SAndrzej Hajda
464e66934eSEric Dumazet void ref_tracker_dir_print(struct ref_tracker_dir *dir,
474e66934eSEric Dumazet unsigned int display_limit);
484e66934eSEric Dumazet
49*227c6c83SAndrzej Hajda int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size);
50*227c6c83SAndrzej Hajda
514e66934eSEric Dumazet int ref_tracker_alloc(struct ref_tracker_dir *dir,
524e66934eSEric Dumazet struct ref_tracker **trackerp, gfp_t gfp);
534e66934eSEric Dumazet
544e66934eSEric Dumazet int ref_tracker_free(struct ref_tracker_dir *dir,
554e66934eSEric Dumazet struct ref_tracker **trackerp);
564e66934eSEric Dumazet
574e66934eSEric Dumazet #else /* CONFIG_REF_TRACKER */
584e66934eSEric Dumazet
ref_tracker_dir_init(struct ref_tracker_dir * dir,unsigned int quarantine_count,const char * name)594e66934eSEric Dumazet static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir,
60b6d7c0ebSAndrzej Hajda unsigned int quarantine_count,
61b6d7c0ebSAndrzej Hajda const char *name)
624e66934eSEric Dumazet {
634e66934eSEric Dumazet }
644e66934eSEric Dumazet
ref_tracker_dir_exit(struct ref_tracker_dir * dir)654e66934eSEric Dumazet static inline void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
664e66934eSEric Dumazet {
674e66934eSEric Dumazet }
684e66934eSEric Dumazet
ref_tracker_dir_print_locked(struct ref_tracker_dir * dir,unsigned int display_limit)697a113ff6SAndrzej Hajda static inline void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir,
707a113ff6SAndrzej Hajda unsigned int display_limit)
717a113ff6SAndrzej Hajda {
727a113ff6SAndrzej Hajda }
737a113ff6SAndrzej Hajda
ref_tracker_dir_print(struct ref_tracker_dir * dir,unsigned int display_limit)744e66934eSEric Dumazet static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir,
754e66934eSEric Dumazet unsigned int display_limit)
764e66934eSEric Dumazet {
774e66934eSEric Dumazet }
784e66934eSEric Dumazet
ref_tracker_dir_snprint(struct ref_tracker_dir * dir,char * buf,size_t size)79*227c6c83SAndrzej Hajda static inline int ref_tracker_dir_snprint(struct ref_tracker_dir *dir,
80*227c6c83SAndrzej Hajda char *buf, size_t size)
81*227c6c83SAndrzej Hajda {
82*227c6c83SAndrzej Hajda return 0;
83*227c6c83SAndrzej Hajda }
84*227c6c83SAndrzej Hajda
ref_tracker_alloc(struct ref_tracker_dir * dir,struct ref_tracker ** trackerp,gfp_t gfp)854e66934eSEric Dumazet static inline int ref_tracker_alloc(struct ref_tracker_dir *dir,
864e66934eSEric Dumazet struct ref_tracker **trackerp,
874e66934eSEric Dumazet gfp_t gfp)
884e66934eSEric Dumazet {
894e66934eSEric Dumazet return 0;
904e66934eSEric Dumazet }
914e66934eSEric Dumazet
ref_tracker_free(struct ref_tracker_dir * dir,struct ref_tracker ** trackerp)924e66934eSEric Dumazet static inline int ref_tracker_free(struct ref_tracker_dir *dir,
934e66934eSEric Dumazet struct ref_tracker **trackerp)
944e66934eSEric Dumazet {
954e66934eSEric Dumazet return 0;
964e66934eSEric Dumazet }
974e66934eSEric Dumazet
984e66934eSEric Dumazet #endif
994e66934eSEric Dumazet
1004e66934eSEric Dumazet #endif /* _LINUX_REF_TRACKER_H */
101