Move *SYNC string translation out of fssync-debug
[openafs.git] / src / vol / volume_inline.h
1 /*
2  * Copyright 2005-2008, Sine Nomine Associates and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #ifndef _AFS_VOL_VOLUME_INLINE_H
11 #define _AFS_VOL_VOLUME_INLINE_H 1
12
13 #include "volume.h"
14 /**
15  * tell caller whether the given program type represents a salvaging
16  * program.
17  *
18  * @param type  program type enumeration
19  *
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
23  */
24 static_inline int
25 VIsSalvager(ProgramType type)
26 {
27     switch(type) {
28     case salvager:
29     case salvageServer:
30     case volumeSalvager:
31         return 1;
32     default:
33         return 0;
34     }
35 }
36
37 /**
38  * tells caller whether or not we need to lock the entire partition when
39  * attaching a volume.
40  *
41  * @return whether or not we need to lock the partition
42  *  @retval 0  no, we do not
43  *  @retval 1  yes, we do
44  */
45 static_inline int
46 VRequiresPartLock(void)
47 {
48     switch (programType) {
49     case volumeServer:
50     case volumeUtility:
51         return 1;
52     default:
53         return 0;
54     }
55 }
56
57 /**
58  * tells caller whether we should check the inUse field in the volume
59  * header when attaching a volume.
60  *
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
66  * we don't care.
67  *
68  * @param mode  the mode of attachment for the volume
69  *
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
73  */
74 static_inline int
75 VShouldCheckInUse(int mode)
76 {
77     if (programType == fileServer) {
78        return 1;
79     }
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. */
85        return 1;
86     }
87     return 0;
88 }
89
90 /***************************************************/
91 /* demand attach fs state machine routines         */
92 /***************************************************/
93
94 #ifdef AFS_DEMAND_ATTACH_FS
95 /**
96  * tells caller whether or not the current state requires
97  * exclusive access without holding glock.
98  *
99  * @param state  volume state enumeration
100  *
101  * @return whether volume state is a mutually exclusive state
102  *   @retval 0  no, state is re-entrant
103  *   @retval 1  yes, state is mutually exclusive
104  *
105  * @note DEMAND_ATTACH_FS only
106  */
107 static_inline int
108 VIsExclusiveState(VolState state)
109 {
110     switch (state) {
111     case VOL_STATE_UPDATING:
112     case VOL_STATE_ATTACHING:
113     case VOL_STATE_GET_BITMAP:
114     case VOL_STATE_HDR_LOADING:
115     case VOL_STATE_HDR_ATTACHING:
116     case VOL_STATE_OFFLINING:
117     case VOL_STATE_DETACHING:
118     case VOL_STATE_SALVSYNC_REQ:
119     case VOL_STATE_VNODE_ALLOC:
120     case VOL_STATE_VNODE_GET:
121     case VOL_STATE_VNODE_CLOSE:
122     case VOL_STATE_VNODE_RELEASE:
123     case VOL_STATE_VLRU_ADD:
124         return 1;
125     default:
126         return 0;
127     }
128 }
129
130 /**
131  * tell caller whether V_attachState is an error condition.
132  *
133  * @param state  volume state enumeration
134  *
135  * @return whether volume state is in error state
136  *   @retval 0  state is not an error state
137  *   @retval 1  state is an error state
138  *
139  * @note DEMAND_ATTACH_FS only
140  */
141 static_inline int
142 VIsErrorState(VolState state)
143 {
144     switch (state) {
145     case VOL_STATE_ERROR:
146     case VOL_STATE_SALVAGING:
147         return 1;
148     default:
149         return 0;
150     }
151 }
152
153 /**
154  * tell caller whether V_attachState is an offline condition.
155  *
156  * @param state  volume state enumeration
157  *
158  * @return whether volume state is in offline state
159  *   @retval 0  state is not an offline state
160  *   @retval 1  state is an offline state
161  *
162  * @note DEMAND_ATTACH_FS only
163  */
164 static_inline int
165 VIsOfflineState(VolState state)
166 {
167     switch (state) {
168     case VOL_STATE_UNATTACHED:
169     case VOL_STATE_ERROR:
170     case VOL_STATE_SALVAGING:
171         return 1;
172     default:
173         return 0;
174     }
175 }
176
177 /**
178  * tell caller whether V_attachState is valid.
179  *
180  * @param state  volume state enumeration
181  *
182  * @return whether volume state is a mutually exclusive state
183  *   @retval 0  no, state is not valid
184  *   @retval 1  yes, state is a valid enumeration member
185  *
186  * @note DEMAND_ATTACH_FS only
187  *
188  * @note do we really want to treat VOL_STATE_FREED as valid?
189  */
190 static_inline int
191 VIsValidState(VolState state)
192 {
193     if ((state >= 0) && 
194         (state < VOL_STATE_COUNT)) {
195         return 1;
196     }
197     return 0;
198 }
199
200 /**
201  * increment volume-package internal refcount.
202  *
203  * @param vp  volume object pointer
204  *
205  * @internal volume package internal use only
206  *
207  * @pre VOL_LOCK must be held
208  *
209  * @post volume waiters refcount is incremented
210  *
211  * @see VCancelReservation_r
212  *
213  * @note DEMAND_ATTACH_FS only
214  */
215 static_inline void
216 VCreateReservation_r(Volume * vp)
217 {
218     vp->nWaiters++;
219 }
220
221 /**
222  * wait for the volume to change states.
223  *
224  * @param vp  volume object pointer
225  *
226  * @pre VOL_LOCK held; ref held on volume
227  *
228  * @post VOL_LOCK held; volume state has changed from previous value
229  *
230  * @note DEMAND_ATTACH_FS only
231  */
232 static_inline void
233 VWaitStateChange_r(Volume * vp)
234 {
235     VolState state_save = V_attachState(vp);
236
237     assert(vp->nWaiters || vp->nUsers);
238     do {
239         VOL_CV_WAIT(&V_attachCV(vp));
240     } while (V_attachState(vp) == state_save);
241     assert(V_attachState(vp) != VOL_STATE_FREED);
242 }
243
244 /**
245  * wait for blocking ops to end.
246  *
247  * @pre VOL_LOCK held; ref held on volume
248  *
249  * @post VOL_LOCK held; volume not in exclusive state
250  *
251  * @param vp  volume object pointer
252  *
253  * @note DEMAND_ATTACH_FS only
254  */
255 static_inline void
256 VWaitExclusiveState_r(Volume * vp)
257 {
258     assert(vp->nWaiters || vp->nUsers);
259     while (VIsExclusiveState(V_attachState(vp))) {
260         VOL_CV_WAIT(&V_attachCV(vp));
261     }
262     assert(V_attachState(vp) != VOL_STATE_FREED);
263 }
264
265 /**
266  * change state, and notify other threads,
267  * return previous state to caller.
268  *
269  * @param vp         pointer to volume object
270  * @param new_state  new volume state value
271  * @pre VOL_LOCK held
272  *
273  * @post volume state changed; stats updated
274  *
275  * @return previous volume state
276  *
277  * @note DEMAND_ATTACH_FS only
278  */
279 static_inline VolState
280 VChangeState_r(Volume * vp, VolState new_state)
281 {
282     VolState old_state = V_attachState(vp);
283
284     /* XXX profiling need to make sure these counters
285      * don't kill performance... */
286     VStats.state_levels[old_state]--;
287     VStats.state_levels[new_state]++;
288
289     V_attachState(vp) = new_state;
290     assert(pthread_cond_broadcast(&V_attachCV(vp)) == 0);
291     return old_state;
292 }
293
294 #endif /* AFS_DEMAND_ATTACH_FS */
295
296 #define VENUMCASE(en) \
297     case en: \
298         return #en; \
299         break
300
301 /**
302  * translate a ProgramType code to a string.
303  *
304  * @param[in] type ProgramType numeric code
305  *
306  * @return a human-readable string for that program type
307  *  @retval "**UNKNOWN**" an unknown ProgramType was given
308  */
309 static_inline char *
310 VPTypeToString(ProgramType type)
311 {
312     switch (type) {
313         VENUMCASE(fileServer);
314         VENUMCASE(volumeUtility);
315         VENUMCASE(salvager);
316         VENUMCASE(salvageServer);
317         VENUMCASE(debugUtility);
318         VENUMCASE(volumeServer);
319         VENUMCASE(volumeSalvager);
320     default:
321         return "**UNKNOWN**";
322     }
323 }
324
325 #undef VENUMCASE
326
327 #endif /* _AFS_VOL_VOLUME_INLINE_H */