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