Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / vol / vnode_inline.h
1 /*
2 * Copyright 2007-2008, Sine Nomine Associates and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 #ifndef _AFS_VOL_VNODE_INLINE_H
11 #define _AFS_VOL_VNODE_INLINE_H 1
12
13 #include "vnode.h"
14
15 /***************************************************/
16 /* demand attach vnode state machine routines */
17 /***************************************************/
18
19 /**
20 * get a reference to a vnode object.
21 *
22 * @param[in] vnp vnode object pointer
23 *
24 * @internal vnode package internal use only
25 *
26 * @pre VOL_LOCK must be held
27 *
28 * @post vnode refcount incremented
29 *
30 * @see VnCancelReservation_r
31 */
32 static_inline void
33 VnCreateReservation_r(Vnode * vnp)
34 {
35 Vn_refcount(vnp)++;
36 if (Vn_refcount(vnp) == 1) {
37 DeleteFromVnLRU(Vn_class(vnp), vnp);
38 }
39 }
40
41 extern int TrustVnodeCacheEntry;
42
43 /**
44 * release a reference to a vnode object.
45 *
46 * @param[in] vnp vnode object pointer
47 *
48 * @pre VOL_LOCK held
49 *
50 * @post refcount decremented; possibly re-added to vn lru
51 *
52 * @internal vnode package internal use only
53 *
54 * @see VnCreateReservation_r
55 */
56 static_inline void
57 VnCancelReservation_r(Vnode * vnp)
58 {
59 if (--Vn_refcount(vnp) == 0) {
60 AddToVnLRU(Vn_class(vnp), vnp);
61
62 /* If caching is turned off,
63 * disassociate vnode cache entry from volume object */
64 if (!TrustVnodeCacheEntry) {
65 DeleteFromVVnList(vnp);
66 }
67 }
68 }
69
70 #ifdef AFS_PTHREAD_ENV
71 #define VN_SET_WRITER_THREAD_ID(v) (((v)->writer) = pthread_self())
72 #else
73 #define VN_SET_WRITER_THREAD_ID(v) (LWP_CurrentProcess(&((v)->writer)))
74 #endif
75
76 #define VOL_LOCK_NOT_HELD 0
77 #define VOL_LOCK_HELD 1
78 #define MIGHT_DEADLOCK 0
79 #define WILL_NOT_DEADLOCK 1
80
81 /**
82 * acquire a lock on a vnode object.
83 *
84 * @param[in] vnp vnode object pointer
85 * @param[in] type lock type
86 * @param[in] held whether or not vol glock is held
87 * @param[in] safe whether it it is safe to acquire without dropping vol glock
88 *
89 * @note caller must guarantee deadlock will not occur
90 *
91 * @post lock acquired.
92 * for write case, thread owner field set.
93 *
94 * @note for DAFS, this is a no-op
95 *
96 * @internal vnode package internal use only
97 */
98 static_inline void
99 VnLock(Vnode * vnp, int type, int held, int safe)
100 {
101 #ifdef AFS_DEMAND_ATTACH_FS
102 if (type == WRITE_LOCK) {
103 VN_SET_WRITER_THREAD_ID(vnp);
104 }
105 #else /* !AFS_DEMAND_ATTACH_FS */
106 if (held && !safe) {
107 VOL_UNLOCK;
108 }
109 if (type == READ_LOCK) {
110 ObtainReadLock(&vnp->lock);
111 } else {
112 ObtainWriteLock(&vnp->lock);
113 VN_SET_WRITER_THREAD_ID(vnp);
114 }
115 if (held && !safe) {
116 VOL_LOCK;
117 }
118 #endif /* !AFS_DEMAND_ATTACH_FS */
119 }
120
121 /**
122 * release a lock on a vnode object.
123 *
124 * @param[in] vnp vnode object pointer
125 * @param[in] type lock type
126 *
127 * @note for DAFS, this is a no-op
128 *
129 * @internal vnode package internal use only
130 */
131 static_inline void
132 VnUnlock(Vnode * vnp, int type)
133 {
134 if (type == READ_LOCK) {
135 #ifndef AFS_DEMAND_ATTACH_FS
136 ReleaseReadLock(&vnp->lock);
137 #endif
138 } else {
139 vnp->writer = 0;
140 #ifndef AFS_DEMAND_ATTACH_FS
141 ReleaseWriteLock(&vnp->lock);
142 #endif
143 }
144 }
145
146
147 #ifdef AFS_DEMAND_ATTACH_FS
148 /**
149 * change state, and notify other threads,
150 * return previous state to caller.
151 *
152 * @param[in] vnp pointer to vnode object
153 * @param[in] new_state new vnode state value
154 *
155 * @pre VOL_LOCK held
156 *
157 * @post vnode state changed
158 *
159 * @return previous vnode state
160 *
161 * @note DEMAND_ATTACH_FS only
162 *
163 * @internal vnode package internal use only
164 */
165 static_inline VnState
166 VnChangeState_r(Vnode * vnp, VnState new_state)
167 {
168 VnState old_state = Vn_state(vnp);
169
170 Vn_state(vnp) = new_state;
171 opr_cv_broadcast(&Vn_stateCV(vnp));
172 return old_state;
173 }
174
175 /**
176 * tells caller whether or not the current state requires
177 * exclusive access without holding glock.
178 *
179 * @param[in] state vnode state enumeration
180 *
181 * @return whether vnode state is a mutually exclusive state
182 * @retval 0 no, state is re-entrant
183 * @retval 1 yes, state is mutually exclusive
184 *
185 * @note DEMAND_ATTACH_FS only
186 */
187 static_inline int
188 VnIsExclusiveState(VnState state)
189 {
190 switch (state) {
191 case VN_STATE_RELEASING:
192 case VN_STATE_CLOSING:
193 case VN_STATE_ALLOC:
194 case VN_STATE_LOAD:
195 case VN_STATE_EXCLUSIVE:
196 case VN_STATE_STORE:
197 return 1;
198 default:
199 return 0;
200 }
201 }
202
203 /**
204 * tell caller whether vnode state is an error condition.
205 *
206 * @param[in] state vnode state enumeration
207 *
208 * @return whether vnode state is in error state
209 * @retval 0 state is not an error state
210 * @retval 1 state is an error state
211 *
212 * @note DEMAND_ATTACH_FS only
213 */
214 static_inline int
215 VnIsErrorState(VnState state)
216 {
217 switch (state) {
218 case VN_STATE_ERROR:
219 return 1;
220 default:
221 return 0;
222 }
223 }
224
225 /**
226 * tell caller whether vnode state is valid.
227 *
228 * @param[in] state vnode state enumeration
229 *
230 * @return whether vnode state is a mutually exclusive state
231 * @retval 0 no, state is not valid
232 * @retval 1 yes, state is a valid enumeration member
233 *
234 * @note DEMAND_ATTACH_FS only
235 */
236 static_inline int
237 VnIsValidState(VnState state)
238 {
239 if (((int) state >= 0) &&
240 (state < VN_STATE_COUNT)) {
241 return 1;
242 }
243 return 0;
244 }
245
246 /**
247 * wait for the vnode to change states.
248 *
249 * @param[in] vnp vnode object pointer
250 *
251 * @pre VOL_LOCK held; ref held on vnode
252 *
253 * @post VOL_LOCK held; vnode state has changed from previous value
254 *
255 * @note DEMAND_ATTACH_FS only
256 */
257 static_inline void
258 VnWaitStateChange_r(Vnode * vnp)
259 {
260 VnState state_save = Vn_state(vnp);
261
262 opr_Assert(Vn_refcount(vnp));
263 do {
264 VOL_CV_WAIT(&Vn_stateCV(vnp));
265 } while (Vn_state(vnp) == state_save);
266 opr_Assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
267 }
268
269 /**
270 * wait for blocking ops to end.
271 *
272 * @pre VOL_LOCK held; ref held on vnode
273 *
274 * @post VOL_LOCK held; vnode not in exclusive state
275 *
276 * @param[in] vnp vnode object pointer
277 *
278 * @note DEMAND_ATTACH_FS only
279 */
280 static_inline void
281 VnWaitExclusiveState_r(Vnode * vnp)
282 {
283 opr_Assert(Vn_refcount(vnp));
284 while (VnIsExclusiveState(Vn_state(vnp))) {
285 VOL_CV_WAIT(&Vn_stateCV(vnp));
286 }
287 opr_Assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
288 }
289
290 /**
291 * wait until vnode is in non-exclusive state, and there are no active readers.
292 *
293 * @param[in] vnp vnode object pointer
294 *
295 * @pre VOL_LOCK held; ref held on vnode
296 *
297 * @post VOL_LOCK held; vnode is in non-exclusive state and has no active readers
298 *
299 * @note DEMAND_ATTACH_FS only
300 */
301 static_inline void
302 VnWaitQuiescent_r(Vnode * vnp)
303 {
304 opr_Assert(Vn_refcount(vnp));
305 while (VnIsExclusiveState(Vn_state(vnp)) ||
306 Vn_readers(vnp)) {
307 VOL_CV_WAIT(&Vn_stateCV(vnp));
308 }
309 opr_Assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
310 }
311
312 /**
313 * register a new reader on a vnode.
314 *
315 * @param[in] vnp vnode object pointer
316 *
317 * @pre VOL_LOCK held.
318 * ref held on vnode.
319 * vnode in VN_STATE_READ or VN_STATE_ONLINE
320 *
321 * @post refcount incremented.
322 * state set to VN_STATE_READ.
323 *
324 * @note DEMAND_ATTACH_FS only
325 *
326 * @internal vnode package internal use only
327 */
328 static_inline void
329 VnBeginRead_r(Vnode * vnp)
330 {
331 if (!Vn_readers(vnp)) {
332 opr_Assert(Vn_state(vnp) == VN_STATE_ONLINE);
333 VnChangeState_r(vnp, VN_STATE_READ);
334 }
335 Vn_readers(vnp)++;
336 opr_Assert(Vn_state(vnp) == VN_STATE_READ);
337 }
338
339 /**
340 * deregister a reader on a vnode.
341 *
342 * @param[in] vnp vnode object pointer
343 *
344 * @pre VOL_LOCK held.
345 * ref held on vnode.
346 * read ref held on vnode.
347 * vnode in VN_STATE_READ.
348 *
349 * @post refcount decremented.
350 * when count reaches zero, state set to VN_STATE_ONLINE.
351 *
352 * @note DEMAND_ATTACH_FS only
353 *
354 * @internal vnode package internal use only
355 */
356 static_inline void
357 VnEndRead_r(Vnode * vnp)
358 {
359 opr_Assert(Vn_readers(vnp) > 0);
360 Vn_readers(vnp)--;
361 if (!Vn_readers(vnp)) {
362 opr_cv_broadcast(&Vn_stateCV(vnp));
363 VnChangeState_r(vnp, VN_STATE_ONLINE);
364 }
365 }
366
367 #endif /* AFS_DEMAND_ATTACH_FS */
368
369 #endif /* _AFS_VOL_VNODE_INLINE_H */