2 * Copyright 2005-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_VOLUME_INLINE_H
11 #define _AFS_VOL_VOLUME_INLINE_H 1
15 * tell caller whether the given program type represents a salvaging
18 * @param type program type enumeration
20 * @return whether program state is a salvager
21 * @retval 0 type is a non-salvaging program
22 * @retval 1 type is a salvaging program
25 VIsSalvager(ProgramType type)
38 * tells caller whether or not we need to lock the entire partition when
41 * @return whether or not we need to lock the partition
42 * @retval 0 no, we do not
43 * @retval 1 yes, we do
46 VRequiresPartLock(void)
48 switch (programType) {
58 * tells caller whether we should check the inUse field in the volume
59 * header when attaching a volume.
61 * If we check inUse, that generally means we will salvage the volume
62 * (or put it in an error state) if we detect that another program
63 * claims to be using the volume when we try to attach. We don't always
64 * want to do that, since sometimes we know that the volume may be in
65 * use by another program, e.g. when we are attaching with V_PEEK, and
68 * @param mode the mode of attachment for the volume
70 * @return whether or not we should check inUse
71 * @retval 0 no, we should not check inUse
72 * @retval 1 yes, we should check inUse
75 VShouldCheckInUse(int mode)
77 if (programType == fileServer) {
80 if (VCanUseFSSYNC() && mode != V_SECRETLY && mode != V_PEEK) {
81 /* If we can FSSYNC, we assume we checked out the volume from
82 * the fileserver, so inUse should not be set. If we checked out
83 * with V_SECRETLY or V_PEEK, though, we didn't ask the
84 * fileserver, so don't check inUse. */
90 #ifdef AFS_DEMAND_ATTACH_FS
92 * acquire a non-blocking disk lock for a particular volume id.
94 * @param[in] volid the volume ID to lock
95 * @param[in] dp the partition on which 'volid' resides
96 * @param[in] locktype READ_LOCK or WRITE_LOCK
98 * @return operation status
99 * @retval 0 success, lock was obtained
100 * @retval EBUSY another process holds a conflicting lock
101 * @retval EIO error acquiring lock
103 * @note Use VLockVolumeNB instead, if possible; only use this directly if
104 * you are not dealing with 'Volume*'s and attached volumes and such
106 * @pre There must not be any other threads acquiring locks on the same volid
107 * and partition; the locks will not work correctly if two threads try to
108 * acquire locks for the same volume
111 VLockVolumeByIdNB(VolumeId volid, struct DiskPartition64 *dp, int locktype)
113 return VLockFileLock(&dp->volLockFile, volid, locktype, 1 /* nonblock */);
117 * release a lock acquired by VLockVolumeByIdNB.
119 * @param[in] volid the volume id to unlock
120 * @param[in] dp the partition on which 'volid' resides
122 * @pre volid was previously locked by VLockVolumeByIdNB
125 VUnlockVolumeById(VolumeId volid, struct DiskPartition64 *dp)
127 VLockFileUnlock(&dp->volLockFile, volid);
130 /***************************************************/
131 /* demand attach fs state machine routines */
132 /***************************************************/
135 * tells caller whether we need to keep volumes locked for the entire time we
136 * are using them, or if we can unlock volumes as soon as they are attached.
138 * @return whether we can unlock attached volumes or not
139 * @retval 1 yes, we can unlock attached volumes
140 * @retval 0 no, do not unlock volumes until we unattach them
143 VCanUnlockAttached(void)
145 switch(programType) {
154 * tells caller whether we need to lock a vol header with a write lock, a
155 * read lock, or if we do not need to lock it at all, when attaching.
157 * @param[in] mode volume attachment mode
158 * @param[in] writeable 1 if the volume is writable, 0 if not
160 * @return how we need to lock the vol header
161 * @retval 0 do not lock the vol header at all
162 * @retval READ_LOCK lock the vol header with a read lock
163 * @retval WRITE_LOCK lock the vol header with a write lock
165 * @note DAFS only (non-DAFS uses partition locks)
168 VVolLockType(int mode, int writeable)
170 switch (programType) {
183 /* volserver, vol utilies, etc */
204 assert(0 /* unknown checkout mode */);
211 * tells caller whether or not the current state requires
212 * exclusive access without holding glock.
214 * @param state volume state enumeration
216 * @return whether volume state is a mutually exclusive state
217 * @retval 0 no, state is re-entrant
218 * @retval 1 yes, state is mutually exclusive
220 * @note DEMAND_ATTACH_FS only
223 VIsExclusiveState(VolState state)
226 case VOL_STATE_UPDATING:
227 case VOL_STATE_ATTACHING:
228 case VOL_STATE_GET_BITMAP:
229 case VOL_STATE_HDR_LOADING:
230 case VOL_STATE_HDR_ATTACHING:
231 case VOL_STATE_OFFLINING:
232 case VOL_STATE_DETACHING:
233 case VOL_STATE_SALVSYNC_REQ:
234 case VOL_STATE_VNODE_ALLOC:
235 case VOL_STATE_VNODE_GET:
236 case VOL_STATE_VNODE_CLOSE:
237 case VOL_STATE_VNODE_RELEASE:
238 case VOL_STATE_VLRU_ADD:
246 * tell caller whether V_attachState is an error condition.
248 * @param state volume state enumeration
250 * @return whether volume state is in error state
251 * @retval 0 state is not an error state
252 * @retval 1 state is an error state
254 * @note DEMAND_ATTACH_FS only
257 VIsErrorState(VolState state)
260 case VOL_STATE_ERROR:
261 case VOL_STATE_SALVAGING:
269 * tell caller whether V_attachState is an offline condition.
271 * @param state volume state enumeration
273 * @return whether volume state is in offline state
274 * @retval 0 state is not an offline state
275 * @retval 1 state is an offline state
277 * @note DEMAND_ATTACH_FS only
280 VIsOfflineState(VolState state)
283 case VOL_STATE_UNATTACHED:
284 case VOL_STATE_ERROR:
285 case VOL_STATE_SALVAGING:
293 * tell caller whether V_attachState is valid.
295 * @param state volume state enumeration
297 * @return whether volume state is a mutually exclusive state
298 * @retval 0 no, state is not valid
299 * @retval 1 yes, state is a valid enumeration member
301 * @note DEMAND_ATTACH_FS only
303 * @note do we really want to treat VOL_STATE_FREED as valid?
306 VIsValidState(VolState state)
309 (state < VOL_STATE_COUNT)) {
316 * increment volume-package internal refcount.
318 * @param vp volume object pointer
320 * @internal volume package internal use only
322 * @pre VOL_LOCK must be held
324 * @post volume waiters refcount is incremented
326 * @see VCancelReservation_r
328 * @note DEMAND_ATTACH_FS only
331 VCreateReservation_r(Volume * vp)
337 * wait for the volume to change states.
339 * @param vp volume object pointer
341 * @pre VOL_LOCK held; ref held on volume
343 * @post VOL_LOCK held; volume state has changed from previous value
345 * @note DEMAND_ATTACH_FS only
348 VWaitStateChange_r(Volume * vp)
350 VolState state_save = V_attachState(vp);
352 assert(vp->nWaiters || vp->nUsers);
354 VOL_CV_WAIT(&V_attachCV(vp));
355 } while (V_attachState(vp) == state_save);
356 assert(V_attachState(vp) != VOL_STATE_FREED);
360 * wait for blocking ops to end.
362 * @pre VOL_LOCK held; ref held on volume
364 * @post VOL_LOCK held; volume not in exclusive state
366 * @param vp volume object pointer
368 * @note DEMAND_ATTACH_FS only
371 VWaitExclusiveState_r(Volume * vp)
373 assert(vp->nWaiters || vp->nUsers);
374 while (VIsExclusiveState(V_attachState(vp))) {
375 VOL_CV_WAIT(&V_attachCV(vp));
377 assert(V_attachState(vp) != VOL_STATE_FREED);
381 * change state, and notify other threads,
382 * return previous state to caller.
384 * @param vp pointer to volume object
385 * @param new_state new volume state value
388 * @post volume state changed; stats updated
390 * @return previous volume state
392 * @note DEMAND_ATTACH_FS only
394 static_inline VolState
395 VChangeState_r(Volume * vp, VolState new_state)
397 VolState old_state = V_attachState(vp);
399 /* XXX profiling need to make sure these counters
400 * don't kill performance... */
401 VStats.state_levels[old_state]--;
402 VStats.state_levels[new_state]++;
404 V_attachState(vp) = new_state;
405 assert(pthread_cond_broadcast(&V_attachCV(vp)) == 0);
409 #endif /* AFS_DEMAND_ATTACH_FS */
411 #define VENUMCASE(en) \
417 * translate a ProgramType code to a string.
419 * @param[in] type ProgramType numeric code
421 * @return a human-readable string for that program type
422 * @retval "**UNKNOWN**" an unknown ProgramType was given
425 VPTypeToString(ProgramType type)
428 VENUMCASE(fileServer);
429 VENUMCASE(volumeUtility);
431 VENUMCASE(salvageServer);
432 VENUMCASE(debugUtility);
433 VENUMCASE(volumeServer);
434 VENUMCASE(volumeSalvager);
436 return "**UNKNOWN**";
442 #endif /* _AFS_VOL_VOLUME_INLINE_H */