diff options
Diffstat (limited to 'fs/ocfs2/stackglue.c')
-rw-r--r-- | fs/ocfs2/stackglue.c | 131 |
1 files changed, 125 insertions, 6 deletions
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index eb88854cb976..f6f309a08344 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
@@ -18,11 +18,21 @@ | |||
18 | * General Public License for more details. | 18 | * General Public License for more details. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/crc32.h> | ||
23 | |||
24 | /* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ | ||
25 | #include <linux/fs.h> | ||
26 | |||
21 | #include "cluster/masklog.h" | 27 | #include "cluster/masklog.h" |
22 | #include "stackglue.h" | 28 | #include "stackglue.h" |
23 | 29 | ||
24 | static struct ocfs2_locking_protocol *lproto; | 30 | static struct ocfs2_locking_protocol *lproto; |
25 | 31 | ||
32 | struct o2dlm_private { | ||
33 | struct dlm_eviction_cb op_eviction_cb; | ||
34 | }; | ||
35 | |||
26 | /* These should be identical */ | 36 | /* These should be identical */ |
27 | #if (DLM_LOCK_IV != LKM_IVMODE) | 37 | #if (DLM_LOCK_IV != LKM_IVMODE) |
28 | # error Lock modes do not match | 38 | # error Lock modes do not match |
@@ -197,7 +207,7 @@ static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) | |||
197 | lproto->lp_unlock_ast(astarg, error); | 207 | lproto->lp_unlock_ast(astarg, error); |
198 | } | 208 | } |
199 | 209 | ||
200 | int ocfs2_dlm_lock(struct dlm_ctxt *dlm, | 210 | int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, |
201 | int mode, | 211 | int mode, |
202 | union ocfs2_dlm_lksb *lksb, | 212 | union ocfs2_dlm_lksb *lksb, |
203 | u32 flags, | 213 | u32 flags, |
@@ -212,15 +222,15 @@ int ocfs2_dlm_lock(struct dlm_ctxt *dlm, | |||
212 | 222 | ||
213 | BUG_ON(lproto == NULL); | 223 | BUG_ON(lproto == NULL); |
214 | 224 | ||
215 | status = dlmlock(dlm, o2dlm_mode, &lksb->lksb_o2dlm, o2dlm_flags, | 225 | status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm, |
216 | name, namelen, | 226 | o2dlm_flags, name, namelen, |
217 | o2dlm_lock_ast_wrapper, astarg, | 227 | o2dlm_lock_ast_wrapper, astarg, |
218 | o2dlm_blocking_ast_wrapper); | 228 | o2dlm_blocking_ast_wrapper); |
219 | ret = dlm_status_to_errno(status); | 229 | ret = dlm_status_to_errno(status); |
220 | return ret; | 230 | return ret; |
221 | } | 231 | } |
222 | 232 | ||
223 | int ocfs2_dlm_unlock(struct dlm_ctxt *dlm, | 233 | int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, |
224 | union ocfs2_dlm_lksb *lksb, | 234 | union ocfs2_dlm_lksb *lksb, |
225 | u32 flags, | 235 | u32 flags, |
226 | void *astarg) | 236 | void *astarg) |
@@ -231,8 +241,8 @@ int ocfs2_dlm_unlock(struct dlm_ctxt *dlm, | |||
231 | 241 | ||
232 | BUG_ON(lproto == NULL); | 242 | BUG_ON(lproto == NULL); |
233 | 243 | ||
234 | status = dlmunlock(dlm, &lksb->lksb_o2dlm, o2dlm_flags, | 244 | status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm, |
235 | o2dlm_unlock_ast_wrapper, astarg); | 245 | o2dlm_flags, o2dlm_unlock_ast_wrapper, astarg); |
236 | ret = dlm_status_to_errno(status); | 246 | ret = dlm_status_to_errno(status); |
237 | return ret; | 247 | return ret; |
238 | } | 248 | } |
@@ -252,6 +262,115 @@ void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb) | |||
252 | return (void *)(lksb->lksb_o2dlm.lvb); | 262 | return (void *)(lksb->lksb_o2dlm.lvb); |
253 | } | 263 | } |
254 | 264 | ||
265 | /* | ||
266 | * Called from the dlm when it's about to evict a node. This is how the | ||
267 | * classic stack signals node death. | ||
268 | */ | ||
269 | static void o2dlm_eviction_cb(int node_num, void *data) | ||
270 | { | ||
271 | struct ocfs2_cluster_connection *conn = data; | ||
272 | |||
273 | mlog(ML_NOTICE, "o2dlm has evicted node %d from group %.*s\n", | ||
274 | node_num, conn->cc_namelen, conn->cc_name); | ||
275 | |||
276 | conn->cc_recovery_handler(node_num, conn->cc_recovery_data); | ||
277 | } | ||
278 | |||
279 | int ocfs2_cluster_connect(const char *group, | ||
280 | int grouplen, | ||
281 | void (*recovery_handler)(int node_num, | ||
282 | void *recovery_data), | ||
283 | void *recovery_data, | ||
284 | struct ocfs2_cluster_connection **conn) | ||
285 | { | ||
286 | int rc = 0; | ||
287 | struct ocfs2_cluster_connection *new_conn; | ||
288 | u32 dlm_key; | ||
289 | struct dlm_ctxt *dlm; | ||
290 | struct o2dlm_private *priv; | ||
291 | struct dlm_protocol_version dlm_version; | ||
292 | |||
293 | BUG_ON(group == NULL); | ||
294 | BUG_ON(conn == NULL); | ||
295 | BUG_ON(recovery_handler == NULL); | ||
296 | |||
297 | if (grouplen > GROUP_NAME_MAX) { | ||
298 | rc = -EINVAL; | ||
299 | goto out; | ||
300 | } | ||
301 | |||
302 | new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection), | ||
303 | GFP_KERNEL); | ||
304 | if (!new_conn) { | ||
305 | rc = -ENOMEM; | ||
306 | goto out; | ||
307 | } | ||
308 | |||
309 | memcpy(new_conn->cc_name, group, grouplen); | ||
310 | new_conn->cc_namelen = grouplen; | ||
311 | new_conn->cc_recovery_handler = recovery_handler; | ||
312 | new_conn->cc_recovery_data = recovery_data; | ||
313 | |||
314 | /* Start the new connection at our maximum compatibility level */ | ||
315 | new_conn->cc_version = lproto->lp_max_version; | ||
316 | |||
317 | priv = kzalloc(sizeof(struct o2dlm_private), GFP_KERNEL); | ||
318 | if (!priv) { | ||
319 | rc = -ENOMEM; | ||
320 | goto out_free; | ||
321 | } | ||
322 | |||
323 | /* This just fills the structure in. It is safe to use new_conn. */ | ||
324 | dlm_setup_eviction_cb(&priv->op_eviction_cb, o2dlm_eviction_cb, | ||
325 | new_conn); | ||
326 | |||
327 | new_conn->cc_private = priv; | ||
328 | |||
329 | /* used by the dlm code to make message headers unique, each | ||
330 | * node in this domain must agree on this. */ | ||
331 | dlm_key = crc32_le(0, group, grouplen); | ||
332 | dlm_version.pv_major = new_conn->cc_version.pv_major; | ||
333 | dlm_version.pv_minor = new_conn->cc_version.pv_minor; | ||
334 | |||
335 | dlm = dlm_register_domain(group, dlm_key, &dlm_version); | ||
336 | if (IS_ERR(dlm)) { | ||
337 | rc = PTR_ERR(dlm); | ||
338 | mlog_errno(rc); | ||
339 | goto out_free; | ||
340 | } | ||
341 | |||
342 | new_conn->cc_version.pv_major = dlm_version.pv_major; | ||
343 | new_conn->cc_version.pv_minor = dlm_version.pv_minor; | ||
344 | new_conn->cc_lockspace = dlm; | ||
345 | |||
346 | dlm_register_eviction_cb(dlm, &priv->op_eviction_cb); | ||
347 | |||
348 | *conn = new_conn; | ||
349 | |||
350 | out_free: | ||
351 | if (rc) { | ||
352 | kfree(new_conn->cc_private); | ||
353 | kfree(new_conn); | ||
354 | } | ||
355 | |||
356 | out: | ||
357 | return rc; | ||
358 | } | ||
359 | |||
360 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn) | ||
361 | { | ||
362 | struct dlm_ctxt *dlm = conn->cc_lockspace; | ||
363 | struct o2dlm_private *priv = conn->cc_private; | ||
364 | |||
365 | dlm_unregister_eviction_cb(&priv->op_eviction_cb); | ||
366 | dlm_unregister_domain(dlm); | ||
367 | |||
368 | kfree(priv); | ||
369 | kfree(conn); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
255 | void o2cb_get_stack(struct ocfs2_locking_protocol *proto) | 374 | void o2cb_get_stack(struct ocfs2_locking_protocol *proto) |
256 | { | 375 | { |
257 | BUG_ON(proto == NULL); | 376 | BUG_ON(proto == NULL); |