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
12 #ifndef _AFS_VOL_VOLUME_INLINE_H
13 #define _AFS_VOL_VOLUME_INLINE_H 1
16 #include "partition.h"
19 * tell caller whether the given program type represents a salvaging
22 * @param type program type enumeration
24 * @return whether program state is a salvager
25 * @retval 0 type is a non-salvaging program
26 * @retval 1 type is a salvaging program
29 VIsSalvager(ProgramType type)
42 * tells caller whether or not we need to lock the entire partition when
45 * @return whether or not we need to lock the partition
46 * @retval 0 no, we do not
47 * @retval 1 yes, we do
49 * @note for DAFS, always returns 0, since we use per-header locks instead
52 VRequiresPartLock(void)
54 #ifdef AFS_DEMAND_ATTACH_FS
57 switch (programType) {
64 #endif /* AFS_DEMAND_ATTACH_FS */
68 * tells caller whether or not we need to check out a volume from the
69 * fileserver before we can use it.
71 * @param[in] mode the mode of attachment for the volume
73 * @return whether or not we need to check out the volume from the fileserver
74 * @retval 0 no, we can just use the volume
75 * @retval 1 yes, we must check out the volume before use
78 VMustCheckoutVolume(int mode)
80 if (VCanUseFSSYNC() && mode != V_SECRETLY && mode != V_PEEK) {
87 * tells caller whether we should check the inUse field in the volume
88 * header when attaching a volume.
90 * If we check inUse, that generally means we will salvage the volume
91 * (or put it in an error state) if we detect that another program
92 * claims to be using the volume when we try to attach. We don't always
93 * want to do that, since sometimes we know that the volume may be in
94 * use by another program, e.g. when we are attaching with V_PEEK, and
97 * @param mode the mode of attachment for the volume
99 * @return whether or not we should check inUse
100 * @retval 0 no, we should not check inUse
101 * @retval 1 yes, we should check inUse
104 VShouldCheckInUse(int mode)
106 if (programType == fileServer) {
109 if (VMustCheckoutVolume(mode)) {
110 /* assume we checked out the volume from the fileserver, so inUse
111 * should not be set */
117 #ifdef AFS_DEMAND_ATTACH_FS
119 * acquire a non-blocking disk lock for a particular volume id.
121 * @param[in] volid the volume ID to lock
122 * @param[in] dp the partition on which 'volid' resides
123 * @param[in] locktype READ_LOCK or WRITE_LOCK
125 * @return operation status
126 * @retval 0 success, lock was obtained
127 * @retval EBUSY another process holds a conflicting lock
128 * @retval EIO error acquiring lock
130 * @note Use VLockVolumeNB instead, if possible; only use this directly if
131 * you are not dealing with 'Volume*'s and attached volumes and such
133 * @pre There must not be any other threads acquiring locks on the same volid
134 * and partition; the locks will not work correctly if two threads try to
135 * acquire locks for the same volume
138 VLockVolumeByIdNB(VolumeId volid, struct DiskPartition64 *dp, int locktype)
140 return VLockFileLock(&dp->volLockFile, volid, locktype, 1 /* nonblock */);
144 * release a lock acquired by VLockVolumeByIdNB.
146 * @param[in] volid the volume id to unlock
147 * @param[in] dp the partition on which 'volid' resides
149 * @pre volid was previously locked by VLockVolumeByIdNB
152 VUnlockVolumeById(VolumeId volid, struct DiskPartition64 *dp)
154 VLockFileUnlock(&dp->volLockFile, volid);
157 /***************************************************/
158 /* demand attach fs state machine routines */
159 /***************************************************/
162 * tells caller whether we need to keep volumes locked for the entire time we
163 * are using them, or if we can unlock volumes as soon as they are attached.
165 * @return whether we can unlock attached volumes or not
166 * @retval 1 yes, we can unlock attached volumes
167 * @retval 0 no, do not unlock volumes until we unattach them
170 VCanUnlockAttached(void)
172 switch(programType) {
181 * tells caller whether we need to lock a vol header with a write lock, a
182 * read lock, or if we do not need to lock it at all, when attaching.
184 * @param[in] mode volume attachment mode
185 * @param[in] writeable 1 if the volume is writable, 0 if not
187 * @return how we need to lock the vol header
188 * @retval 0 do not lock the vol header at all
189 * @retval READ_LOCK lock the vol header with a read lock
190 * @retval WRITE_LOCK lock the vol header with a write lock
192 * @note DAFS only (non-DAFS uses partition locks)
195 VVolLockType(int mode, int writeable)
197 switch (programType) {
210 /* volserver, vol utilies, etc */
231 assert(0 /* unknown checkout mode */);
238 * tells caller whether or not the current state requires
239 * exclusive access without holding glock.
241 * @param state volume state enumeration
243 * @return whether volume state is a mutually exclusive state
244 * @retval 0 no, state is re-entrant
245 * @retval 1 yes, state is mutually exclusive
247 * @note DEMAND_ATTACH_FS only
250 VIsExclusiveState(VolState state)
253 case VOL_STATE_UPDATING:
254 case VOL_STATE_ATTACHING:
255 case VOL_STATE_GET_BITMAP:
256 case VOL_STATE_HDR_LOADING:
257 case VOL_STATE_HDR_ATTACHING:
258 case VOL_STATE_OFFLINING:
259 case VOL_STATE_DETACHING:
260 case VOL_STATE_SALVSYNC_REQ:
261 case VOL_STATE_VNODE_ALLOC:
262 case VOL_STATE_VNODE_GET:
263 case VOL_STATE_VNODE_CLOSE:
264 case VOL_STATE_VNODE_RELEASE:
265 case VOL_STATE_VLRU_ADD:
273 * tell caller whether V_attachState is an error condition.
275 * @param state volume state enumeration
277 * @return whether volume state is in error state
278 * @retval 0 state is not an error state
279 * @retval 1 state is an error state
281 * @note DEMAND_ATTACH_FS only
284 VIsErrorState(VolState state)
287 case VOL_STATE_ERROR:
288 case VOL_STATE_SALVAGING:
296 * tell caller whether V_attachState is an offline condition.
298 * @param state volume state enumeration
300 * @return whether volume state is in offline state
301 * @retval 0 state is not an offline state
302 * @retval 1 state is an offline state
304 * @note DEMAND_ATTACH_FS only
307 VIsOfflineState(VolState state)
310 case VOL_STATE_UNATTACHED:
311 case VOL_STATE_ERROR:
312 case VOL_STATE_SALVAGING:
320 * tell caller whether V_attachState is valid.
322 * @param state volume state enumeration
324 * @return whether volume state is a mutually exclusive state
325 * @retval 0 no, state is not valid
326 * @retval 1 yes, state is a valid enumeration member
328 * @note DEMAND_ATTACH_FS only
330 * @note do we really want to treat VOL_STATE_FREED as valid?
333 VIsValidState(VolState state)
336 (state < VOL_STATE_COUNT)) {
343 * increment volume-package internal refcount.
345 * @param vp volume object pointer
347 * @internal volume package internal use only
349 * @pre VOL_LOCK must be held
351 * @post volume waiters refcount is incremented
353 * @see VCancelReservation_r
355 * @note DEMAND_ATTACH_FS only
358 VCreateReservation_r(Volume * vp)
364 * wait for the volume to change states.
366 * @param vp volume object pointer
368 * @pre VOL_LOCK held; ref held on volume
370 * @post VOL_LOCK held; volume state has changed from previous value
372 * @note DEMAND_ATTACH_FS only
375 VWaitStateChange_r(Volume * vp)
377 VolState state_save = V_attachState(vp);
379 assert(vp->nWaiters || vp->nUsers);
381 VOL_CV_WAIT(&V_attachCV(vp));
382 } while (V_attachState(vp) == state_save);
383 assert(V_attachState(vp) != VOL_STATE_FREED);
387 * wait for blocking ops to end.
389 * @pre VOL_LOCK held; ref held on volume
391 * @post VOL_LOCK held; volume not in exclusive state
393 * @param vp volume object pointer
395 * @note DEMAND_ATTACH_FS only
398 VWaitExclusiveState_r(Volume * vp)
400 assert(vp->nWaiters || vp->nUsers);
401 while (VIsExclusiveState(V_attachState(vp))) {
402 VOL_CV_WAIT(&V_attachCV(vp));
404 assert(V_attachState(vp) != VOL_STATE_FREED);
408 * change state, and notify other threads,
409 * return previous state to caller.
411 * @param vp pointer to volume object
412 * @param new_state new volume state value
415 * @post volume state changed; stats updated
417 * @return previous volume state
419 * @note DEMAND_ATTACH_FS only
421 static_inline VolState
422 VChangeState_r(Volume * vp, VolState new_state)
424 VolState old_state = V_attachState(vp);
426 /* XXX profiling need to make sure these counters
427 * don't kill performance... */
428 VStats.state_levels[old_state]--;
429 VStats.state_levels[new_state]++;
431 V_attachState(vp) = new_state;
432 assert(pthread_cond_broadcast(&V_attachCV(vp)) == 0);
436 #endif /* AFS_DEMAND_ATTACH_FS */
438 #define VENUMCASE(en) \
444 * translate a ProgramType code to a string.
446 * @param[in] type ProgramType numeric code
448 * @return a human-readable string for that program type
449 * @retval "**UNKNOWN**" an unknown ProgramType was given
452 VPTypeToString(ProgramType type)
455 VENUMCASE(fileServer);
456 VENUMCASE(volumeUtility);
458 VENUMCASE(salvageServer);
459 VENUMCASE(debugUtility);
460 VENUMCASE(volumeServer);
461 VENUMCASE(volumeSalvager);
463 return "**UNKNOWN**";
469 #endif /* _AFS_VOL_VOLUME_INLINE_H */