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);
71 log_error("no mount options, (u)mount helpers not installed");
75 for (options = data; (x = strsep(&options, ":")); ) {
83 if (!strcmp(x, "jid")) {
85 log_error("need argument to jid");
89 sscanf(y, "%u", &ls->jid);
91 } else if (!strcmp(x, "first")) {
93 log_error("need argument to first");
97 sscanf(y, "%u", &ls->first);
99 } else if (!strcmp(x, "id")) {
101 log_error("need argument to id");
105 sscanf(y, "%u", &ls->id);
107 } else if (!strcmp(x, "nodir")) {
109 log_error("need argument to nodir");
113 sscanf(y, "%u", nodir);
116 log_error("unkonwn option: %s", x);
125 static int gdlm_mount(char *table_name, char *host_data,
126 lm_callback_t cb, void *cb_data,
127 unsigned int min_lvb_size, int flags,
128 struct lm_lockstruct *lockstruct,
129 struct kobject *fskobj)
132 int error = -ENOMEM, nodir = 0;
134 if (min_lvb_size > GDLM_LVB_SIZE)
137 ls = init_gdlm(cb, cb_data, flags, table_name);
141 error = make_args(ls, host_data, &nodir);
145 error = gdlm_init_threads(ls);
149 error = gdlm_kobject_setup(ls, fskobj);
153 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
155 DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
158 log_error("dlm_new_lockspace error %d", error);
162 lockstruct->ls_jid = ls->jid;
163 lockstruct->ls_first = ls->first;
164 lockstruct->ls_lockspace = ls;
165 lockstruct->ls_ops = &gdlm_ops;
166 lockstruct->ls_flags = 0;
167 lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
171 gdlm_kobject_release(ls);
173 gdlm_release_threads(ls);
180 static void gdlm_unmount(void *lockspace)
182 struct gdlm_ls *ls = lockspace;
185 log_debug("unmount flags %lx", ls->flags);
187 /* FIXME: serialize unmount and withdraw in case they
188 happen at once. Also, if unmount follows withdraw,
189 wait for withdraw to finish. */
191 if (test_bit(DFL_WITHDRAW, &ls->flags))
194 gdlm_kobject_release(ls);
195 dlm_release_lockspace(ls->dlm_lockspace, 2);
196 gdlm_release_threads(ls);
197 rv = gdlm_release_all_locks(ls);
199 log_info("gdlm_unmount: %d stray locks freed", rv);
204 static void gdlm_recovery_done(void *lockspace, unsigned int jid,
205 unsigned int message)
207 struct gdlm_ls *ls = lockspace;
208 ls->recover_jid_done = jid;
209 ls->recover_jid_status = message;
210 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
213 static void gdlm_others_may_mount(void *lockspace)
215 struct gdlm_ls *ls = lockspace;
217 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
220 /* Userspace gets the offline uevent, blocks new gfs locks on
221 other mounters, and lets us know (sets WITHDRAW flag). Then,
222 userspace leaves the mount group while we leave the lockspace. */
224 static void gdlm_withdraw(void *lockspace)
226 struct gdlm_ls *ls = lockspace;
228 kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
230 wait_event_interruptible(ls->wait_control,
231 test_bit(DFL_WITHDRAW, &ls->flags));
233 dlm_release_lockspace(ls->dlm_lockspace, 2);
234 gdlm_release_threads(ls);
235 gdlm_release_all_locks(ls);
236 gdlm_kobject_release(ls);
239 static int gdlm_plock(void *lockspace, struct lm_lockname *name,
240 struct file *file, int cmd, struct file_lock *fl)
242 struct gdlm_ls *ls = lockspace;
243 return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
246 static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
247 struct file *file, struct file_lock *fl)
249 struct gdlm_ls *ls = lockspace;
250 return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
253 static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
254 struct file *file, struct file_lock *fl)
256 struct gdlm_ls *ls = lockspace;
257 return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
260 const struct lm_lockops gdlm_ops = {
261 .lm_proto_name = "lock_dlm",
262 .lm_mount = gdlm_mount,
263 .lm_others_may_mount = gdlm_others_may_mount,
264 .lm_unmount = gdlm_unmount,
265 .lm_withdraw = gdlm_withdraw,
266 .lm_get_lock = gdlm_get_lock,
267 .lm_put_lock = gdlm_put_lock,
268 .lm_lock = gdlm_lock,
269 .lm_unlock = gdlm_unlock,
270 .lm_plock = gdlm_plock,
271 .lm_punlock = gdlm_punlock,
272 .lm_plock_get = gdlm_plock_get,
273 .lm_cancel = gdlm_cancel,
274 .lm_hold_lvb = gdlm_hold_lvb,
275 .lm_unhold_lvb = gdlm_unhold_lvb,
276 .lm_recovery_done = gdlm_recovery_done,
277 .lm_owner = THIS_MODULE,