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