diff options
Diffstat (limited to 'fs/gfs2/locking/dlm/mount.c')
-rw-r--r-- | fs/gfs2/locking/dlm/mount.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c new file mode 100644 index 000000000000..1f94dd35a943 --- /dev/null +++ b/fs/gfs2/locking/dlm/mount.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
3 | * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | ||
4 | * | ||
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 | */ | ||
9 | |||
10 | #include "lock_dlm.h" | ||
11 | |||
12 | int gdlm_drop_count; | ||
13 | int gdlm_drop_period; | ||
14 | const struct lm_lockops gdlm_ops; | ||
15 | |||
16 | |||
17 | static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp, | ||
18 | int flags, char *table_name) | ||
19 | { | ||
20 | struct gdlm_ls *ls; | ||
21 | char buf[256], *p; | ||
22 | |||
23 | ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL); | ||
24 | if (!ls) | ||
25 | return NULL; | ||
26 | |||
27 | ls->drop_locks_count = gdlm_drop_count; | ||
28 | ls->drop_locks_period = gdlm_drop_period; | ||
29 | ls->fscb = cb; | ||
30 | ls->sdp = sdp; | ||
31 | ls->fsflags = flags; | ||
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); | ||
40 | ls->thread1 = NULL; | ||
41 | ls->thread2 = NULL; | ||
42 | ls->drop_time = jiffies; | ||
43 | ls->jid = -1; | ||
44 | |||
45 | strncpy(buf, table_name, 256); | ||
46 | buf[255] = '\0'; | ||
47 | |||
48 | p = strstr(buf, ":"); | ||
49 | if (!p) { | ||
50 | log_info("invalid table_name \"%s\"", table_name); | ||
51 | kfree(ls); | ||
52 | return NULL; | ||
53 | } | ||
54 | *p = '\0'; | ||
55 | p++; | ||
56 | |||
57 | strncpy(ls->clustername, buf, GDLM_NAME_LEN); | ||
58 | strncpy(ls->fsname, p, GDLM_NAME_LEN); | ||
59 | |||
60 | return ls; | ||
61 | } | ||
62 | |||
63 | static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir) | ||
64 | { | ||
65 | char data[256]; | ||
66 | char *options, *x, *y; | ||
67 | int error = 0; | ||
68 | |||
69 | memset(data, 0, 256); | ||
70 | strncpy(data, data_arg, 255); | ||
71 | |||
72 | for (options = data; (x = strsep(&options, ":")); ) { | ||
73 | if (!*x) | ||
74 | continue; | ||
75 | |||
76 | y = strchr(x, '='); | ||
77 | if (y) | ||
78 | *y++ = 0; | ||
79 | |||
80 | if (!strcmp(x, "jid")) { | ||
81 | if (!y) { | ||
82 | log_error("need argument to jid"); | ||
83 | error = -EINVAL; | ||
84 | break; | ||
85 | } | ||
86 | sscanf(y, "%u", &ls->jid); | ||
87 | |||
88 | } else if (!strcmp(x, "first")) { | ||
89 | if (!y) { | ||
90 | log_error("need argument to first"); | ||
91 | error = -EINVAL; | ||
92 | break; | ||
93 | } | ||
94 | sscanf(y, "%u", &ls->first); | ||
95 | |||
96 | } else if (!strcmp(x, "id")) { | ||
97 | if (!y) { | ||
98 | log_error("need argument to id"); | ||
99 | error = -EINVAL; | ||
100 | break; | ||
101 | } | ||
102 | sscanf(y, "%u", &ls->id); | ||
103 | |||
104 | } else if (!strcmp(x, "nodir")) { | ||
105 | if (!y) { | ||
106 | log_error("need argument to nodir"); | ||
107 | error = -EINVAL; | ||
108 | break; | ||
109 | } | ||
110 | sscanf(y, "%u", nodir); | ||
111 | |||
112 | } else { | ||
113 | log_error("unkonwn option: %s", x); | ||
114 | error = -EINVAL; | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return error; | ||
120 | } | ||
121 | |||
122 | static int gdlm_mount(char *table_name, char *host_data, | ||
123 | lm_callback_t cb, void *cb_data, | ||
124 | unsigned int min_lvb_size, int flags, | ||
125 | struct lm_lockstruct *lockstruct, | ||
126 | struct kobject *fskobj) | ||
127 | { | ||
128 | struct gdlm_ls *ls; | ||
129 | int error = -ENOMEM, nodir = 0; | ||
130 | |||
131 | if (min_lvb_size > GDLM_LVB_SIZE) | ||
132 | goto out; | ||
133 | |||
134 | ls = init_gdlm(cb, cb_data, flags, table_name); | ||
135 | if (!ls) | ||
136 | goto out; | ||
137 | |||
138 | error = make_args(ls, host_data, &nodir); | ||
139 | if (error) | ||
140 | goto out; | ||
141 | |||
142 | error = gdlm_init_threads(ls); | ||
143 | if (error) | ||
144 | goto out_free; | ||
145 | |||
146 | error = gdlm_kobject_setup(ls, fskobj); | ||
147 | if (error) | ||
148 | goto out_thread; | ||
149 | |||
150 | error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), | ||
151 | &ls->dlm_lockspace, | ||
152 | nodir ? DLM_LSFL_NODIR : 0, | ||
153 | GDLM_LVB_SIZE); | ||
154 | if (error) { | ||
155 | log_error("dlm_new_lockspace error %d", error); | ||
156 | goto out_kobj; | ||
157 | } | ||
158 | |||
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; | ||
165 | return 0; | ||
166 | |||
167 | out_kobj: | ||
168 | gdlm_kobject_release(ls); | ||
169 | out_thread: | ||
170 | gdlm_release_threads(ls); | ||
171 | out_free: | ||
172 | kfree(ls); | ||
173 | out: | ||
174 | return error; | ||
175 | } | ||
176 | |||
177 | static void gdlm_unmount(void *lockspace) | ||
178 | { | ||
179 | struct gdlm_ls *ls = lockspace; | ||
180 | int rv; | ||
181 | |||
182 | log_debug("unmount flags %lx", ls->flags); | ||
183 | |||
184 | /* FIXME: serialize unmount and withdraw in case they | ||
185 | happen at once. Also, if unmount follows withdraw, | ||
186 | wait for withdraw to finish. */ | ||
187 | |||
188 | if (test_bit(DFL_WITHDRAW, &ls->flags)) | ||
189 | goto out; | ||
190 | |||
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); | ||
195 | if (rv) | ||
196 | log_info("gdlm_unmount: %d stray locks freed", rv); | ||
197 | out: | ||
198 | kfree(ls); | ||
199 | } | ||
200 | |||
201 | static void gdlm_recovery_done(void *lockspace, unsigned int jid, | ||
202 | unsigned int message) | ||
203 | { | ||
204 | struct gdlm_ls *ls = lockspace; | ||
205 | ls->recover_jid_done = jid; | ||
206 | ls->recover_jid_status = message; | ||
207 | kobject_uevent(&ls->kobj, KOBJ_CHANGE); | ||
208 | } | ||
209 | |||
210 | static void gdlm_others_may_mount(void *lockspace) | ||
211 | { | ||
212 | struct gdlm_ls *ls = lockspace; | ||
213 | ls->first_done = 1; | ||
214 | kobject_uevent(&ls->kobj, KOBJ_CHANGE); | ||
215 | } | ||
216 | |||
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. */ | ||
220 | |||
221 | static void gdlm_withdraw(void *lockspace) | ||
222 | { | ||
223 | struct gdlm_ls *ls = lockspace; | ||
224 | |||
225 | kobject_uevent(&ls->kobj, KOBJ_OFFLINE); | ||
226 | |||
227 | wait_event_interruptible(ls->wait_control, | ||
228 | test_bit(DFL_WITHDRAW, &ls->flags)); | ||
229 | |||
230 | dlm_release_lockspace(ls->dlm_lockspace, 2); | ||
231 | gdlm_release_threads(ls); | ||
232 | gdlm_release_all_locks(ls); | ||
233 | gdlm_kobject_release(ls); | ||
234 | } | ||
235 | |||
236 | const 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_recovery_done = gdlm_recovery_done, | ||
253 | .lm_owner = THIS_MODULE, | ||
254 | }; | ||
255 | |||