diff options
Diffstat (limited to 'fs/gfs2/locking/dlm/mount.c')
-rw-r--r-- | fs/gfs2/locking/dlm/mount.c | 189 |
1 files changed, 98 insertions, 91 deletions
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c index 92b1789deb89..bfb224638f2d 100644 --- a/fs/gfs2/locking/dlm/mount.c +++ b/fs/gfs2/locking/dlm/mount.c | |||
@@ -1,15 +1,11 @@ | |||
1 | /****************************************************************************** | 1 | /* |
2 | ******************************************************************************* | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | ** | 3 | * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | * |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | ** | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | * of the GNU General Public License v.2. |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | */ |
9 | ** of the GNU General Public License v.2. | ||
10 | ** | ||
11 | ******************************************************************************* | ||
12 | ******************************************************************************/ | ||
13 | 9 | ||
14 | #include "lock_dlm.h" | 10 | #include "lock_dlm.h" |
15 | 11 | ||
@@ -24,27 +20,21 @@ static struct gdlm_ls *init_gdlm(lm_callback_t cb, lm_fsdata_t *fsdata, | |||
24 | struct gdlm_ls *ls; | 20 | struct gdlm_ls *ls; |
25 | char buf[256], *p; | 21 | char buf[256], *p; |
26 | 22 | ||
27 | ls = kmalloc(sizeof(struct gdlm_ls), GFP_KERNEL); | 23 | ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL); |
28 | if (!ls) | 24 | if (!ls) |
29 | return NULL; | 25 | return NULL; |
30 | 26 | ||
31 | memset(ls, 0, sizeof(struct gdlm_ls)); | ||
32 | |||
33 | ls->drop_locks_count = gdlm_drop_count; | 27 | ls->drop_locks_count = gdlm_drop_count; |
34 | ls->drop_locks_period = gdlm_drop_period; | 28 | ls->drop_locks_period = gdlm_drop_period; |
35 | |||
36 | ls->fscb = cb; | 29 | ls->fscb = cb; |
37 | ls->fsdata = fsdata; | 30 | ls->fsdata = fsdata; |
38 | ls->fsflags = flags; | 31 | ls->fsflags = flags; |
39 | |||
40 | spin_lock_init(&ls->async_lock); | 32 | spin_lock_init(&ls->async_lock); |
41 | |||
42 | INIT_LIST_HEAD(&ls->complete); | 33 | INIT_LIST_HEAD(&ls->complete); |
43 | INIT_LIST_HEAD(&ls->blocking); | 34 | INIT_LIST_HEAD(&ls->blocking); |
44 | INIT_LIST_HEAD(&ls->delayed); | 35 | INIT_LIST_HEAD(&ls->delayed); |
45 | INIT_LIST_HEAD(&ls->submit); | 36 | INIT_LIST_HEAD(&ls->submit); |
46 | INIT_LIST_HEAD(&ls->all_locks); | 37 | INIT_LIST_HEAD(&ls->all_locks); |
47 | |||
48 | init_waitqueue_head(&ls->thread_wait); | 38 | init_waitqueue_head(&ls->thread_wait); |
49 | init_waitqueue_head(&ls->wait_control); | 39 | init_waitqueue_head(&ls->wait_control); |
50 | ls->thread1 = NULL; | 40 | ls->thread1 = NULL; |
@@ -57,23 +47,75 @@ static struct gdlm_ls *init_gdlm(lm_callback_t cb, lm_fsdata_t *fsdata, | |||
57 | 47 | ||
58 | p = strstr(buf, ":"); | 48 | p = strstr(buf, ":"); |
59 | if (!p) { | 49 | if (!p) { |
60 | printk("lock_dlm: invalid table_name \"%s\"\n", table_name); | 50 | log_info("invalid table_name \"%s\"", table_name); |
61 | kfree(ls); | 51 | kfree(ls); |
62 | return NULL; | 52 | return NULL; |
63 | } | 53 | } |
64 | *p = '\0'; | 54 | *p = '\0'; |
65 | p++; | 55 | p++; |
66 | 56 | ||
67 | strncpy(ls->clustername, buf, 128); | 57 | strncpy(ls->clustername, buf, GDLM_NAME_LEN); |
68 | strncpy(ls->fsname, p, 128); | 58 | strncpy(ls->fsname, p, GDLM_NAME_LEN); |
69 | 59 | ||
70 | return ls; | 60 | return ls; |
71 | } | 61 | } |
72 | 62 | ||
63 | static int make_args(struct gdlm_ls *ls, char *data_arg) | ||
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 { | ||
105 | log_error("unkonwn option: %s", x); | ||
106 | error = -EINVAL; | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | return error; | ||
112 | } | ||
113 | |||
73 | static int gdlm_mount(char *table_name, char *host_data, | 114 | static int gdlm_mount(char *table_name, char *host_data, |
74 | lm_callback_t cb, lm_fsdata_t *fsdata, | 115 | lm_callback_t cb, lm_fsdata_t *fsdata, |
75 | unsigned int min_lvb_size, int flags, | 116 | unsigned int min_lvb_size, int flags, |
76 | struct lm_lockstruct *lockstruct) | 117 | struct lm_lockstruct *lockstruct, |
118 | struct kobject *fskobj) | ||
77 | { | 119 | { |
78 | struct gdlm_ls *ls; | 120 | struct gdlm_ls *ls; |
79 | int error = -ENOMEM; | 121 | int error = -ENOMEM; |
@@ -92,30 +134,18 @@ static int gdlm_mount(char *table_name, char *host_data, | |||
92 | error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), | 134 | error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), |
93 | &ls->dlm_lockspace, 0, GDLM_LVB_SIZE); | 135 | &ls->dlm_lockspace, 0, GDLM_LVB_SIZE); |
94 | if (error) { | 136 | if (error) { |
95 | printk("lock_dlm: dlm_new_lockspace error %d\n", error); | 137 | log_error("dlm_new_lockspace error %d", error); |
96 | goto out_thread; | 138 | goto out_thread; |
97 | } | 139 | } |
98 | 140 | ||
99 | error = gdlm_kobject_setup(ls); | 141 | error = gdlm_kobject_setup(ls, fskobj); |
100 | if (error) | 142 | if (error) |
101 | goto out_dlm; | 143 | goto out_dlm; |
102 | kobject_uevent(&ls->kobj, KOBJ_MOUNT, NULL); | ||
103 | 144 | ||
104 | /* Now we depend on userspace to notice the new mount, | 145 | error = make_args(ls, host_data); |
105 | join the appropriate group, and do a write to our sysfs | ||
106 | "mounted" or "terminate" file. Before the start, userspace | ||
107 | must set "jid" and "first". */ | ||
108 | |||
109 | error = wait_event_interruptible(ls->wait_control, | ||
110 | test_bit(DFL_JOIN_DONE, &ls->flags)); | ||
111 | if (error) | 146 | if (error) |
112 | goto out_sysfs; | 147 | goto out_sysfs; |
113 | 148 | ||
114 | if (test_bit(DFL_TERMINATE, &ls->flags)) { | ||
115 | error = -ERESTARTSYS; | ||
116 | goto out_sysfs; | ||
117 | } | ||
118 | |||
119 | lockstruct->ls_jid = ls->jid; | 149 | lockstruct->ls_jid = ls->jid; |
120 | lockstruct->ls_first = ls->first; | 150 | lockstruct->ls_first = ls->first; |
121 | lockstruct->ls_lockspace = ls; | 151 | lockstruct->ls_lockspace = ls; |
@@ -143,22 +173,19 @@ static void gdlm_unmount(lm_lockspace_t *lockspace) | |||
143 | 173 | ||
144 | log_debug("unmount flags %lx", ls->flags); | 174 | log_debug("unmount flags %lx", ls->flags); |
145 | 175 | ||
146 | if (test_bit(DFL_WITHDRAW, &ls->flags)) { | 176 | /* FIXME: serialize unmount and withdraw in case they |
147 | gdlm_kobject_release(ls); | 177 | happen at once. Also, if unmount follows withdraw, |
148 | goto out; | 178 | wait for withdraw to finish. */ |
149 | } | ||
150 | |||
151 | kobject_uevent(&ls->kobj, KOBJ_UMOUNT, NULL); | ||
152 | 179 | ||
153 | wait_event_interruptible(ls->wait_control, | 180 | if (test_bit(DFL_WITHDRAW, &ls->flags)) |
154 | test_bit(DFL_LEAVE_DONE, &ls->flags)); | 181 | goto out; |
155 | 182 | ||
156 | gdlm_kobject_release(ls); | 183 | gdlm_kobject_release(ls); |
157 | dlm_release_lockspace(ls->dlm_lockspace, 2); | 184 | dlm_release_lockspace(ls->dlm_lockspace, 2); |
158 | gdlm_release_threads(ls); | 185 | gdlm_release_threads(ls); |
159 | rv = gdlm_release_all_locks(ls); | 186 | rv = gdlm_release_all_locks(ls); |
160 | if (rv) | 187 | if (rv) |
161 | log_all("lm_dlm_unmount: %d stray locks freed", rv); | 188 | log_info("gdlm_unmount: %d stray locks freed", rv); |
162 | out: | 189 | out: |
163 | kfree(ls); | 190 | kfree(ls); |
164 | } | 191 | } |
@@ -167,7 +194,7 @@ static void gdlm_recovery_done(lm_lockspace_t *lockspace, unsigned int jid, | |||
167 | unsigned int message) | 194 | unsigned int message) |
168 | { | 195 | { |
169 | struct gdlm_ls *ls = (struct gdlm_ls *) lockspace; | 196 | struct gdlm_ls *ls = (struct gdlm_ls *) lockspace; |
170 | ls->recover_done = jid; | 197 | ls->recover_jid_done = jid; |
171 | kobject_uevent(&ls->kobj, KOBJ_CHANGE, NULL); | 198 | kobject_uevent(&ls->kobj, KOBJ_CHANGE, NULL); |
172 | } | 199 | } |
173 | 200 | ||
@@ -178,12 +205,14 @@ static void gdlm_others_may_mount(lm_lockspace_t *lockspace) | |||
178 | kobject_uevent(&ls->kobj, KOBJ_CHANGE, NULL); | 205 | kobject_uevent(&ls->kobj, KOBJ_CHANGE, NULL); |
179 | } | 206 | } |
180 | 207 | ||
208 | /* Userspace gets the offline uevent, blocks new gfs locks on | ||
209 | other mounters, and lets us know (sets WITHDRAW flag). Then, | ||
210 | userspace leaves the mount group while we leave the lockspace. */ | ||
211 | |||
181 | static void gdlm_withdraw(lm_lockspace_t *lockspace) | 212 | static void gdlm_withdraw(lm_lockspace_t *lockspace) |
182 | { | 213 | { |
183 | struct gdlm_ls *ls = (struct gdlm_ls *) lockspace; | 214 | struct gdlm_ls *ls = (struct gdlm_ls *) lockspace; |
184 | 215 | ||
185 | /* userspace suspends locking on all other members */ | ||
186 | |||
187 | kobject_uevent(&ls->kobj, KOBJ_OFFLINE, NULL); | 216 | kobject_uevent(&ls->kobj, KOBJ_OFFLINE, NULL); |
188 | 217 | ||
189 | wait_event_interruptible(ls->wait_control, | 218 | wait_event_interruptible(ls->wait_control, |
@@ -192,49 +221,27 @@ static void gdlm_withdraw(lm_lockspace_t *lockspace) | |||
192 | dlm_release_lockspace(ls->dlm_lockspace, 2); | 221 | dlm_release_lockspace(ls->dlm_lockspace, 2); |
193 | gdlm_release_threads(ls); | 222 | gdlm_release_threads(ls); |
194 | gdlm_release_all_locks(ls); | 223 | gdlm_release_all_locks(ls); |
195 | 224 | gdlm_kobject_release(ls); | |
196 | kobject_uevent(&ls->kobj, KOBJ_UMOUNT, NULL); | ||
197 | |||
198 | /* userspace leaves the mount group, we don't need to wait for | ||
199 | that to complete */ | ||
200 | } | ||
201 | |||
202 | int gdlm_plock_get(lm_lockspace_t *lockspace, struct lm_lockname *name, | ||
203 | struct file *file, struct file_lock *fl) | ||
204 | { | ||
205 | return -ENOSYS; | ||
206 | } | ||
207 | |||
208 | int gdlm_punlock(lm_lockspace_t *lockspace, struct lm_lockname *name, | ||
209 | struct file *file, struct file_lock *fl) | ||
210 | { | ||
211 | return -ENOSYS; | ||
212 | } | ||
213 | |||
214 | int gdlm_plock(lm_lockspace_t *lockspace, struct lm_lockname *name, | ||
215 | struct file *file, int cmd, struct file_lock *fl) | ||
216 | { | ||
217 | return -ENOSYS; | ||
218 | } | 225 | } |
219 | 226 | ||
220 | struct lm_lockops gdlm_ops = { | 227 | struct lm_lockops gdlm_ops = { |
221 | lm_proto_name:"lock_dlm", | 228 | .lm_proto_name = "lock_dlm", |
222 | lm_mount:gdlm_mount, | 229 | .lm_mount = gdlm_mount, |
223 | lm_others_may_mount:gdlm_others_may_mount, | 230 | .lm_others_may_mount = gdlm_others_may_mount, |
224 | lm_unmount:gdlm_unmount, | 231 | .lm_unmount = gdlm_unmount, |
225 | lm_withdraw:gdlm_withdraw, | 232 | .lm_withdraw = gdlm_withdraw, |
226 | lm_get_lock:gdlm_get_lock, | 233 | .lm_get_lock = gdlm_get_lock, |
227 | lm_put_lock:gdlm_put_lock, | 234 | .lm_put_lock = gdlm_put_lock, |
228 | lm_lock:gdlm_lock, | 235 | .lm_lock = gdlm_lock, |
229 | lm_unlock:gdlm_unlock, | 236 | .lm_unlock = gdlm_unlock, |
230 | lm_plock:gdlm_plock, | 237 | .lm_plock = gdlm_plock, |
231 | lm_punlock:gdlm_punlock, | 238 | .lm_punlock = gdlm_punlock, |
232 | lm_plock_get:gdlm_plock_get, | 239 | .lm_plock_get = gdlm_plock_get, |
233 | lm_cancel:gdlm_cancel, | 240 | .lm_cancel = gdlm_cancel, |
234 | lm_hold_lvb:gdlm_hold_lvb, | 241 | .lm_hold_lvb = gdlm_hold_lvb, |
235 | lm_unhold_lvb:gdlm_unhold_lvb, | 242 | .lm_unhold_lvb = gdlm_unhold_lvb, |
236 | lm_sync_lvb:gdlm_sync_lvb, | 243 | .lm_sync_lvb = gdlm_sync_lvb, |
237 | lm_recovery_done:gdlm_recovery_done, | 244 | .lm_recovery_done = gdlm_recovery_done, |
238 | lm_owner:THIS_MODULE, | 245 | .lm_owner = THIS_MODULE, |
239 | }; | 246 | }; |
240 | 247 | ||