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