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.
14 struct lm_lockops gdlm_ops;
17 static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp,
18 int flags, char *table_name)
23 ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
27 ls->drop_locks_count = gdlm_drop_count;
28 ls->drop_locks_period = gdlm_drop_period;
32 spin_lock_init(&ls->async_lock);
33 INIT_LIST_HEAD(&ls->complete);
34 INIT_LIST_HEAD(&ls->blocking);
35 INIT_LIST_HEAD(&ls->delayed);
36 INIT_LIST_HEAD(&ls->submit);
37 INIT_LIST_HEAD(&ls->all_locks);
38 init_waitqueue_head(&ls->thread_wait);
39 init_waitqueue_head(&ls->wait_control);
42 ls->drop_time = jiffies;
45 strncpy(buf, table_name, 256);
50 log_info("invalid table_name \"%s\"", table_name);
57 strncpy(ls->clustername, buf, GDLM_NAME_LEN);
58 strncpy(ls->fsname, p, GDLM_NAME_LEN);
63 static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
66 char *options, *x, *y;
70 strncpy(data, data_arg, 255);
72 for (options = data; (x = strsep(&options, ":")); ) {
80 if (!strcmp(x, "jid")) {
82 log_error("need argument to jid");
86 sscanf(y, "%u", &ls->jid);
88 } else if (!strcmp(x, "first")) {
90 log_error("need argument to first");
94 sscanf(y, "%u", &ls->first);
96 } else if (!strcmp(x, "id")) {
98 log_error("need argument to id");
102 sscanf(y, "%u", &ls->id);
104 } else if (!strcmp(x, "nodir")) {
106 log_error("need argument to nodir");
110 sscanf(y, "%u", nodir);
113 log_error("unkonwn option: %s", x);
122 static int gdlm_mount(char *table_name, char *host_data,
123 lm_callback_t cb, struct gfs2_sbd *sdp,
124 unsigned int min_lvb_size, int flags,
125 struct lm_lockstruct *lockstruct,
126 struct kobject *fskobj)
129 int error = -ENOMEM, nodir = 0;
131 if (min_lvb_size > GDLM_LVB_SIZE)
134 ls = init_gdlm(cb, sdp, flags, table_name);
138 error = make_args(ls, host_data, &nodir);
142 error = gdlm_init_threads(ls);
146 error = gdlm_kobject_setup(ls, fskobj);
150 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
152 nodir ? DLM_LSFL_NODIR : 0,
155 log_error("dlm_new_lockspace error %d", error);
159 lockstruct->ls_jid = ls->jid;
160 lockstruct->ls_first = ls->first;
161 lockstruct->ls_lockspace = ls;
162 lockstruct->ls_ops = &gdlm_ops;
163 lockstruct->ls_flags = 0;
164 lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
168 gdlm_kobject_release(ls);
170 gdlm_release_threads(ls);
177 static void gdlm_unmount(lm_lockspace_t *lockspace)
179 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
182 log_debug("unmount flags %lx", ls->flags);
184 /* FIXME: serialize unmount and withdraw in case they
185 happen at once. Also, if unmount follows withdraw,
186 wait for withdraw to finish. */
188 if (test_bit(DFL_WITHDRAW, &ls->flags))
191 gdlm_kobject_release(ls);
192 dlm_release_lockspace(ls->dlm_lockspace, 2);
193 gdlm_release_threads(ls);
194 rv = gdlm_release_all_locks(ls);
196 log_info("gdlm_unmount: %d stray locks freed", rv);
201 static void gdlm_recovery_done(lm_lockspace_t *lockspace, unsigned int jid,
202 unsigned int message)
204 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
205 ls->recover_jid_done = jid;
206 ls->recover_jid_status = message;
207 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
210 static void gdlm_others_may_mount(lm_lockspace_t *lockspace)
212 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
214 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
217 /* Userspace gets the offline uevent, blocks new gfs locks on
218 other mounters, and lets us know (sets WITHDRAW flag). Then,
219 userspace leaves the mount group while we leave the lockspace. */
221 static void gdlm_withdraw(lm_lockspace_t *lockspace)
223 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
225 kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
227 wait_event_interruptible(ls->wait_control,
228 test_bit(DFL_WITHDRAW, &ls->flags));
230 dlm_release_lockspace(ls->dlm_lockspace, 2);
231 gdlm_release_threads(ls);
232 gdlm_release_all_locks(ls);
233 gdlm_kobject_release(ls);
236 struct lm_lockops gdlm_ops = {
237 .lm_proto_name = "lock_dlm",
238 .lm_mount = gdlm_mount,
239 .lm_others_may_mount = gdlm_others_may_mount,
240 .lm_unmount = gdlm_unmount,
241 .lm_withdraw = gdlm_withdraw,
242 .lm_get_lock = gdlm_get_lock,
243 .lm_put_lock = gdlm_put_lock,
244 .lm_lock = gdlm_lock,
245 .lm_unlock = gdlm_unlock,
246 .lm_plock = gdlm_plock,
247 .lm_punlock = gdlm_punlock,
248 .lm_plock_get = gdlm_plock_get,
249 .lm_cancel = gdlm_cancel,
250 .lm_hold_lvb = gdlm_hold_lvb,
251 .lm_unhold_lvb = gdlm_unhold_lvb,
252 .lm_sync_lvb = gdlm_sync_lvb,
253 .lm_recovery_done = gdlm_recovery_done,
254 .lm_owner = THIS_MODULE,