vol: Use OSI_NULLSOCKET and not -1 to indicate invalid fssync fd
[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     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 ((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     osi_Assert(Vn_refcount(vnp));
263     do {
264         VOL_CV_WAIT(&Vn_stateCV(vnp));
265     } while (Vn_state(vnp) == state_save);
266     osi_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     osi_Assert(Vn_refcount(vnp));
284     while (VnIsExclusiveState(Vn_state(vnp))) {
285         VOL_CV_WAIT(&Vn_stateCV(vnp));
286     }
287     osi_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     osi_Assert(Vn_refcount(vnp));
305     while (VnIsExclusiveState(Vn_state(vnp)) ||
306            Vn_readers(vnp)) {
307         VOL_CV_WAIT(&Vn_stateCV(vnp));
308     }
309     osi_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         osi_Assert(Vn_state(vnp) == VN_STATE_ONLINE);
333         VnChangeState_r(vnp, VN_STATE_READ);
334     }
335     Vn_readers(vnp)++;
336     osi_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     osi_Assert(Vn_readers(vnp) > 0);
360     Vn_readers(vnp)--;
361     if (!Vn_readers(vnp)) {
362         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 */