aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/stackglue.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/stackglue.c')
-rw-r--r--fs/ocfs2/stackglue.c131
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
24static struct ocfs2_locking_protocol *lproto; 30static struct ocfs2_locking_protocol *lproto;
25 31
32struct 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
200int ocfs2_dlm_lock(struct dlm_ctxt *dlm, 210int 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
223int ocfs2_dlm_unlock(struct dlm_ctxt *dlm, 233int 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 */
269static 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
279int 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
350out_free:
351 if (rc) {
352 kfree(new_conn->cc_private);
353 kfree(new_conn);
354 }
355
356out:
357 return rc;
358}
359
360int 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
255void o2cb_get_stack(struct ocfs2_locking_protocol *proto) 374void o2cb_get_stack(struct ocfs2_locking_protocol *proto)
256{ 375{
257 BUG_ON(proto == NULL); 376 BUG_ON(proto == NULL);