1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _BCACHEFS_ENUMERATED_REF_H 3 #define _BCACHEFS_ENUMERATED_REF_H 4 5 #include "enumerated_ref_types.h" 6 7 /* 8 * A refcount where the users are enumerated: in debug mode, we create sepate 9 * refcounts for each user, to make leaks and refcount errors easy to track 10 * down: 11 */ 12 13 #ifdef ENUMERATED_REF_DEBUG 14 void enumerated_ref_get(struct enumerated_ref *, unsigned); 15 bool __enumerated_ref_tryget(struct enumerated_ref *, unsigned); 16 bool enumerated_ref_tryget(struct enumerated_ref *, unsigned); 17 void enumerated_ref_put(struct enumerated_ref *, unsigned); 18 #else 19 20 static inline void enumerated_ref_get(struct enumerated_ref *ref, unsigned idx) 21 { 22 percpu_ref_get(&ref->ref); 23 } 24 25 static inline bool __enumerated_ref_tryget(struct enumerated_ref *ref, unsigned idx) 26 { 27 return percpu_ref_tryget(&ref->ref); 28 } 29 30 static inline bool enumerated_ref_tryget(struct enumerated_ref *ref, unsigned idx) 31 { 32 return percpu_ref_tryget_live(&ref->ref); 33 } 34 35 static inline void enumerated_ref_put(struct enumerated_ref *ref, unsigned idx) 36 { 37 percpu_ref_put(&ref->ref); 38 } 39 #endif 40 41 static inline bool enumerated_ref_is_zero(struct enumerated_ref *ref) 42 { 43 #ifndef ENUMERATED_REF_DEBUG 44 return percpu_ref_is_zero(&ref->ref); 45 #else 46 for (unsigned i = 0; i < ref->nr; i++) 47 if (atomic_long_read(&ref->refs[i])) 48 return false; 49 return true; 50 #endif 51 } 52 53 void enumerated_ref_stop_async(struct enumerated_ref *); 54 void enumerated_ref_stop(struct enumerated_ref *, const char * const[]); 55 void enumerated_ref_start(struct enumerated_ref *); 56 57 void enumerated_ref_exit(struct enumerated_ref *); 58 int enumerated_ref_init(struct enumerated_ref *, unsigned, 59 void (*stop_fn)(struct enumerated_ref *)); 60 61 struct printbuf; 62 void enumerated_ref_to_text(struct printbuf *, 63 struct enumerated_ref *, 64 const char * const[]); 65 66 #endif /* _BCACHEFS_ENUMERATED_REF_H */ 67