diff options
Diffstat (limited to 'fs/ocfs2/stackglue.c')
-rw-r--r-- | fs/ocfs2/stackglue.c | 142 |
1 files changed, 135 insertions, 7 deletions
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index 99538043fc17..0aec2fcf2175 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * General Public License for more details. | 18 | * General Public License for more details. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "cluster/masklog.h" | ||
21 | #include "stackglue.h" | 22 | #include "stackglue.h" |
22 | 23 | ||
23 | static struct ocfs2_locking_protocol *lproto; | 24 | static struct ocfs2_locking_protocol *lproto; |
@@ -77,7 +78,126 @@ static int flags_to_o2dlm(u32 flags) | |||
77 | } | 78 | } |
78 | #undef map_flag | 79 | #undef map_flag |
79 | 80 | ||
80 | enum dlm_status ocfs2_dlm_lock(struct dlm_ctxt *dlm, | 81 | /* |
82 | * Map an o2dlm status to standard errno values. | ||
83 | * | ||
84 | * o2dlm only uses a handful of these, and returns even fewer to the | ||
85 | * caller. Still, we try to assign sane values to each error. | ||
86 | * | ||
87 | * The following value pairs have special meanings to dlmglue, thus | ||
88 | * the right hand side needs to stay unique - never duplicate the | ||
89 | * mapping elsewhere in the table! | ||
90 | * | ||
91 | * DLM_NORMAL: 0 | ||
92 | * DLM_NOTQUEUED: -EAGAIN | ||
93 | * DLM_CANCELGRANT: -DLM_ECANCEL | ||
94 | * DLM_CANCEL: -DLM_EUNLOCK | ||
95 | */ | ||
96 | /* Keep in sync with dlmapi.h */ | ||
97 | static int status_map[] = { | ||
98 | [DLM_NORMAL] = 0, /* Success */ | ||
99 | [DLM_GRANTED] = -EINVAL, | ||
100 | [DLM_DENIED] = -EACCES, | ||
101 | [DLM_DENIED_NOLOCKS] = -EACCES, | ||
102 | [DLM_WORKING] = -EBUSY, | ||
103 | [DLM_BLOCKED] = -EINVAL, | ||
104 | [DLM_BLOCKED_ORPHAN] = -EINVAL, | ||
105 | [DLM_DENIED_GRACE_PERIOD] = -EACCES, | ||
106 | [DLM_SYSERR] = -ENOMEM, /* It is what it is */ | ||
107 | [DLM_NOSUPPORT] = -EPROTO, | ||
108 | [DLM_CANCELGRANT] = -DLM_ECANCEL, /* Cancel after grant */ | ||
109 | [DLM_IVLOCKID] = -EINVAL, | ||
110 | [DLM_SYNC] = -EINVAL, | ||
111 | [DLM_BADTYPE] = -EINVAL, | ||
112 | [DLM_BADRESOURCE] = -EINVAL, | ||
113 | [DLM_MAXHANDLES] = -ENOMEM, | ||
114 | [DLM_NOCLINFO] = -EINVAL, | ||
115 | [DLM_NOLOCKMGR] = -EINVAL, | ||
116 | [DLM_NOPURGED] = -EINVAL, | ||
117 | [DLM_BADARGS] = -EINVAL, | ||
118 | [DLM_VOID] = -EINVAL, | ||
119 | [DLM_NOTQUEUED] = -EAGAIN, /* Trylock failed */ | ||
120 | [DLM_IVBUFLEN] = -EINVAL, | ||
121 | [DLM_CVTUNGRANT] = -EPERM, | ||
122 | [DLM_BADPARAM] = -EINVAL, | ||
123 | [DLM_VALNOTVALID] = -EINVAL, | ||
124 | [DLM_REJECTED] = -EPERM, | ||
125 | [DLM_ABORT] = -EINVAL, | ||
126 | [DLM_CANCEL] = -DLM_EUNLOCK, /* Successful cancel */ | ||
127 | [DLM_IVRESHANDLE] = -EINVAL, | ||
128 | [DLM_DEADLOCK] = -EDEADLK, | ||
129 | [DLM_DENIED_NOASTS] = -EINVAL, | ||
130 | [DLM_FORWARD] = -EINVAL, | ||
131 | [DLM_TIMEOUT] = -ETIMEDOUT, | ||
132 | [DLM_IVGROUPID] = -EINVAL, | ||
133 | [DLM_VERS_CONFLICT] = -EOPNOTSUPP, | ||
134 | [DLM_BAD_DEVICE_PATH] = -ENOENT, | ||
135 | [DLM_NO_DEVICE_PERMISSION] = -EPERM, | ||
136 | [DLM_NO_CONTROL_DEVICE] = -ENOENT, | ||
137 | [DLM_RECOVERING] = -ENOTCONN, | ||
138 | [DLM_MIGRATING] = -ERESTART, | ||
139 | [DLM_MAXSTATS] = -EINVAL, | ||
140 | }; | ||
141 | static int dlm_status_to_errno(enum dlm_status status) | ||
142 | { | ||
143 | BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0]))); | ||
144 | |||
145 | return status_map[status]; | ||
146 | } | ||
147 | |||
148 | static void o2dlm_lock_ast_wrapper(void *astarg) | ||
149 | { | ||
150 | BUG_ON(lproto == NULL); | ||
151 | |||
152 | lproto->lp_lock_ast(astarg); | ||
153 | } | ||
154 | |||
155 | static void o2dlm_blocking_ast_wrapper(void *astarg, int level) | ||
156 | { | ||
157 | BUG_ON(lproto == NULL); | ||
158 | |||
159 | lproto->lp_blocking_ast(astarg, level); | ||
160 | } | ||
161 | |||
162 | static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) | ||
163 | { | ||
164 | int error; | ||
165 | |||
166 | BUG_ON(lproto == NULL); | ||
167 | |||
168 | /* | ||
169 | * XXX: CANCEL values are sketchy. | ||
170 | * | ||
171 | * Currently we have preserved the o2dlm paradigm. You can get | ||
172 | * unlock_ast() whether the cancel succeded or not. | ||
173 | * | ||
174 | * First, we're going to pass DLM_EUNLOCK just like fs/dlm does for | ||
175 | * successful unlocks. That is a clean behavior. | ||
176 | * | ||
177 | * In o2dlm, you can get both the lock_ast() for the lock being | ||
178 | * granted and the unlock_ast() for the CANCEL failing. A | ||
179 | * successful cancel sends DLM_NORMAL here. If the | ||
180 | * lock grant happened before the cancel arrived, you get | ||
181 | * DLM_CANCELGRANT. For now, we'll use DLM_ECANCEL to signify | ||
182 | * CANCELGRANT - the CANCEL was supposed to happen but didn't. We | ||
183 | * can then use DLM_EUNLOCK to signify a successful CANCEL - | ||
184 | * effectively, the CANCEL caused the lock to roll back. | ||
185 | * | ||
186 | * In the future, we will likely move the o2dlm to send only one | ||
187 | * ast - either unlock_ast() for a successful CANCEL or lock_ast() | ||
188 | * when the grant succeeds. At that point, we'll send DLM_ECANCEL | ||
189 | * for all cancel results (CANCELGRANT will no longer exist). | ||
190 | */ | ||
191 | error = dlm_status_to_errno(status); | ||
192 | |||
193 | /* Successful unlock is DLM_EUNLOCK */ | ||
194 | if (!error) | ||
195 | error = -DLM_EUNLOCK; | ||
196 | |||
197 | lproto->lp_unlock_ast(astarg, error); | ||
198 | } | ||
199 | |||
200 | int ocfs2_dlm_lock(struct dlm_ctxt *dlm, | ||
81 | int mode, | 201 | int mode, |
82 | struct dlm_lockstatus *lksb, | 202 | struct dlm_lockstatus *lksb, |
83 | u32 flags, | 203 | u32 flags, |
@@ -85,27 +205,35 @@ enum dlm_status ocfs2_dlm_lock(struct dlm_ctxt *dlm, | |||
85 | unsigned int namelen, | 205 | unsigned int namelen, |
86 | void *astarg) | 206 | void *astarg) |
87 | { | 207 | { |
208 | enum dlm_status status; | ||
88 | int o2dlm_mode = mode_to_o2dlm(mode); | 209 | int o2dlm_mode = mode_to_o2dlm(mode); |
89 | int o2dlm_flags = flags_to_o2dlm(flags); | 210 | int o2dlm_flags = flags_to_o2dlm(flags); |
211 | int ret; | ||
90 | 212 | ||
91 | BUG_ON(lproto == NULL); | 213 | BUG_ON(lproto == NULL); |
92 | 214 | ||
93 | return dlmlock(dlm, o2dlm_mode, lksb, o2dlm_flags, name, namelen, | 215 | status = dlmlock(dlm, o2dlm_mode, lksb, o2dlm_flags, name, namelen, |
94 | lproto->lp_lock_ast, astarg, | 216 | o2dlm_lock_ast_wrapper, astarg, |
95 | lproto->lp_blocking_ast); | 217 | o2dlm_blocking_ast_wrapper); |
218 | ret = dlm_status_to_errno(status); | ||
219 | return ret; | ||
96 | } | 220 | } |
97 | 221 | ||
98 | enum dlm_status ocfs2_dlm_unlock(struct dlm_ctxt *dlm, | 222 | int ocfs2_dlm_unlock(struct dlm_ctxt *dlm, |
99 | struct dlm_lockstatus *lksb, | 223 | struct dlm_lockstatus *lksb, |
100 | u32 flags, | 224 | u32 flags, |
101 | void *astarg) | 225 | void *astarg) |
102 | { | 226 | { |
227 | enum dlm_status status; | ||
103 | int o2dlm_flags = flags_to_o2dlm(flags); | 228 | int o2dlm_flags = flags_to_o2dlm(flags); |
229 | int ret; | ||
104 | 230 | ||
105 | BUG_ON(lproto == NULL); | 231 | BUG_ON(lproto == NULL); |
106 | 232 | ||
107 | return dlmunlock(dlm, lksb, o2dlm_flags, | 233 | status = dlmunlock(dlm, lksb, o2dlm_flags, |
108 | lproto->lp_unlock_ast, astarg); | 234 | o2dlm_unlock_ast_wrapper, astarg); |
235 | ret = dlm_status_to_errno(status); | ||
236 | return ret; | ||
109 | } | 237 | } |
110 | 238 | ||
111 | 239 | ||