vol-dafs-aix-fixes-20080313
[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 #ifdef AFS_HPUX_ENV
16 #define static_inline static __inline
17 #elif defined(AFS_AIX_ENV)
18 #define static_inline static
19 #else
20 #define static_inline static inline
21 #endif
22
23
24 /***************************************************/
25 /* demand attach fs state machine routines         */
26 /***************************************************/
27
28 #ifdef AFS_DEMAND_ATTACH_FS
29 /**
30  * tells caller whether or not the current state requires
31  * exclusive access without holding glock.
32  *
33  * @param state  volume state enumeration
34  *
35  * @return whether volume state is a mutually exclusive state
36  *   @retval 0  no, state is re-entrant
37  *   @retval 1  yes, state is mutually exclusive
38  *
39  * @note DEMAND_ATTACH_FS only
40  *
41  * @note should VOL_STATE_SALVSYNC_REQ be treated as exclusive?
42  */
43 static_inline int
44 VIsExclusiveState(VolState state)
45 {
46     switch (state) {
47     case VOL_STATE_UPDATING:
48     case VOL_STATE_ATTACHING:
49     case VOL_STATE_GET_BITMAP:
50     case VOL_STATE_HDR_LOADING:
51     case VOL_STATE_HDR_ATTACHING:
52     case VOL_STATE_OFFLINING:
53     case VOL_STATE_DETACHING:
54     case VOL_STATE_VNODE_ALLOC:
55     case VOL_STATE_VNODE_GET:
56     case VOL_STATE_VNODE_CLOSE:
57     case VOL_STATE_VNODE_RELEASE:
58         return 1;
59     }
60     return 0;
61 }
62
63 /**
64  * tell caller whether V_attachState is an error condition.
65  *
66  * @param state  volume state enumeration
67  *
68  * @return whether volume state is in error state
69  *   @retval 0  state is not an error state
70  *   @retval 1  state is an error state
71  *
72  * @note DEMAND_ATTACH_FS only
73  */
74 static_inline int
75 VIsErrorState(VolState state)
76 {
77     switch (state) {
78     case VOL_STATE_ERROR:
79     case VOL_STATE_SALVAGING:
80         return 1;
81     }
82     return 0;
83 }
84
85 /**
86  * tell caller whether V_attachState is valid.
87  *
88  * @param state  volume state enumeration
89  *
90  * @return whether volume state is a mutually exclusive state
91  *   @retval 0  no, state is not valid
92  *   @retval 1  yes, state is a valid enumeration member
93  *
94  * @note DEMAND_ATTACH_FS only
95  *
96  * @note do we really want to treat VOL_STATE_FREED as valid?
97  */
98 static_inline int
99 VIsValidState(VolState state)
100 {
101     if ((state >= 0) && 
102         (state < VOL_STATE_COUNT)) {
103         return 1;
104     }
105     return 0;
106 }
107
108 /**
109  * increment volume-package internal refcount.
110  *
111  * @param vp  volume object pointer
112  *
113  * @internal volume package internal use only
114  *
115  * @pre VOL_LOCK must be held
116  *
117  * @post volume waiters refcount is incremented
118  *
119  * @see VCancelReservation_r
120  *
121  * @note DEMAND_ATTACH_FS only
122  */
123 static_inline void
124 VCreateReservation_r(Volume * vp)
125 {
126     vp->nWaiters++;
127 }
128
129 /**
130  * wait for the volume to change states.
131  *
132  * @param vp  volume object pointer
133  *
134  * @pre VOL_LOCK held; ref held on volume
135  *
136  * @post VOL_LOCK held; volume state has changed from previous value
137  *
138  * @note DEMAND_ATTACH_FS only
139  */
140 static_inline void
141 VWaitStateChange_r(Volume * vp)
142 {
143     VolState state_save = V_attachState(vp);
144
145     assert(vp->nWaiters || vp->nUsers);
146     do {
147         VOL_CV_WAIT(&V_attachCV(vp));
148     } while (V_attachState(vp) == state_save);
149     assert(V_attachState(vp) != VOL_STATE_FREED);
150 }
151
152 /**
153  * wait for blocking ops to end.
154  *
155  * @pre VOL_LOCK held; ref held on volume
156  *
157  * @post VOL_LOCK held; volume not in exclusive state
158  *
159  * @param vp  volume object pointer
160  *
161  * @note DEMAND_ATTACH_FS only
162  */
163 static_inline void
164 VWaitExclusiveState_r(Volume * vp)
165 {
166     assert(vp->nWaiters || vp->nUsers);
167     while (VIsExclusiveState(V_attachState(vp))) {
168         VOL_CV_WAIT(&V_attachCV(vp));
169     }
170     assert(V_attachState(vp) != VOL_STATE_FREED);
171 }
172
173 /**
174  * change state, and notify other threads,
175  * return previous state to caller.
176  *
177  * @param vp         pointer to volume object
178  * @param new_state  new volume state value
179  * @pre VOL_LOCK held
180  *
181  * @post volume state changed; stats updated
182  *
183  * @return previous volume state
184  *
185  * @note DEMAND_ATTACH_FS only
186  */
187 static_inline VolState
188 VChangeState_r(Volume * vp, VolState new_state)
189 {
190     VolState old_state = V_attachState(vp);
191
192     /* XXX profiling need to make sure these counters
193      * don't kill performance... */
194     VStats.state_levels[old_state]--;
195     VStats.state_levels[new_state]++;
196
197     V_attachState(vp) = new_state;
198     assert(pthread_cond_broadcast(&V_attachCV(vp)) == 0);
199     return old_state;
200 }
201
202 #endif /* AFS_DEMAND_ATTACH_FS */
203
204 #endif /* _AFS_VOL_VOLUME_INLINE_H */