Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / fs / gfs2 / locking / dlm / mount.c
blobf2efff424224dd3e0052284076e679d067e48ad8
1 /*
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.
8 */
10 #include "lock_dlm.h"
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)
18 struct gdlm_ls *ls;
19 char buf[256], *p;
21 ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
22 if (!ls)
23 return NULL;
25 ls->drop_locks_count = GDLM_DROP_COUNT;
26 ls->drop_locks_period = GDLM_DROP_PERIOD;
27 ls->fscb = cb;
28 ls->sdp = sdp;
29 ls->fsflags = flags;
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);
38 ls->thread1 = NULL;
39 ls->thread2 = NULL;
40 ls->drop_time = jiffies;
41 ls->jid = -1;
43 strncpy(buf, table_name, 256);
44 buf[255] = '\0';
46 p = strchr(buf, ':');
47 if (!p) {
48 log_info("invalid table_name \"%s\"", table_name);
49 kfree(ls);
50 return NULL;
52 *p = '\0';
53 p++;
55 strncpy(ls->clustername, buf, GDLM_NAME_LEN);
56 strncpy(ls->fsname, p, GDLM_NAME_LEN);
58 return ls;
61 static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
63 char data[256];
64 char *options, *x, *y;
65 int error = 0;
67 memset(data, 0, 256);
68 strncpy(data, data_arg, 255);
70 if (!strlen(data)) {
71 log_error("no mount options, (u)mount helpers not installed");
72 return -EINVAL;
75 for (options = data; (x = strsep(&options, ":")); ) {
76 if (!*x)
77 continue;
79 y = strchr(x, '=');
80 if (y)
81 *y++ = 0;
83 if (!strcmp(x, "jid")) {
84 if (!y) {
85 log_error("need argument to jid");
86 error = -EINVAL;
87 break;
89 sscanf(y, "%u", &ls->jid);
91 } else if (!strcmp(x, "first")) {
92 if (!y) {
93 log_error("need argument to first");
94 error = -EINVAL;
95 break;
97 sscanf(y, "%u", &ls->first);
99 } else if (!strcmp(x, "id")) {
100 if (!y) {
101 log_error("need argument to id");
102 error = -EINVAL;
103 break;
105 sscanf(y, "%u", &ls->id);
107 } else if (!strcmp(x, "nodir")) {
108 if (!y) {
109 log_error("need argument to nodir");
110 error = -EINVAL;
111 break;
113 sscanf(y, "%u", nodir);
115 } else {
116 log_error("unkonwn option: %s", x);
117 error = -EINVAL;
118 break;
122 return error;
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)
131 struct gdlm_ls *ls;
132 int error = -ENOMEM, nodir = 0;
134 if (min_lvb_size > GDLM_LVB_SIZE)
135 goto out;
137 ls = init_gdlm(cb, cb_data, flags, table_name);
138 if (!ls)
139 goto out;
141 error = make_args(ls, host_data, &nodir);
142 if (error)
143 goto out;
145 error = gdlm_init_threads(ls);
146 if (error)
147 goto out_free;
149 error = gdlm_kobject_setup(ls, fskobj);
150 if (error)
151 goto out_thread;
153 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
154 &ls->dlm_lockspace,
155 DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
156 GDLM_LVB_SIZE);
157 if (error) {
158 log_error("dlm_new_lockspace error %d", error);
159 goto out_kobj;
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;
168 return 0;
170 out_kobj:
171 gdlm_kobject_release(ls);
172 out_thread:
173 gdlm_release_threads(ls);
174 out_free:
175 kfree(ls);
176 out:
177 return error;
180 static void gdlm_unmount(void *lockspace)
182 struct gdlm_ls *ls = lockspace;
183 int rv;
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))
192 goto out;
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);
198 if (rv)
199 log_info("gdlm_unmount: %d stray locks freed", rv);
200 out:
201 kfree(ls);
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;
216 ls->first_done = 1;
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 const struct lm_lockops gdlm_ops = {
240 .lm_proto_name = "lock_dlm",
241 .lm_mount = gdlm_mount,
242 .lm_others_may_mount = gdlm_others_may_mount,
243 .lm_unmount = gdlm_unmount,
244 .lm_withdraw = gdlm_withdraw,
245 .lm_get_lock = gdlm_get_lock,
246 .lm_put_lock = gdlm_put_lock,
247 .lm_lock = gdlm_lock,
248 .lm_unlock = gdlm_unlock,
249 .lm_plock = gdlm_plock,
250 .lm_punlock = gdlm_punlock,
251 .lm_plock_get = gdlm_plock_get,
252 .lm_cancel = gdlm_cancel,
253 .lm_hold_lvb = gdlm_hold_lvb,
254 .lm_unhold_lvb = gdlm_unhold_lvb,
255 .lm_recovery_done = gdlm_recovery_done,
256 .lm_owner = THIS_MODULE,