2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License version 2.
12 const struct lm_lockops gdlm_ops;
15 static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp,
16 int flags, char *table_name)
21 ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
28 spin_lock_init(&ls->async_lock);
29 INIT_LIST_HEAD(&ls->delayed);
30 INIT_LIST_HEAD(&ls->submit);
31 init_waitqueue_head(&ls->thread_wait);
32 init_waitqueue_head(&ls->wait_control);
35 strncpy(buf, table_name, 256);
40 log_info("invalid table_name \"%s\"", table_name);
47 strncpy(ls->clustername, buf, GDLM_NAME_LEN);
48 strncpy(ls->fsname, p, GDLM_NAME_LEN);
53 static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
56 char *options, *x, *y;
60 strncpy(data, data_arg, 255);
63 log_error("no mount options, (u)mount helpers not installed");
67 for (options = data; (x = strsep(&options, ":")); ) {
75 if (!strcmp(x, "jid")) {
77 log_error("need argument to jid");
81 sscanf(y, "%u", &ls->jid);
83 } else if (!strcmp(x, "first")) {
85 log_error("need argument to first");
89 sscanf(y, "%u", &ls->first);
91 } else if (!strcmp(x, "id")) {
93 log_error("need argument to id");
97 sscanf(y, "%u", &ls->id);
99 } else if (!strcmp(x, "nodir")) {
101 log_error("need argument to nodir");
105 sscanf(y, "%u", nodir);
108 log_error("unkonwn option: %s", x);
117 static int gdlm_mount(char *table_name, char *host_data,
118 lm_callback_t cb, void *cb_data,
119 unsigned int min_lvb_size, int flags,
120 struct lm_lockstruct *lockstruct,
121 struct kobject *fskobj)
124 int error = -ENOMEM, nodir = 0;
126 if (min_lvb_size > GDLM_LVB_SIZE)
129 ls = init_gdlm(cb, cb_data, flags, table_name);
133 error = make_args(ls, host_data, &nodir);
137 error = gdlm_init_threads(ls);
141 error = gdlm_kobject_setup(ls, fskobj);
145 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
147 DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
148 (nodir ? DLM_LSFL_NODIR : 0),
151 log_error("dlm_new_lockspace error %d", error);
155 lockstruct->ls_jid = ls->jid;
156 lockstruct->ls_first = ls->first;
157 lockstruct->ls_lockspace = ls;
158 lockstruct->ls_ops = &gdlm_ops;
159 lockstruct->ls_flags = 0;
160 lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
164 gdlm_kobject_release(ls);
166 gdlm_release_threads(ls);
173 static void gdlm_unmount(void *lockspace)
175 struct gdlm_ls *ls = lockspace;
177 log_debug("unmount flags %lx", ls->flags);
179 /* FIXME: serialize unmount and withdraw in case they
180 happen at once. Also, if unmount follows withdraw,
181 wait for withdraw to finish. */
183 if (test_bit(DFL_WITHDRAW, &ls->flags))
186 gdlm_kobject_release(ls);
187 dlm_release_lockspace(ls->dlm_lockspace, 2);
188 gdlm_release_threads(ls);
189 BUG_ON(ls->all_locks_count);
194 static void gdlm_recovery_done(void *lockspace, unsigned int jid,
195 unsigned int message)
197 struct gdlm_ls *ls = lockspace;
198 ls->recover_jid_done = jid;
199 ls->recover_jid_status = message;
200 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
203 static void gdlm_others_may_mount(void *lockspace)
205 struct gdlm_ls *ls = lockspace;
207 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
210 /* Userspace gets the offline uevent, blocks new gfs locks on
211 other mounters, and lets us know (sets WITHDRAW flag). Then,
212 userspace leaves the mount group while we leave the lockspace. */
214 static void gdlm_withdraw(void *lockspace)
216 struct gdlm_ls *ls = lockspace;
218 kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
220 wait_event_interruptible(ls->wait_control,
221 test_bit(DFL_WITHDRAW, &ls->flags));
223 dlm_release_lockspace(ls->dlm_lockspace, 2);
224 gdlm_release_threads(ls);
225 gdlm_kobject_release(ls);
228 static int gdlm_plock(void *lockspace, struct lm_lockname *name,
229 struct file *file, int cmd, struct file_lock *fl)
231 struct gdlm_ls *ls = lockspace;
232 return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
235 static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
236 struct file *file, struct file_lock *fl)
238 struct gdlm_ls *ls = lockspace;
239 return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
242 static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
243 struct file *file, struct file_lock *fl)
245 struct gdlm_ls *ls = lockspace;
246 return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
249 const struct lm_lockops gdlm_ops = {
250 .lm_proto_name = "lock_dlm",
251 .lm_mount = gdlm_mount,
252 .lm_others_may_mount = gdlm_others_may_mount,
253 .lm_unmount = gdlm_unmount,
254 .lm_withdraw = gdlm_withdraw,
255 .lm_get_lock = gdlm_get_lock,
256 .lm_put_lock = gdlm_put_lock,
257 .lm_lock = gdlm_lock,
258 .lm_unlock = gdlm_unlock,
259 .lm_plock = gdlm_plock,
260 .lm_punlock = gdlm_punlock,
261 .lm_plock_get = gdlm_plock_get,
262 .lm_cancel = gdlm_cancel,
263 .lm_hold_lvb = gdlm_hold_lvb,
264 .lm_unhold_lvb = gdlm_unhold_lvb,
265 .lm_recovery_done = gdlm_recovery_done,
266 .lm_owner = THIS_MODULE,