2 * Copyright 2007-2008, Sine Nomine Associates and others.
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
10 #ifndef _AFS_VOL_VNODE_INLINE_H
11 #define _AFS_VOL_VNODE_INLINE_H 1
16 #define static_inline static __inline
17 #elif defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
18 #define static_inline static
20 #define static_inline static inline
23 /***************************************************/
24 /* demand attach vnode state machine routines */
25 /***************************************************/
28 * get a reference to a vnode object.
30 * @param[in] vnp vnode object pointer
32 * @internal vnode package internal use only
34 * @pre VOL_LOCK must be held
36 * @post vnode refcount incremented
38 * @see VnCancelReservation_r
41 VnCreateReservation_r(Vnode * vnp)
44 if (Vn_refcount(vnp) == 1) {
45 DeleteFromVnLRU(Vn_class(vnp), vnp);
49 extern int TrustVnodeCacheEntry;
52 * release a reference to a vnode object.
54 * @param[in] vnp vnode object pointer
58 * @post refcount decremented; possibly re-added to vn lru
60 * @internal vnode package internal use only
62 * @see VnCreateReservation_r
65 VnCancelReservation_r(Vnode * vnp)
67 if (--Vn_refcount(vnp) == 0) {
68 AddToVnLRU(Vn_class(vnp), vnp);
70 /* If caching is turned off,
71 * disassociate vnode cache entry from volume object */
72 if (!TrustVnodeCacheEntry) {
73 DeleteFromVVnList(vnp);
78 #ifdef AFS_PTHREAD_ENV
79 #define VN_SET_WRITER_THREAD_ID(v) (((v)->writer) = pthread_self())
81 #define VN_SET_WRITER_THREAD_ID(v) (LWP_CurrentProcess(&((v)->writer)))
84 #define VOL_LOCK_NOT_HELD 0
85 #define VOL_LOCK_HELD 1
86 #define MIGHT_DEADLOCK 0
87 #define WILL_NOT_DEADLOCK 1
90 * acquire a lock on a vnode object.
92 * @param[in] vnp vnode object pointer
93 * @param[in] type lock type
94 * @param[in] held whether or not vol glock is held
95 * @param[in] safe whether it it is safe to acquire without dropping vol glock
97 * @note caller must guarantee deadlock will not occur
99 * @post lock acquired.
100 * for write case, thread owner field set.
102 * @note for DAFS, this is a no-op
104 * @internal vnode package internal use only
107 VnLock(Vnode * vnp, int type, int held, int safe)
109 #ifdef AFS_DEMAND_ATTACH_FS
110 if (type == WRITE_LOCK) {
111 VN_SET_WRITER_THREAD_ID(vnp);
113 #else /* !AFS_DEMAND_ATTACH_FS */
117 if (type == READ_LOCK) {
118 ObtainReadLock(&vnp->lock);
120 ObtainWriteLock(&vnp->lock);
121 VN_SET_WRITER_THREAD_ID(vnp);
126 #endif /* !AFS_DEMAND_ATTACH_FS */
130 * release a lock on a vnode object.
132 * @param[in] vnp vnode object pointer
133 * @param[in] type lock type
135 * @note for DAFS, this is a no-op
137 * @internal vnode package internal use only
140 VnUnlock(Vnode * vnp, int type)
142 if (type == READ_LOCK) {
143 #ifndef AFS_DEMAND_ATTACH_FS
144 ReleaseReadLock(&vnp->lock);
148 #ifndef AFS_DEMAND_ATTACH_FS
149 ReleaseWriteLock(&vnp->lock);
155 #ifdef AFS_DEMAND_ATTACH_FS
157 * change state, and notify other threads,
158 * return previous state to caller.
160 * @param[in] vnp pointer to vnode object
161 * @param[in] new_state new vnode state value
165 * @post vnode state changed
167 * @return previous vnode state
169 * @note DEMAND_ATTACH_FS only
171 * @internal vnode package internal use only
173 static_inline VnState
174 VnChangeState_r(Vnode * vnp, VnState new_state)
176 VnState old_state = Vn_state(vnp);
178 Vn_state(vnp) = new_state;
179 assert(pthread_cond_broadcast(&Vn_stateCV(vnp)) == 0);
184 * tells caller whether or not the current state requires
185 * exclusive access without holding glock.
187 * @param[in] state vnode state enumeration
189 * @return whether vnode state is a mutually exclusive state
190 * @retval 0 no, state is re-entrant
191 * @retval 1 yes, state is mutually exclusive
193 * @note DEMAND_ATTACH_FS only
196 VnIsExclusiveState(VnState state)
199 case VN_STATE_RELEASING:
200 case VN_STATE_CLOSING:
203 case VN_STATE_EXCLUSIVE:
211 * tell caller whether vnode state is an error condition.
213 * @param[in] state vnode state enumeration
215 * @return whether vnode state is in error state
216 * @retval 0 state is not an error state
217 * @retval 1 state is an error state
219 * @note DEMAND_ATTACH_FS only
222 VnIsErrorState(VnState state)
232 * tell caller whether vnode state is valid.
234 * @param[in] state vnode state enumeration
236 * @return whether vnode state is a mutually exclusive state
237 * @retval 0 no, state is not valid
238 * @retval 1 yes, state is a valid enumeration member
240 * @note DEMAND_ATTACH_FS only
243 VnIsValidState(VnState state)
246 (state < VN_STATE_COUNT)) {
253 * wait for the vnode to change states.
255 * @param[in] vnp vnode object pointer
257 * @pre VOL_LOCK held; ref held on vnode
259 * @post VOL_LOCK held; vnode state has changed from previous value
261 * @note DEMAND_ATTACH_FS only
264 VnWaitStateChange_r(Vnode * vnp)
266 VnState state_save = Vn_state(vnp);
268 assert(Vn_refcount(vnp));
270 VOL_CV_WAIT(&Vn_stateCV(vnp));
271 } while (Vn_state(vnp) == state_save);
272 assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
276 * wait for blocking ops to end.
278 * @pre VOL_LOCK held; ref held on vnode
280 * @post VOL_LOCK held; vnode not in exclusive state
282 * @param[in] vnp vnode object pointer
284 * @note DEMAND_ATTACH_FS only
287 VnWaitExclusiveState_r(Vnode * vnp)
289 assert(Vn_refcount(vnp));
290 while (VnIsExclusiveState(Vn_state(vnp))) {
291 VOL_CV_WAIT(&Vn_stateCV(vnp));
293 assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
297 * wait until vnode is in non-exclusive state, and there are no active readers.
299 * @param[in] vnp vnode object pointer
301 * @pre VOL_LOCK held; ref held on vnode
303 * @post VOL_LOCK held; vnode is in non-exclusive state and has no active readers
305 * @note DEMAND_ATTACH_FS only
308 VnWaitQuiescent_r(Vnode * vnp)
310 assert(Vn_refcount(vnp));
311 while (VnIsExclusiveState(Vn_state(vnp)) ||
313 VOL_CV_WAIT(&Vn_stateCV(vnp));
315 assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
319 * register a new reader on a vnode.
321 * @param[in] vnp vnode object pointer
323 * @pre VOL_LOCK held.
325 * vnode in VN_STATE_READ or VN_STATE_ONLINE
327 * @post refcount incremented.
328 * state set to VN_STATE_READ.
330 * @note DEMAND_ATTACH_FS only
332 * @internal vnode package internal use only
335 VnBeginRead_r(Vnode * vnp)
337 if (!Vn_readers(vnp)) {
338 assert(Vn_state(vnp) == VN_STATE_ONLINE);
339 VnChangeState_r(vnp, VN_STATE_READ);
342 assert(Vn_state(vnp) == VN_STATE_READ);
346 * deregister a reader on a vnode.
348 * @param[in] vnp vnode object pointer
350 * @pre VOL_LOCK held.
352 * read ref held on vnode.
353 * vnode in VN_STATE_READ.
355 * @post refcount decremented.
356 * when count reaches zero, state set to VN_STATE_ONLINE.
358 * @note DEMAND_ATTACH_FS only
360 * @internal vnode package internal use only
363 VnEndRead_r(Vnode * vnp)
365 assert(Vn_readers(vnp) > 0);
367 if (!Vn_readers(vnp)) {
368 assert(pthread_cond_broadcast(&Vn_stateCV(vnp)) == 0);
369 VnChangeState_r(vnp, VN_STATE_ONLINE);
373 #endif /* AFS_DEMAND_ATTACH_FS */
375 #endif /* _AFS_VOL_VNODE_INLINE_H */