Whamcloud - gitweb
LU-17705 ptlrpc: replace synchronize_rcu() with rcu_barrier()
[fs/lustre-release.git] / lustre / include / lu_ref.h
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
4  * Use is subject to license terms.
5  *
6  * Copyright (c) 2012, 2013, Intel Corporation.
7  *
8  *   Author: Nikita Danilov <nikita.danilov@sun.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  */
22
23 #ifndef __LUSTRE_LU_REF_H
24 #define __LUSTRE_LU_REF_H
25
26 #include <linux/list.h>
27
28 /** \defgroup lu_ref lu_ref
29  *
30  * An interface to track references between objects. Mostly for debugging.
31  *
32  * Suppose there is a reference counted data-structure struct foo. To track
33  * who acquired references to instance of struct foo, add lu_ref field to it:
34  *
35  * \code
36  *       struct foo {
37  *               atomic_t      foo_refcount;
38  *               struct lu_ref foo_reference;
39  *               ...
40  *       };
41  * \endcode
42  *
43  * foo::foo_reference has to be initialized by calling
44  * lu_ref_init(). Typically there will be functions or macros to increment and
45  * decrement foo::foo_refcount, let's say they are foo_get(struct foo *foo)
46  * and foo_put(struct foo *foo), respectively.
47  *
48  * Whenever foo_get() is called to acquire a reference on a foo, lu_ref_add()
49  * has to be called to insert into foo::foo_reference a record, describing
50  * acquired reference. Dually, lu_ref_del() removes matching record. Typical
51  * usages are:
52  *
53  * \code
54  *      struct bar *bar;
55  *
56  *      // bar owns a reference to foo.
57  *      bar->bar_foo = foo_get(foo);
58  *      lu_ref_add(&foo->foo_reference, "bar", bar);
59  *
60  *      ...
61  *
62  *      // reference from bar to foo is released.
63  *      lu_ref_del(&foo->foo_reference, "bar", bar);
64  *      foo_put(bar->bar_foo);
65  *
66  *
67  *      // current thread acquired a temporary reference to foo.
68  *      foo_get(foo);
69  *      lu_ref_add(&foo->reference, __func__, current);
70  *
71  *      ...
72  *
73  *      // temporary reference is released.
74  *      lu_ref_del(&foo->reference, __func__, current);
75  *      foo_put(foo);
76  * \endcode
77  *
78  * \e Et \e cetera. Often it makes sense to include lu_ref_add() and
79  * lu_ref_del() calls into foo_get() and foo_put(). When an instance of struct
80  * foo is destroyed, lu_ref_fini() has to be called that checks that no
81  * pending references remain. lu_ref_print() can be used to dump a list of
82  * pending references, while hunting down a leak.
83  *
84  * For objects to which a large number of references can be acquired,
85  * lu_ref_del() can become cpu consuming, as it has to scan the list of
86  * references. To work around this, remember result of lu_ref_add() (usually
87  * in the same place where pointer to struct foo is stored), and use
88  * lu_ref_del_at():
89  *
90  * \code
91  *      // There is a large number of bar's for a single foo.
92  *      bar->bar_foo     = foo_get(foo);
93  *      bar->bar_foo_ref = lu_ref_add(&foo->foo_reference, "bar", bar);
94  *
95  *      ...
96  *
97  *      // reference from bar to foo is released.
98  *      lu_ref_del_at(&foo->foo_reference, bar->bar_foo_ref, "bar", bar);
99  *      foo_put(bar->bar_foo);
100  * \endcode
101  *
102  * lu_ref interface degrades gracefully in case of memory shortages.
103  *
104  * @{
105  */
106
107 #ifdef CONFIG_LUSTRE_DEBUG_LU_REF
108
109 /**
110  * Data-structure to keep track of references to a given object. This is used
111  * for debugging.
112  *
113  * lu_ref is embedded into an object which other entities (objects, threads,
114  * etc.) refer to.
115  */
116 struct lu_ref {
117         /**
118          * Spin-lock protecting lu_ref::lf_list.
119          */
120         spinlock_t              lf_guard;
121         /**
122          * List of all outstanding references (each represented by struct
123          * lu_ref_link), pointing to this object.
124          */
125         struct list_head        lf_list;
126         /**
127          * # of links.
128          */
129         short                   lf_refs;
130         /**
131          * Flag set when lu_ref_add() failed to allocate lu_ref_link. It is
132          * used to mask spurious failure of the following lu_ref_del().
133          */
134         short                   lf_failed;
135         /**
136          * flags - attribute for the lu_ref, for pad and future use.
137          */
138         short                   lf_flags;
139         /**
140          * Where was I initialized?
141          */
142         short                   lf_line;
143         const char              *lf_func;
144         /**
145          * Linkage into a global list of all lu_ref's (lu_ref_refs).
146          */
147         struct list_head        lf_linkage;
148 };
149
150 struct lu_ref_link {
151         struct lu_ref   *ll_ref;
152         struct list_head ll_linkage;
153         const char      *ll_scope;
154         const void      *ll_source;
155 };
156
157 void lu_ref_init_loc(struct lu_ref *ref, const char *func, const int line);
158 void lu_ref_fini(struct lu_ref *ref);
159 #define lu_ref_init(ref) lu_ref_init_loc(ref, __func__, __LINE__)
160
161 void lu_ref_add(struct lu_ref *ref, const char *scope, const void *source);
162
163 void lu_ref_add_atomic(struct lu_ref *ref, const char *scope,
164                        const void *source);
165
166 void lu_ref_add_at(struct lu_ref *ref, struct lu_ref_link *link,
167                    const char *scope, const void *source);
168
169 void lu_ref_del(struct lu_ref *ref, const char *scope, const void *source);
170
171 void lu_ref_set_at(struct lu_ref *ref, struct lu_ref_link *link,
172                    const char *scope, const void *source0, const void *source1);
173
174 void lu_ref_del_at(struct lu_ref *ref, struct lu_ref_link *link,
175                    const char *scope, const void *source);
176
177 void lu_ref_print(const struct lu_ref *ref);
178
179 void lu_ref_print_all(void);
180
181 int lu_ref_global_init(void);
182
183 void lu_ref_global_fini(void);
184
185 #else /* !CONFIG_LUSTRE_DEBUG_LU_REF */
186
187 struct lu_ref {
188 };
189
190 struct lu_ref_link {
191 };
192
193 static inline void lu_ref_init(struct lu_ref *ref)
194 {
195 }
196
197 static inline void lu_ref_fini(struct lu_ref *ref)
198 {
199 }
200
201 static inline void lu_ref_add(struct lu_ref *ref,
202                               const char *scope,
203                               const void *source)
204 {
205 }
206
207 static inline void lu_ref_add_atomic(struct lu_ref *ref,
208                                      const char *scope,
209                                      const void *source)
210 {
211 }
212
213 static inline void lu_ref_add_at(struct lu_ref *ref,
214                                  struct lu_ref_link *link,
215                                  const char *scope,
216                                  const void *source)
217 {
218 }
219
220 static inline void lu_ref_del(struct lu_ref *ref, const char *scope,
221                               const void *source)
222 {
223 }
224
225 static inline void lu_ref_set_at(struct lu_ref *ref, struct lu_ref_link *link,
226                                  const char *scope, const void *source0,
227                                  const void *source1)
228 {
229 }
230
231 static inline void lu_ref_del_at(struct lu_ref *ref, struct lu_ref_link *link,
232                                  const char *scope, const void *source)
233 {
234 }
235
236 static inline int lu_ref_global_init(void)
237 {
238         return 0;
239 }
240
241 static inline void lu_ref_global_fini(void)
242 {
243 }
244
245 static inline void lu_ref_print(const struct lu_ref *ref)
246 {
247 }
248
249 static inline void lu_ref_print_all(void)
250 {
251 }
252 #endif /* CONFIG_LUSTRE_DEBUG_LU_REF */
253
254 /** @} lu */
255
256 #endif /* __LUSTRE_LU_REF_H */