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);
72 "DLM/GFS2/GFS ERROR: (u)mount helpers are not installed!\n");
76 for (options = data; (x = strsep(&options, ":")); ) {
84 if (!strcmp(x, "jid")) {
86 log_error("need argument to jid");
90 sscanf(y, "%u", &ls->jid);
92 } else if (!strcmp(x, "first")) {
94 log_error("need argument to first");
98 sscanf(y, "%u", &ls->first);
100 } else if (!strcmp(x, "id")) {
102 log_error("need argument to id");
106 sscanf(y, "%u", &ls->id);
108 } else if (!strcmp(x, "nodir")) {
110 log_error("need argument to nodir");
114 sscanf(y, "%u", nodir);
117 log_error("unkonwn option: %s", x);
126 static int gdlm_mount(char *table_name, char *host_data,
127 lm_callback_t cb, void *cb_data,
128 unsigned int min_lvb_size, int flags,
129 struct lm_lockstruct *lockstruct,
130 struct kobject *fskobj)
133 int error = -ENOMEM, nodir = 0;
135 if (min_lvb_size > GDLM_LVB_SIZE)
138 ls = init_gdlm(cb, cb_data, flags, table_name);
142 error = make_args(ls, host_data, &nodir);
146 error = gdlm_init_threads(ls);
150 error = gdlm_kobject_setup(ls, fskobj);
154 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
156 DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
159 log_error("dlm_new_lockspace error %d", error);
163 lockstruct->ls_jid = ls->jid;
164 lockstruct->ls_first = ls->first;
165 lockstruct->ls_lockspace = ls;
166 lockstruct->ls_ops = &gdlm_ops;
167 lockstruct->ls_flags = 0;
168 lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
172 gdlm_kobject_release(ls);
174 gdlm_release_threads(ls);
181 static void gdlm_unmount(void *lockspace)
183 struct gdlm_ls *ls = lockspace;
186 log_debug("unmount flags %lx", ls->flags);
188 /* FIXME: serialize unmount and withdraw in case they
189 happen at once. Also, if unmount follows withdraw,
190 wait for withdraw to finish. */
192 if (test_bit(DFL_WITHDRAW, &ls->flags))
195 gdlm_kobject_release(ls);
196 dlm_release_lockspace(ls->dlm_lockspace, 2);
197 gdlm_release_threads(ls);
198 rv = gdlm_release_all_locks(ls);
200 log_info("gdlm_unmount: %d stray locks freed", rv);
205 static void gdlm_recovery_done(void *lockspace, unsigned int jid,
206 unsigned int message)
208 struct gdlm_ls *ls = lockspace;
209 ls->recover_jid_done = jid;
210 ls->recover_jid_status = message;
211 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
214 static void gdlm_others_may_mount(void *lockspace)
216 struct gdlm_ls *ls = lockspace;
218 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
221 /* Userspace gets the offline uevent, blocks new gfs locks on
222 other mounters, and lets us know (sets WITHDRAW flag). Then,
223 userspace leaves the mount group while we leave the lockspace. */
225 static void gdlm_withdraw(void *lockspace)
227 struct gdlm_ls *ls = lockspace;
229 kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
231 wait_event_interruptible(ls->wait_control,
232 test_bit(DFL_WITHDRAW, &ls->flags));
234 dlm_release_lockspace(ls->dlm_lockspace, 2);
235 gdlm_release_threads(ls);
236 gdlm_release_all_locks(ls);
237 gdlm_kobject_release(ls);
240 const struct lm_lockops gdlm_ops = {
241 .lm_proto_name = "lock_dlm",
242 .lm_mount = gdlm_mount,
243 .lm_others_may_mount = gdlm_others_may_mount,
244 .lm_unmount = gdlm_unmount,
245 .lm_withdraw = gdlm_withdraw,
246 .lm_get_lock = gdlm_get_lock,
247 .lm_put_lock = gdlm_put_lock,
248 .lm_lock = gdlm_lock,
249 .lm_unlock = gdlm_unlock,
250 .lm_plock = gdlm_plock,
251 .lm_punlock = gdlm_punlock,
252 .lm_plock_get = gdlm_plock_get,
253 .lm_cancel = gdlm_cancel,
254 .lm_hold_lvb = gdlm_hold_lvb,
255 .lm_unhold_lvb = gdlm_unhold_lvb,
256 .lm_recovery_done = gdlm_recovery_done,
257 .lm_owner = THIS_MODULE,