diff options
| -rw-r--r-- | drivers/md/md-cluster.c | 102 | 
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 | |||
| 19 | struct 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 | |||
| 28 | static 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 | |||
| 36 | static 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 | |||
| 50 | static int dlm_unlock_sync(struct dlm_lock_resource *res) | ||
| 51 | { | ||
| 52 | return dlm_lock_sync(res, DLM_LOCK_NL); | ||
| 53 | } | ||
| 54 | |||
| 55 | static 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; | ||
| 95 | out_err: | ||
| 96 | kfree(res->lksb.sb_lvbptr); | ||
| 97 | kfree(res->name); | ||
| 98 | kfree(res); | ||
| 99 | return NULL; | ||
| 100 | } | ||
| 101 | |||
| 102 | static 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 | ||
| 14 | static int __init cluster_init(void) | 116 | static int __init cluster_init(void) | 
| 15 | { | 117 | { | 
