blob: bc8ea9d768754bf1f029c62ee58f8257e16150af [file] [log] [blame]
Goldwyn Rodrigues8e854e92014-03-07 11:21:15 -06001/*
2 * Copyright (C) 2015, SUSE
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 */
10
11
12#include <linux/module.h>
Goldwyn Rodrigues47741b72014-03-07 13:49:26 -060013#include <linux/dlm.h>
14#include <linux/sched.h>
15#include "md.h"
16
17#define LVB_SIZE 64
18
19struct dlm_lock_resource {
20 dlm_lockspace_t *ls;
21 struct dlm_lksb lksb;
22 char *name; /* lock name. */
23 uint32_t flags; /* flags to pass to dlm_lock() */
24 void (*bast)(void *arg, int mode); /* blocking AST function pointer*/
25 struct completion completion; /* completion for synchronized locking */
26};
27
28static void sync_ast(void *arg)
29{
30 struct dlm_lock_resource *res;
31
32 res = (struct dlm_lock_resource *) arg;
33 complete(&res->completion);
34}
35
36static int dlm_lock_sync(struct dlm_lock_resource *res, int mode)
37{
38 int ret = 0;
39
40 init_completion(&res->completion);
41 ret = dlm_lock(res->ls, mode, &res->lksb,
42 res->flags, res->name, strlen(res->name),
43 0, sync_ast, res, res->bast);
44 if (ret)
45 return ret;
46 wait_for_completion(&res->completion);
47 return res->lksb.sb_status;
48}
49
50static int dlm_unlock_sync(struct dlm_lock_resource *res)
51{
52 return dlm_lock_sync(res, DLM_LOCK_NL);
53}
54
55static struct dlm_lock_resource *lockres_init(dlm_lockspace_t *lockspace,
56 char *name, void (*bastfn)(void *arg, int mode), int with_lvb)
57{
58 struct dlm_lock_resource *res = NULL;
59 int ret, namelen;
60
61 res = kzalloc(sizeof(struct dlm_lock_resource), GFP_KERNEL);
62 if (!res)
63 return NULL;
64 res->ls = lockspace;
65 namelen = strlen(name);
66 res->name = kzalloc(namelen + 1, GFP_KERNEL);
67 if (!res->name) {
68 pr_err("md-cluster: Unable to allocate resource name for resource %s\n", name);
69 goto out_err;
70 }
71 strlcpy(res->name, name, namelen + 1);
72 if (with_lvb) {
73 res->lksb.sb_lvbptr = kzalloc(LVB_SIZE, GFP_KERNEL);
74 if (!res->lksb.sb_lvbptr) {
75 pr_err("md-cluster: Unable to allocate LVB for resource %s\n", name);
76 goto out_err;
77 }
78 res->flags = DLM_LKF_VALBLK;
79 }
80
81 if (bastfn)
82 res->bast = bastfn;
83
84 res->flags |= DLM_LKF_EXPEDITE;
85
86 ret = dlm_lock_sync(res, DLM_LOCK_NL);
87 if (ret) {
88 pr_err("md-cluster: Unable to lock NL on new lock resource %s\n", name);
89 goto out_err;
90 }
91 res->flags &= ~DLM_LKF_EXPEDITE;
92 res->flags |= DLM_LKF_CONVERT;
93
94 return res;
95out_err:
96 kfree(res->lksb.sb_lvbptr);
97 kfree(res->name);
98 kfree(res);
99 return NULL;
100}
101
102static void lockres_free(struct dlm_lock_resource *res)
103{
104 if (!res)
105 return;
106
107 init_completion(&res->completion);
108 dlm_unlock(res->ls, res->lksb.sb_lkid, 0, &res->lksb, res);
109 wait_for_completion(&res->completion);
110
111 kfree(res->name);
112 kfree(res->lksb.sb_lvbptr);
113 kfree(res);
114}
Goldwyn Rodrigues8e854e92014-03-07 11:21:15 -0600115
116static int __init cluster_init(void)
117{
118 pr_warn("md-cluster: EXPERIMENTAL. Use with caution\n");
119 pr_info("Registering Cluster MD functions\n");
120 return 0;
121}
122
123static void cluster_exit(void)
124{
125}
126
127module_init(cluster_init);
128module_exit(cluster_exit);
129MODULE_LICENSE("GPL");
130MODULE_DESCRIPTION("Clustering support for MD");