1 From: David Teigland <teigland@redhat.com>
2 Subject: [PATCH] dlm: allow multiple lockspace creates
3 Patch-mainline: 2.6.28?
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
12 Signed-off-by: David Teigland <teigland@redhat.com>
13 Acked-by: Mark Fasheh <mfasheh@suse.com>
15 fs/dlm/dlm_internal.h | 6 ++-
16 fs/dlm/lockspace.c | 107 ++++++++++++++++++++++++++++---------------
17 fs/dlm/user.c | 54 +++++++++++++--------
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(-)
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
29 *******************************************************************************
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.
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 */
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;
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
53 *******************************************************************************
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.
59 ** This copyrighted material is made available to anyone wishing to use,
60 ** modify, copy, or redistribute it subject to the terms and conditions
64 #include "requestqueue.h"
68 static struct mutex ls_lock;
69 @@ -246,23 +247,6 @@ static void dlm_scand_stop(void)
70 kthread_stop(scand_task);
73 -static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
77 - spin_lock(&lslist_lock);
79 - list_for_each_entry(ls, &lslist, ls_list) {
80 - if (ls->ls_namelen == namelen &&
81 - memcmp(ls->ls_name, name, namelen) == 0)
86 - spin_unlock(&lslist_lock);
90 struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
93 @@ -327,6 +311,7 @@ static void remove_lockspace(struct dlm_ls *ls)
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);
101 @@ -381,7 +366,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
102 uint32_t flags, int lvblen)
105 - int i, size, error = -ENOMEM;
106 + int i, size, error;
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))
114 - ls = dlm_find_lockspace_name(name, namelen);
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)
124 + if (memcmp(ls->ls_name, name, namelen))
126 + if (flags & DLM_LSFL_NEWEXCL) {
130 + ls->ls_create_count++;
131 module_put(THIS_MODULE);
133 + error = 1; /* not an error, return 0 */
136 + spin_unlock(&lslist_lock);
145 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
147 @@ -418,8 +423,9 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
148 ls->ls_allocation = GFP_KERNEL;
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));
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);
162 spin_lock(&lslist_lock);
163 + ls->ls_create_count = 1;
164 list_add(&ls->ls_list, &lslist);
165 spin_unlock(&lslist_lock);
167 @@ -548,7 +555,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
168 dlm_create_debug_file(ls);
170 log_debug(ls, "join complete");
176 @@ -635,11 +642,32 @@ static int release_lockspace(struct dlm_ls *ls, int force)
179 struct list_head *head;
181 - int busy = lockspace_busy(ls);
184 + busy = lockspace_busy(ls);
186 + spin_lock(&lslist_lock);
187 + if (ls->ls_create_count == 1) {
191 + /* remove_lockspace takes ls off lslist */
192 + ls->ls_create_count = 0;
195 + } else if (ls->ls_create_count > 1) {
196 + rv = --ls->ls_create_count;
200 + spin_unlock(&lslist_lock);
203 + log_debug(ls, "release_lockspace no remove %d", rv);
209 + dlm_device_deregister(ls);
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 */
221 - mutex_lock(&ls_lock);
225 - mutex_unlock(&ls_lock);
227 module_put(THIS_MODULE);
230 @@ -750,11 +773,21 @@ static int release_lockspace(struct dlm_ls *ls, int force)
231 int dlm_release_lockspace(void *lockspace, int force)
236 ls = dlm_find_lockspace_local(lockspace);
239 dlm_put_lockspace(ls);
240 - return release_lockspace(ls, force);
242 + mutex_lock(&ls_lock);
243 + error = release_lockspace(ls, force);
246 + else if (!ls_count)
248 + mutex_unlock(&ls_lock);
253 diff --git a/fs/dlm/user.c b/fs/dlm/user.c
254 index 34f14a1..6542110 100644
259 - * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
260 + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
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,
268 -static int create_misc_device(struct dlm_ls *ls, char *name)
269 +static int dlm_device_register(struct dlm_ls *ls, char *name)
273 + /* The device is already registered. This happens when the
274 + lockspace is created multiple times from userspace. */
275 + if (ls->ls_device.name)
279 len = strlen(name) + strlen(name_prefix) + 2;
280 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
281 @@ -363,6 +368,22 @@ fail:
285 +int dlm_device_deregister(struct dlm_ls *ls)
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)
295 + error = misc_deregister(&ls->ls_device);
297 + kfree(ls->ls_device.name);
301 static int device_user_purge(struct dlm_user_proc *proc,
302 struct dlm_purge_params *params)
304 @@ -397,7 +418,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params)
308 - error = create_misc_device(ls, params->name);
309 + error = dlm_device_register(ls, params->name);
310 dlm_put_lockspace(ls);
313 @@ -421,31 +442,22 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
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
321 - error = misc_deregister(&ls->ls_device);
323 - dlm_put_lockspace(ls);
326 - kfree(ls->ls_device.name);
328 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
331 lockspace = ls->ls_local_handle;
332 + dlm_put_lockspace(ls);
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. */
344 - dlm_put_lockspace(ls);
345 error = dlm_release_lockspace(lockspace, force);
347 - create_misc_device(ls, ls->ls_name);
354 diff --git a/fs/dlm/user.h b/fs/dlm/user.h
355 index d38e9f3..c528b6b 100644
360 - * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
361 + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
363 * This copyrighted material is made available to anyone wishing to use,
364 * modify, copy, or redistribute it subject to the terms and conditions
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);
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,
378 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
380 - DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
381 + DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
382 + (nodir ? DLM_LSFL_NODIR : 0),
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
391 *******************************************************************************
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.
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 {
403 +/* dlm_new_lockspace() flags */
405 #define DLM_LSFL_NODIR 0x00000001
406 #define DLM_LSFL_TIMEWARN 0x00000002
407 #define DLM_LSFL_FS 0x00000004
408 +#define DLM_LSFL_NEWEXCL 0x00000008
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
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
423 /* struct passed to the lock write */
424 struct dlm_lock_params {