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