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);
25 ls->drop_locks_count = GDLM_DROP_COUNT;
26 ls->drop_locks_period = GDLM_DROP_PERIOD;
30 spin_lock_init(&ls->async_lock);
31 INIT_LIST_HEAD(&ls->complete);
32 INIT_LIST_HEAD(&ls->blocking);
33 INIT_LIST_HEAD(&ls->delayed);
34 INIT_LIST_HEAD(&ls->submit);
35 INIT_LIST_HEAD(&ls->all_locks);
36 init_waitqueue_head(&ls->thread_wait);
37 init_waitqueue_head(&ls->wait_control);
40 ls->drop_time = jiffies;
43 strncpy(buf, table_name, 256);
48 log_info("invalid table_name \"%s\"", table_name);
55 strncpy(ls->clustername, buf, GDLM_NAME_LEN);
56 strncpy(ls->fsname, p, GDLM_NAME_LEN);
61 static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
64 char *options, *x, *y;
68 strncpy(data, data_arg, 255);
70 for (options = data; (x = strsep(&options, ":")); ) {
78 if (!strcmp(x, "jid")) {
80 log_error("need argument to jid");
84 sscanf(y, "%u", &ls->jid);
86 } else if (!strcmp(x, "first")) {
88 log_error("need argument to first");
92 sscanf(y, "%u", &ls->first);
94 } else if (!strcmp(x, "id")) {
96 log_error("need argument to id");
100 sscanf(y, "%u", &ls->id);
102 } else if (!strcmp(x, "nodir")) {
104 log_error("need argument to nodir");
108 sscanf(y, "%u", nodir);
111 log_error("unkonwn option: %s", x);
120 static int gdlm_mount(char *table_name, char *host_data,
121 lm_callback_t cb, void *cb_data,
122 unsigned int min_lvb_size, int flags,
123 struct lm_lockstruct *lockstruct,
124 struct kobject *fskobj)
127 int error = -ENOMEM, nodir = 0;
129 if (min_lvb_size > GDLM_LVB_SIZE)
132 ls = init_gdlm(cb, cb_data, flags, table_name);
136 error = make_args(ls, host_data, &nodir);
140 error = gdlm_init_threads(ls);
144 error = gdlm_kobject_setup(ls, fskobj);
148 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
150 DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
153 log_error("dlm_new_lockspace error %d", error);
157 lockstruct->ls_jid = ls->jid;
158 lockstruct->ls_first = ls->first;
159 lockstruct->ls_lockspace = ls;
160 lockstruct->ls_ops = &gdlm_ops;
161 lockstruct->ls_flags = 0;
162 lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
166 gdlm_kobject_release(ls);
168 gdlm_release_threads(ls);
175 static void gdlm_unmount(void *lockspace)
177 struct gdlm_ls *ls = lockspace;
180 log_debug("unmount flags %lx", ls->flags);
182 /* FIXME: serialize unmount and withdraw in case they
183 happen at once. Also, if unmount follows withdraw,
184 wait for withdraw to finish. */
186 if (test_bit(DFL_WITHDRAW, &ls->flags))
189 gdlm_kobject_release(ls);
190 dlm_release_lockspace(ls->dlm_lockspace, 2);
191 gdlm_release_threads(ls);
192 rv = gdlm_release_all_locks(ls);
194 log_info("gdlm_unmount: %d stray locks freed", rv);
199 static void gdlm_recovery_done(void *lockspace, unsigned int jid,
200 unsigned int message)
202 struct gdlm_ls *ls = lockspace;
203 ls->recover_jid_done = jid;
204 ls->recover_jid_status = message;
205 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
208 static void gdlm_others_may_mount(void *lockspace)
210 struct gdlm_ls *ls = lockspace;
212 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
215 /* Userspace gets the offline uevent, blocks new gfs locks on
216 other mounters, and lets us know (sets WITHDRAW flag). Then,
217 userspace leaves the mount group while we leave the lockspace. */
219 static void gdlm_withdraw(void *lockspace)
221 struct gdlm_ls *ls = lockspace;
223 kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
225 wait_event_interruptible(ls->wait_control,
226 test_bit(DFL_WITHDRAW, &ls->flags));
228 dlm_release_lockspace(ls->dlm_lockspace, 2);
229 gdlm_release_threads(ls);
230 gdlm_release_all_locks(ls);
231 gdlm_kobject_release(ls);
234 const struct lm_lockops gdlm_ops = {
235 .lm_proto_name = "lock_dlm",
236 .lm_mount = gdlm_mount,
237 .lm_others_may_mount = gdlm_others_may_mount,
238 .lm_unmount = gdlm_unmount,
239 .lm_withdraw = gdlm_withdraw,
240 .lm_get_lock = gdlm_get_lock,
241 .lm_put_lock = gdlm_put_lock,
242 .lm_lock = gdlm_lock,
243 .lm_unlock = gdlm_unlock,
244 .lm_plock = gdlm_plock,
245 .lm_punlock = gdlm_punlock,
246 .lm_plock_get = gdlm_plock_get,
247 .lm_cancel = gdlm_cancel,
248 .lm_hold_lvb = gdlm_hold_lvb,
249 .lm_unhold_lvb = gdlm_unhold_lvb,
250 .lm_recovery_done = gdlm_recovery_done,
251 .lm_owner = THIS_MODULE,