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
14 #include "partition.h"
16 #ifdef AFS_DEMAND_ATTACH_FS
21 * tell caller whether the given program type represents a salvaging
24 * @param type program type enumeration
26 * @return whether program state is a salvager
27 * @retval 0 type is a non-salvaging program
28 * @retval 1 type is a salvaging program
31 VIsSalvager(ProgramType type)
44 * tells caller whether or not we need to lock the entire partition when
47 * @return whether or not we need to lock the partition
48 * @retval 0 no, we do not
49 * @retval 1 yes, we do
51 * @note for DAFS, always returns 0, since we use per-header locks instead
54 VRequiresPartLock(void)
56 #ifdef AFS_DEMAND_ATTACH_FS
59 switch (programType) {
66 #endif /* AFS_DEMAND_ATTACH_FS */
70 * tells caller whether or not we need to check out a volume from the
71 * fileserver before we can use it.
73 * @param[in] mode the mode of attachment for the volume
75 * @return whether or not we need to check out the volume from the fileserver
76 * @retval 0 no, we can just use the volume
77 * @retval 1 yes, we must check out the volume before use
80 VMustCheckoutVolume(int mode)
82 if (VCanUseFSSYNC() && mode != V_SECRETLY && mode != V_PEEK) {
89 * tells caller whether we should check the inUse field in the volume
90 * header when attaching a volume.
92 * If we check inUse, that generally means we will salvage the volume
93 * (or put it in an error state) if we detect that another program
94 * claims to be using the volume when we try to attach. We don't always
95 * want to do that, since sometimes we know that the volume may be in
96 * use by another program, e.g. when we are attaching with V_PEEK, and
99 * @param mode the mode of attachment for the volume
101 * @return whether or not we should check inUse
102 * @retval 0 no, we should not check inUse
103 * @retval 1 yes, we should check inUse
106 VShouldCheckInUse(int mode)
108 if (VCanUnsafeAttach()) {
111 if (programType == fileServer) {
114 if (VMustCheckoutVolume(mode)) {
115 /* assume we checked out the volume from the fileserver, so inUse
116 * should not be set */
122 #ifdef AFS_DEMAND_ATTACH_FS
124 * acquire a non-blocking disk lock for a particular volume id.
126 * @param[in] volid the volume ID to lock
127 * @param[in] dp the partition on which 'volid' resides
128 * @param[in] locktype READ_LOCK or WRITE_LOCK
130 * @return operation status
131 * @retval 0 success, lock was obtained
132 * @retval EBUSY another process holds a conflicting lock
133 * @retval EIO error acquiring lock
135 * @note Use VLockVolumeNB instead, if possible; only use this directly if
136 * you are not dealing with 'Volume*'s and attached volumes and such
138 * @pre There must not be any other threads acquiring locks on the same volid
139 * and partition; the locks will not work correctly if two threads try to
140 * acquire locks for the same volume
143 VLockVolumeByIdNB(VolumeId volid, struct DiskPartition64 *dp, int locktype)
145 return VLockFileLock(&dp->volLockFile, volid, locktype, 1 /* nonblock */);
149 * release a lock acquired by VLockVolumeByIdNB.
151 * @param[in] volid the volume id to unlock
152 * @param[in] dp the partition on which 'volid' resides
154 * @pre volid was previously locked by VLockVolumeByIdNB
157 VUnlockVolumeById(VolumeId volid, struct DiskPartition64 *dp)
159 VLockFileUnlock(&dp->volLockFile, volid);
162 /***************************************************/
163 /* demand attach fs state machine routines */
164 /***************************************************/
167 * tells caller whether we need to keep volumes locked for the entire time we
168 * are using them, or if we can unlock volumes as soon as they are attached.
170 * @return whether we can unlock attached volumes or not
171 * @retval 1 yes, we can unlock attached volumes
172 * @retval 0 no, do not unlock volumes until we unattach them
175 VCanUnlockAttached(void)
177 switch(programType) {
186 * tells caller whether we need to lock a vol header with a write lock, a
187 * read lock, or if we do not need to lock it at all, when attaching.
189 * @param[in] mode volume attachment mode
190 * @param[in] writeable 1 if the volume is writable, 0 if not
192 * @return how we need to lock the vol header
193 * @retval 0 do not lock the vol header at all
194 * @retval READ_LOCK lock the vol header with a read lock
195 * @retval WRITE_LOCK lock the vol header with a write lock
197 * @note DAFS only (non-DAFS uses partition locks)
200 VVolLockType(int mode, int writeable)
202 switch (programType) {
215 /* volserver, vol utilies, etc */
236 assert(0 /* unknown checkout mode */);
243 * tells caller whether or not the current state requires
244 * exclusive access without holding glock.
246 * @param state volume state enumeration
248 * @return whether volume state is a mutually exclusive state
249 * @retval 0 no, state is re-entrant
250 * @retval 1 yes, state is mutually exclusive
252 * @note DEMAND_ATTACH_FS only
255 VIsExclusiveState(VolState state)
258 case VOL_STATE_UPDATING:
259 case VOL_STATE_ATTACHING:
260 case VOL_STATE_GET_BITMAP:
261 case VOL_STATE_HDR_LOADING:
262 case VOL_STATE_HDR_ATTACHING:
263 case VOL_STATE_OFFLINING:
264 case VOL_STATE_DETACHING:
265 case VOL_STATE_SALVSYNC_REQ:
266 case VOL_STATE_VNODE_ALLOC:
267 case VOL_STATE_VNODE_GET:
268 case VOL_STATE_VNODE_CLOSE:
269 case VOL_STATE_VNODE_RELEASE:
270 case VOL_STATE_VLRU_ADD:
278 * tell caller whether V_attachState is an error condition.
280 * @param state volume state enumeration
282 * @return whether volume state is in error state
283 * @retval 0 state is not an error state
284 * @retval 1 state is an error state
286 * @note DEMAND_ATTACH_FS only
289 VIsErrorState(VolState state)
292 case VOL_STATE_ERROR:
293 case VOL_STATE_SALVAGING:
301 * tell caller whether V_attachState is an offline condition.
303 * @param state volume state enumeration
305 * @return whether volume state is in offline state
306 * @retval 0 state is not an offline state
307 * @retval 1 state is an offline state
309 * @note DEMAND_ATTACH_FS only
312 VIsOfflineState(VolState state)
315 case VOL_STATE_UNATTACHED:
316 case VOL_STATE_ERROR:
317 case VOL_STATE_SALVAGING:
318 case VOL_STATE_DELETED:
326 * tell caller whether V_attachState is valid.
328 * @param state volume state enumeration
330 * @return whether volume state is a mutually exclusive state
331 * @retval 0 no, state is not valid
332 * @retval 1 yes, state is a valid enumeration member
334 * @note DEMAND_ATTACH_FS only
336 * @note do we really want to treat VOL_STATE_FREED as valid?
339 VIsValidState(VolState state)
342 (state < VOL_STATE_COUNT)) {
349 * increment volume-package internal refcount.
351 * @param vp volume object pointer
353 * @internal volume package internal use only
355 * @pre VOL_LOCK must be held
357 * @post volume waiters refcount is incremented
359 * @see VCancelReservation_r
361 * @note DEMAND_ATTACH_FS only
364 VCreateReservation_r(Volume * vp)
370 * wait for the volume to change states.
372 * @param vp volume object pointer
374 * @pre VOL_LOCK held; ref held on volume
376 * @post VOL_LOCK held; volume state has changed from previous value
378 * @note DEMAND_ATTACH_FS only
381 VWaitStateChange_r(Volume * vp)
383 VolState state_save = V_attachState(vp);
385 assert(vp->nWaiters || vp->nUsers);
387 VOL_CV_WAIT(&V_attachCV(vp));
388 } while (V_attachState(vp) == state_save);
389 assert(V_attachState(vp) != VOL_STATE_FREED);
393 * wait for blocking ops to end.
395 * @pre VOL_LOCK held; ref held on volume
397 * @post VOL_LOCK held; volume not in exclusive state
399 * @param vp volume object pointer
401 * @note DEMAND_ATTACH_FS only
404 VWaitExclusiveState_r(Volume * vp)
406 assert(vp->nWaiters || vp->nUsers);
407 while (VIsExclusiveState(V_attachState(vp))) {
408 VOL_CV_WAIT(&V_attachCV(vp));
410 assert(V_attachState(vp) != VOL_STATE_FREED);
414 * change state, and notify other threads,
415 * return previous state to caller.
417 * @param vp pointer to volume object
418 * @param new_state new volume state value
421 * @post volume state changed; stats updated
423 * @return previous volume state
425 * @note DEMAND_ATTACH_FS only
427 static_inline VolState
428 VChangeState_r(Volume * vp, VolState new_state)
430 VolState old_state = V_attachState(vp);
432 /* XXX profiling need to make sure these counters
433 * don't kill performance... */
434 VStats.state_levels[old_state]--;
435 VStats.state_levels[new_state]++;
437 V_attachState(vp) = new_state;
438 assert(pthread_cond_broadcast(&V_attachCV(vp)) == 0);
442 #endif /* AFS_DEMAND_ATTACH_FS */
444 #define VENUMCASE(en) \
450 * translate a ProgramType code to a string.
452 * @param[in] type ProgramType numeric code
454 * @return a human-readable string for that program type
455 * @retval "**UNKNOWN**" an unknown ProgramType was given
458 VPTypeToString(ProgramType type)
461 VENUMCASE(fileServer);
462 VENUMCASE(volumeUtility);
464 VENUMCASE(salvageServer);
465 VENUMCASE(debugUtility);
466 VENUMCASE(volumeServer);
467 VENUMCASE(volumeSalvager);
469 return "**UNKNOWN**";
475 #endif /* _AFS_VOL_VOLUME_INLINE_H */