]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.fixes/dlm-allow-multiple-lockspaces.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / dlm-allow-multiple-lockspaces.patch
1 From: David Teigland <teigland@redhat.com>
2 Subject: [PATCH] dlm: allow multiple lockspace creates
3 Patch-mainline: 2.6.28?
4 References: FATE110294
5
6 Add a count for lockspace create and release so that create can
7 be called multiple times to use the lockspace from different places.
8 Also add the new flag DLM_LSFL_NEWEXCL to create a lockspace with
9 the previous behavior of returning -EEXIST if the lockspace already
10 exists.
11
12 Signed-off-by: David Teigland <teigland@redhat.com>
13 Acked-by: Mark Fasheh <mfasheh@suse.com>
14 ---
15 fs/dlm/dlm_internal.h | 6 ++-
16 fs/dlm/lockspace.c | 107 ++++++++++++++++++++++++++++---------------
17 fs/dlm/user.c | 54 +++++++++++++--------
18 fs/dlm/user.h | 3 +-
19 fs/gfs2/locking/dlm/mount.c | 3 +-
20 include/linux/dlm.h | 5 ++-
21 include/linux/dlm_device.h | 2 +-
22 7 files changed, 116 insertions(+), 64 deletions(-)
23
24 diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
25 index 5a7ac33..9e0622a 100644
26 --- a/fs/dlm/dlm_internal.h
27 +++ b/fs/dlm/dlm_internal.h
28 @@ -2,7 +2,7 @@
29 *******************************************************************************
30 **
31 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
32 -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
33 +** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
34 **
35 ** This copyrighted material is made available to anyone wishing to use,
36 ** modify, copy, or redistribute it subject to the terms and conditions
37 @@ -441,7 +441,9 @@ struct dlm_ls {
38 uint32_t ls_global_id; /* global unique lockspace ID */
39 uint32_t ls_exflags;
40 int ls_lvblen;
41 - int ls_count; /* reference count */
42 + int ls_count; /* refcount of processes in
43 + the dlm using this ls */
44 + int ls_create_count; /* create/release refcount */
45 unsigned long ls_flags; /* LSFL_ */
46 struct kobject ls_kobj;
47
48 diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
49 index 499e167..56eae4e 100644
50 --- a/fs/dlm/lockspace.c
51 +++ b/fs/dlm/lockspace.c
52 @@ -2,7 +2,7 @@
53 *******************************************************************************
54 **
55 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
56 -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
57 +** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
58 **
59 ** This copyrighted material is made available to anyone wishing to use,
60 ** modify, copy, or redistribute it subject to the terms and conditions
61 @@ -23,6 +23,7 @@
62 #include "lock.h"
63 #include "recover.h"
64 #include "requestqueue.h"
65 +#include "user.h"
66
67 static int ls_count;
68 static struct mutex ls_lock;
69 @@ -246,23 +247,6 @@ static void dlm_scand_stop(void)
70 kthread_stop(scand_task);
71 }
72
73 -static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
74 -{
75 - struct dlm_ls *ls;
76 -
77 - spin_lock(&lslist_lock);
78 -
79 - list_for_each_entry(ls, &lslist, ls_list) {
80 - if (ls->ls_namelen == namelen &&
81 - memcmp(ls->ls_name, name, namelen) == 0)
82 - goto out;
83 - }
84 - ls = NULL;
85 - out:
86 - spin_unlock(&lslist_lock);
87 - return ls;
88 -}
89 -
90 struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
91 {
92 struct dlm_ls *ls;
93 @@ -327,6 +311,7 @@ static void remove_lockspace(struct dlm_ls *ls)
94 for (;;) {
95 spin_lock(&lslist_lock);
96 if (ls->ls_count == 0) {
97 + WARN_ON(ls->ls_create_count != 0);
98 list_del(&ls->ls_list);
99 spin_unlock(&lslist_lock);
100 return;
101 @@ -381,7 +366,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
102 uint32_t flags, int lvblen)
103 {
104 struct dlm_ls *ls;
105 - int i, size, error = -ENOMEM;
106 + int i, size, error;
107 int do_unreg = 0;
108
109 if (namelen > DLM_LOCKSPACE_LEN)
110 @@ -393,12 +378,32 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
111 if (!try_module_get(THIS_MODULE))
112 return -EINVAL;
113
114 - ls = dlm_find_lockspace_name(name, namelen);
115 - if (ls) {
116 - *lockspace = ls;
117 + error = 0;
118 +
119 + spin_lock(&lslist_lock);
120 + list_for_each_entry(ls, &lslist, ls_list) {
121 + WARN_ON(ls->ls_create_count <= 0);
122 + if (ls->ls_namelen != namelen)
123 + continue;
124 + if (memcmp(ls->ls_name, name, namelen))
125 + continue;
126 + if (flags & DLM_LSFL_NEWEXCL) {
127 + error = -EEXIST;
128 + break;
129 + }
130 + ls->ls_create_count++;
131 module_put(THIS_MODULE);
132 - return -EEXIST;
133 + error = 1; /* not an error, return 0 */
134 + break;
135 }
136 + spin_unlock(&lslist_lock);
137 +
138 + if (error < 0)
139 + goto out;
140 + if (error)
141 + goto ret_zero;
142 +
143 + error = -ENOMEM;
144
145 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
146 if (!ls)
147 @@ -418,8 +423,9 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
148 ls->ls_allocation = GFP_KERNEL;
149
150 /* ls_exflags are forced to match among nodes, and we don't
151 - need to require all nodes to have TIMEWARN or FS set */
152 - ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
153 + need to require all nodes to have some flags set */
154 + ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
155 + DLM_LSFL_NEWEXCL));
156
157 size = dlm_config.ci_rsbtbl_size;
158 ls->ls_rsbtbl_size = size;
159 @@ -510,6 +516,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
160 down_write(&ls->ls_in_recovery);
161
162 spin_lock(&lslist_lock);
163 + ls->ls_create_count = 1;
164 list_add(&ls->ls_list, &lslist);
165 spin_unlock(&lslist_lock);
166
167 @@ -548,7 +555,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
168 dlm_create_debug_file(ls);
169
170 log_debug(ls, "join complete");
171 -
172 + ret_zero:
173 *lockspace = ls;
174 return 0;
175
176 @@ -635,11 +642,32 @@ static int release_lockspace(struct dlm_ls *ls, int force)
177 struct dlm_lkb *lkb;
178 struct dlm_rsb *rsb;
179 struct list_head *head;
180 - int i;
181 - int busy = lockspace_busy(ls);
182 + int i, busy, rv;
183 +
184 + busy = lockspace_busy(ls);
185 +
186 + spin_lock(&lslist_lock);
187 + if (ls->ls_create_count == 1) {
188 + if (busy > force)
189 + rv = -EBUSY;
190 + else {
191 + /* remove_lockspace takes ls off lslist */
192 + ls->ls_create_count = 0;
193 + rv = 0;
194 + }
195 + } else if (ls->ls_create_count > 1) {
196 + rv = --ls->ls_create_count;
197 + } else {
198 + rv = -EINVAL;
199 + }
200 + spin_unlock(&lslist_lock);
201 +
202 + if (rv) {
203 + log_debug(ls, "release_lockspace no remove %d", rv);
204 + return rv;
205 + }
206
207 - if (busy > force)
208 - return -EBUSY;
209 + dlm_device_deregister(ls);
210
211 if (force < 3)
212 do_uevent(ls, 0);
213 @@ -720,15 +748,10 @@ static int release_lockspace(struct dlm_ls *ls, int force)
214 dlm_clear_members(ls);
215 dlm_clear_members_gone(ls);
216 kfree(ls->ls_node_array);
217 + log_debug(ls, "release_lockspace final free");
218 kobject_put(&ls->ls_kobj);
219 /* The ls structure will be freed when the kobject is done with */
220
221 - mutex_lock(&ls_lock);
222 - ls_count--;
223 - if (!ls_count)
224 - threads_stop();
225 - mutex_unlock(&ls_lock);
226 -
227 module_put(THIS_MODULE);
228 return 0;
229 }
230 @@ -750,11 +773,21 @@ static int release_lockspace(struct dlm_ls *ls, int force)
231 int dlm_release_lockspace(void *lockspace, int force)
232 {
233 struct dlm_ls *ls;
234 + int error;
235
236 ls = dlm_find_lockspace_local(lockspace);
237 if (!ls)
238 return -EINVAL;
239 dlm_put_lockspace(ls);
240 - return release_lockspace(ls, force);
241 +
242 + mutex_lock(&ls_lock);
243 + error = release_lockspace(ls, force);
244 + if (!error)
245 + ls_count--;
246 + else if (!ls_count)
247 + threads_stop();
248 + mutex_unlock(&ls_lock);
249 +
250 + return error;
251 }
252
253 diff --git a/fs/dlm/user.c b/fs/dlm/user.c
254 index 34f14a1..6542110 100644
255 --- a/fs/dlm/user.c
256 +++ b/fs/dlm/user.c
257 @@ -1,5 +1,5 @@
258 /*
259 - * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
260 + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
261 *
262 * This copyrighted material is made available to anyone wishing to use,
263 * modify, copy, or redistribute it subject to the terms and conditions
264 @@ -340,10 +340,15 @@ static int device_user_deadlock(struct dlm_user_proc *proc,
265 return error;
266 }
267
268 -static int create_misc_device(struct dlm_ls *ls, char *name)
269 +static int dlm_device_register(struct dlm_ls *ls, char *name)
270 {
271 int error, len;
272
273 + /* The device is already registered. This happens when the
274 + lockspace is created multiple times from userspace. */
275 + if (ls->ls_device.name)
276 + return 0;
277 +
278 error = -ENOMEM;
279 len = strlen(name) + strlen(name_prefix) + 2;
280 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
281 @@ -363,6 +368,22 @@ fail:
282 return error;
283 }
284
285 +int dlm_device_deregister(struct dlm_ls *ls)
286 +{
287 + int error;
288 +
289 + /* The device is not registered. This happens when the lockspace
290 + was never used from userspace, or when device_create_lockspace()
291 + calls dlm_release_lockspace() after the register fails. */
292 + if (!ls->ls_device.name)
293 + return 0;
294 +
295 + error = misc_deregister(&ls->ls_device);
296 + if (!error)
297 + kfree(ls->ls_device.name);
298 + return error;
299 +}
300 +
301 static int device_user_purge(struct dlm_user_proc *proc,
302 struct dlm_purge_params *params)
303 {
304 @@ -397,7 +418,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params)
305 if (!ls)
306 return -ENOENT;
307
308 - error = create_misc_device(ls, params->name);
309 + error = dlm_device_register(ls, params->name);
310 dlm_put_lockspace(ls);
311
312 if (error)
313 @@ -421,31 +442,22 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
314 if (!ls)
315 return -ENOENT;
316
317 - /* Deregister the misc device first, so we don't have
318 - * a device that's not attached to a lockspace. If
319 - * dlm_release_lockspace fails then we can recreate it
320 - */
321 - error = misc_deregister(&ls->ls_device);
322 - if (error) {
323 - dlm_put_lockspace(ls);
324 - goto out;
325 - }
326 - kfree(ls->ls_device.name);
327 -
328 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
329 force = 2;
330
331 lockspace = ls->ls_local_handle;
332 + dlm_put_lockspace(ls);
333
334 - /* dlm_release_lockspace waits for references to go to zero,
335 - so all processes will need to close their device for the ls
336 - before the release will procede */
337 + /* The final dlm_release_lockspace waits for references to go to
338 + zero, so all processes will need to close their device for the
339 + ls before the release will proceed. release also calls the
340 + device_deregister above. Converting a positive return value
341 + from release to zero means that userspace won't know when its
342 + release was the final one, but it shouldn't need to know. */
343
344 - dlm_put_lockspace(ls);
345 error = dlm_release_lockspace(lockspace, force);
346 - if (error)
347 - create_misc_device(ls, ls->ls_name);
348 - out:
349 + if (error > 0)
350 + error = 0;
351 return error;
352 }
353
354 diff --git a/fs/dlm/user.h b/fs/dlm/user.h
355 index d38e9f3..c528b6b 100644
356 --- a/fs/dlm/user.h
357 +++ b/fs/dlm/user.h
358 @@ -1,5 +1,5 @@
359 /*
360 - * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
361 + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
362 *
363 * This copyrighted material is made available to anyone wishing to use,
364 * modify, copy, or redistribute it subject to the terms and conditions
365 @@ -12,5 +12,6 @@
366 void dlm_user_add_ast(struct dlm_lkb *lkb, int type);
367 int dlm_user_init(void);
368 void dlm_user_exit(void);
369 +int dlm_device_deregister(struct dlm_ls *ls);
370
371 #endif
372 diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
373 index 09d78c2..0c4cbe6 100644
374 --- a/fs/gfs2/locking/dlm/mount.c
375 +++ b/fs/gfs2/locking/dlm/mount.c
376 @@ -144,7 +144,8 @@ static int gdlm_mount(char *table_name, char *host_data,
377
378 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
379 &ls->dlm_lockspace,
380 - DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
381 + DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
382 + (nodir ? DLM_LSFL_NODIR : 0),
383 GDLM_LVB_SIZE);
384 if (error) {
385 log_error("dlm_new_lockspace error %d", error);
386 diff --git a/include/linux/dlm.h b/include/linux/dlm.h
387 index 203a025..b9cd386 100644
388 --- a/include/linux/dlm.h
389 +++ b/include/linux/dlm.h
390 @@ -2,7 +2,7 @@
391 *******************************************************************************
392 **
393 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
394 -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
395 +** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
396 **
397 ** This copyrighted material is made available to anyone wishing to use,
398 ** modify, copy, or redistribute it subject to the terms and conditions
399 @@ -65,9 +65,12 @@ struct dlm_lksb {
400 char * sb_lvbptr;
401 };
402
403 +/* dlm_new_lockspace() flags */
404 +
405 #define DLM_LSFL_NODIR 0x00000001
406 #define DLM_LSFL_TIMEWARN 0x00000002
407 #define DLM_LSFL_FS 0x00000004
408 +#define DLM_LSFL_NEWEXCL 0x00000008
409
410 #ifdef __KERNEL__
411
412 diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
413 index c603450..3060783 100644
414 --- a/include/linux/dlm_device.h
415 +++ b/include/linux/dlm_device.h
416 @@ -26,7 +26,7 @@
417 /* Version of the device interface */
418 #define DLM_DEVICE_VERSION_MAJOR 6
419 #define DLM_DEVICE_VERSION_MINOR 0
420 -#define DLM_DEVICE_VERSION_PATCH 0
421 +#define DLM_DEVICE_VERSION_PATCH 1
422
423 /* struct passed to the lock write */
424 struct dlm_lock_params {
425 --
426 1.5.4.5
427