]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.fixes/dlm-allow-multiple-lockspaces.patch
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / dlm-allow-multiple-lockspaces.patch
CommitLineData
00e5a55c
BS
1From: David Teigland <teigland@redhat.com>
2Subject: [PATCH] dlm: allow multiple lockspace creates
3Patch-mainline: 2.6.28?
4References: FATE110294
5
6Add a count for lockspace create and release so that create can
7be called multiple times to use the lockspace from different places.
8Also add the new flag DLM_LSFL_NEWEXCL to create a lockspace with
9the previous behavior of returning -EEXIST if the lockspace already
10exists.
11
12Signed-off-by: David Teigland <teigland@redhat.com>
13Acked-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
24diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
25index 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
48diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
49index 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
253diff --git a/fs/dlm/user.c b/fs/dlm/user.c
254index 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
354diff --git a/fs/dlm/user.h b/fs/dlm/user.h
355index 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
372diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
373index 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);
386diff --git a/include/linux/dlm.h b/include/linux/dlm.h
387index 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
412diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
413index 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--
4261.5.4.5
427