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
15 /***************************************************/
16 /* demand attach vnode state machine routines */
17 /***************************************************/
20 * get a reference to a vnode object.
22 * @param[in] vnp vnode object pointer
24 * @internal vnode package internal use only
26 * @pre VOL_LOCK must be held
28 * @post vnode refcount incremented
30 * @see VnCancelReservation_r
33 VnCreateReservation_r(Vnode
* vnp
)
36 if (Vn_refcount(vnp
) == 1) {
37 DeleteFromVnLRU(Vn_class(vnp
), vnp
);
41 extern int TrustVnodeCacheEntry
;
44 * release a reference to a vnode object.
46 * @param[in] vnp vnode object pointer
50 * @post refcount decremented; possibly re-added to vn lru
52 * @internal vnode package internal use only
54 * @see VnCreateReservation_r
57 VnCancelReservation_r(Vnode
* vnp
)
59 if (--Vn_refcount(vnp
) == 0) {
60 AddToVnLRU(Vn_class(vnp
), vnp
);
62 /* If caching is turned off,
63 * disassociate vnode cache entry from volume object */
64 if (!TrustVnodeCacheEntry
) {
65 DeleteFromVVnList(vnp
);
70 #ifdef AFS_PTHREAD_ENV
71 #define VN_SET_WRITER_THREAD_ID(v) (((v)->writer) = pthread_self())
73 #define VN_SET_WRITER_THREAD_ID(v) (LWP_CurrentProcess(&((v)->writer)))
76 #define VOL_LOCK_NOT_HELD 0
77 #define VOL_LOCK_HELD 1
78 #define MIGHT_DEADLOCK 0
79 #define WILL_NOT_DEADLOCK 1
82 * acquire a lock on a vnode object.
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
89 * @note caller must guarantee deadlock will not occur
91 * @post lock acquired.
92 * for write case, thread owner field set.
94 * @note for DAFS, this is a no-op
96 * @internal vnode package internal use only
99 VnLock(Vnode
* vnp
, int type
, int held
, int safe
)
101 #ifdef AFS_DEMAND_ATTACH_FS
102 if (type
== WRITE_LOCK
) {
103 VN_SET_WRITER_THREAD_ID(vnp
);
105 #else /* !AFS_DEMAND_ATTACH_FS */
109 if (type
== READ_LOCK
) {
110 ObtainReadLock(&vnp
->lock
);
112 ObtainWriteLock(&vnp
->lock
);
113 VN_SET_WRITER_THREAD_ID(vnp
);
118 #endif /* !AFS_DEMAND_ATTACH_FS */
122 * release a lock on a vnode object.
124 * @param[in] vnp vnode object pointer
125 * @param[in] type lock type
127 * @note for DAFS, this is a no-op
129 * @internal vnode package internal use only
132 VnUnlock(Vnode
* vnp
, int type
)
134 if (type
== READ_LOCK
) {
135 #ifndef AFS_DEMAND_ATTACH_FS
136 ReleaseReadLock(&vnp
->lock
);
140 #ifndef AFS_DEMAND_ATTACH_FS
141 ReleaseWriteLock(&vnp
->lock
);
147 #ifdef AFS_DEMAND_ATTACH_FS
149 * change state, and notify other threads,
150 * return previous state to caller.
152 * @param[in] vnp pointer to vnode object
153 * @param[in] new_state new vnode state value
157 * @post vnode state changed
159 * @return previous vnode state
161 * @note DEMAND_ATTACH_FS only
163 * @internal vnode package internal use only
165 static_inline VnState
166 VnChangeState_r(Vnode
* vnp
, VnState new_state
)
168 VnState old_state
= Vn_state(vnp
);
170 Vn_state(vnp
) = new_state
;
171 CV_BROADCAST(&Vn_stateCV(vnp
));
176 * tells caller whether or not the current state requires
177 * exclusive access without holding glock.
179 * @param[in] state vnode state enumeration
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
185 * @note DEMAND_ATTACH_FS only
188 VnIsExclusiveState(VnState state
)
191 case VN_STATE_RELEASING
:
192 case VN_STATE_CLOSING
:
195 case VN_STATE_EXCLUSIVE
:
204 * tell caller whether vnode state is an error condition.
206 * @param[in] state vnode state enumeration
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
212 * @note DEMAND_ATTACH_FS only
215 VnIsErrorState(VnState state
)
226 * tell caller whether vnode state is valid.
228 * @param[in] state vnode state enumeration
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
234 * @note DEMAND_ATTACH_FS only
237 VnIsValidState(VnState state
)
239 if (((int) state
>= 0) &&
240 (state
< VN_STATE_COUNT
)) {
247 * wait for the vnode to change states.
249 * @param[in] vnp vnode object pointer
251 * @pre VOL_LOCK held; ref held on vnode
253 * @post VOL_LOCK held; vnode state has changed from previous value
255 * @note DEMAND_ATTACH_FS only
258 VnWaitStateChange_r(Vnode
* vnp
)
260 VnState state_save
= Vn_state(vnp
);
262 osi_Assert(Vn_refcount(vnp
));
264 VOL_CV_WAIT(&Vn_stateCV(vnp
));
265 } while (Vn_state(vnp
) == state_save
);
266 osi_Assert(!(Vn_stateFlags(vnp
) & VN_ON_LRU
));
270 * wait for blocking ops to end.
272 * @pre VOL_LOCK held; ref held on vnode
274 * @post VOL_LOCK held; vnode not in exclusive state
276 * @param[in] vnp vnode object pointer
278 * @note DEMAND_ATTACH_FS only
281 VnWaitExclusiveState_r(Vnode
* vnp
)
283 osi_Assert(Vn_refcount(vnp
));
284 while (VnIsExclusiveState(Vn_state(vnp
))) {
285 VOL_CV_WAIT(&Vn_stateCV(vnp
));
287 osi_Assert(!(Vn_stateFlags(vnp
) & VN_ON_LRU
));
291 * wait until vnode is in non-exclusive state, and there are no active readers.
293 * @param[in] vnp vnode object pointer
295 * @pre VOL_LOCK held; ref held on vnode
297 * @post VOL_LOCK held; vnode is in non-exclusive state and has no active readers
299 * @note DEMAND_ATTACH_FS only
302 VnWaitQuiescent_r(Vnode
* vnp
)
304 osi_Assert(Vn_refcount(vnp
));
305 while (VnIsExclusiveState(Vn_state(vnp
)) ||
307 VOL_CV_WAIT(&Vn_stateCV(vnp
));
309 osi_Assert(!(Vn_stateFlags(vnp
) & VN_ON_LRU
));
313 * register a new reader on a vnode.
315 * @param[in] vnp vnode object pointer
317 * @pre VOL_LOCK held.
319 * vnode in VN_STATE_READ or VN_STATE_ONLINE
321 * @post refcount incremented.
322 * state set to VN_STATE_READ.
324 * @note DEMAND_ATTACH_FS only
326 * @internal vnode package internal use only
329 VnBeginRead_r(Vnode
* vnp
)
331 if (!Vn_readers(vnp
)) {
332 osi_Assert(Vn_state(vnp
) == VN_STATE_ONLINE
);
333 VnChangeState_r(vnp
, VN_STATE_READ
);
336 osi_Assert(Vn_state(vnp
) == VN_STATE_READ
);
340 * deregister a reader on a vnode.
342 * @param[in] vnp vnode object pointer
344 * @pre VOL_LOCK held.
346 * read ref held on vnode.
347 * vnode in VN_STATE_READ.
349 * @post refcount decremented.
350 * when count reaches zero, state set to VN_STATE_ONLINE.
352 * @note DEMAND_ATTACH_FS only
354 * @internal vnode package internal use only
357 VnEndRead_r(Vnode
* vnp
)
359 osi_Assert(Vn_readers(vnp
) > 0);
361 if (!Vn_readers(vnp
)) {
362 CV_BROADCAST(&Vn_stateCV(vnp
));
363 VnChangeState_r(vnp
, VN_STATE_ONLINE
);
367 #endif /* AFS_DEMAND_ATTACH_FS */
369 #endif /* _AFS_VOL_VNODE_INLINE_H */