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