aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md-cluster.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index f377e71949c5..bc8ea9d76875 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -10,6 +10,108 @@
10 10
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#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}
13 115
14static int __init cluster_init(void) 116static int __init cluster_init(void)
15{ 117{