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_LIST_HEAD(&ls->all_locks);
32 init_waitqueue_head(&ls->thread_wait);
33 init_waitqueue_head(&ls->wait_control);
36 strncpy(buf, table_name, 256);
41 log_info("invalid table_name \"%s\"", table_name);
48 strncpy(ls->clustername, buf, GDLM_NAME_LEN);
49 strncpy(ls->fsname, p, GDLM_NAME_LEN);
54 static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
57 char *options, *x, *y;
61 strncpy(data, data_arg, 255);
64 log_error("no mount options, (u)mount helpers not installed");
68 for (options = data; (x = strsep(&options, ":")); ) {
76 if (!strcmp(x, "jid")) {
78 log_error("need argument to jid");
82 sscanf(y, "%u", &ls->jid);
84 } else if (!strcmp(x, "first")) {
86 log_error("need argument to first");
90 sscanf(y, "%u", &ls->first);
92 } else if (!strcmp(x, "id")) {
94 log_error("need argument to id");
98 sscanf(y, "%u", &ls->id);
100 } else if (!strcmp(x, "nodir")) {
102 log_error("need argument to nodir");
106 sscanf(y, "%u", nodir);
109 log_error("unkonwn option: %s", x);
118 static int gdlm_mount(char *table_name, char *host_data,
119 lm_callback_t cb, void *cb_data,
120 unsigned int min_lvb_size, int flags,
121 struct lm_lockstruct *lockstruct,
122 struct kobject *fskobj)
125 int error = -ENOMEM, nodir = 0;
127 if (min_lvb_size > GDLM_LVB_SIZE)
130 ls = init_gdlm(cb, cb_data, flags, table_name);
134 error = make_args(ls, host_data, &nodir);
138 error = gdlm_init_threads(ls);
142 error = gdlm_kobject_setup(ls, fskobj);
146 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
148 DLM_LSFL_FS | (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;
178 log_debug("unmount flags %lx", ls->flags);
180 /* FIXME: serialize unmount and withdraw in case they
181 happen at once. Also, if unmount follows withdraw,
182 wait for withdraw to finish. */
184 if (test_bit(DFL_WITHDRAW, &ls->flags))
187 gdlm_kobject_release(ls);
188 dlm_release_lockspace(ls->dlm_lockspace, 2);
189 gdlm_release_threads(ls);
190 rv = gdlm_release_all_locks(ls);
192 log_info("gdlm_unmount: %d stray locks freed", rv);
197 static void gdlm_recovery_done(void *lockspace, unsigned int jid,
198 unsigned int message)
200 struct gdlm_ls *ls = lockspace;
201 ls->recover_jid_done = jid;
202 ls->recover_jid_status = message;
203 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
206 static void gdlm_others_may_mount(void *lockspace)
208 struct gdlm_ls *ls = lockspace;
210 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
213 /* Userspace gets the offline uevent, blocks new gfs locks on
214 other mounters, and lets us know (sets WITHDRAW flag). Then,
215 userspace leaves the mount group while we leave the lockspace. */
217 static void gdlm_withdraw(void *lockspace)
219 struct gdlm_ls *ls = lockspace;
221 kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
223 wait_event_interruptible(ls->wait_control,
224 test_bit(DFL_WITHDRAW, &ls->flags));
226 dlm_release_lockspace(ls->dlm_lockspace, 2);
227 gdlm_release_threads(ls);
228 gdlm_release_all_locks(ls);
229 gdlm_kobject_release(ls);
232 static int gdlm_plock(void *lockspace, struct lm_lockname *name,
233 struct file *file, int cmd, struct file_lock *fl)
235 struct gdlm_ls *ls = lockspace;
236 return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
239 static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
240 struct file *file, struct file_lock *fl)
242 struct gdlm_ls *ls = lockspace;
243 return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
246 static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
247 struct file *file, struct file_lock *fl)
249 struct gdlm_ls *ls = lockspace;
250 return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
253 const struct lm_lockops gdlm_ops = {
254 .lm_proto_name = "lock_dlm",
255 .lm_mount = gdlm_mount,
256 .lm_others_may_mount = gdlm_others_may_mount,
257 .lm_unmount = gdlm_unmount,
258 .lm_withdraw = gdlm_withdraw,
259 .lm_get_lock = gdlm_get_lock,
260 .lm_put_lock = gdlm_put_lock,
261 .lm_lock = gdlm_lock,
262 .lm_unlock = gdlm_unlock,
263 .lm_plock = gdlm_plock,
264 .lm_punlock = gdlm_punlock,
265 .lm_plock_get = gdlm_plock_get,
266 .lm_cancel = gdlm_cancel,
267 .lm_hold_lvb = gdlm_hold_lvb,
268 .lm_unhold_lvb = gdlm_unhold_lvb,
269 .lm_recovery_done = gdlm_recovery_done,
270 .lm_owner = THIS_MODULE,