diff options
author | David Teigland <teigland@redhat.com> | 2008-08-06 14:30:24 -0400 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2008-08-28 12:49:15 -0400 |
commit | 0f8e0d9a317406612700426fad3efab0b7bbc467 (patch) | |
tree | b4ed35afeab36615e50d5c7928a6199780fd2fca /fs/dlm/user.c | |
parent | 4c246edd2550304df5b766cc841584b2bb058843 (diff) |
dlm: allow multiple lockspace creates
Add a count for lockspace create and release so that create can
be called multiple times to use the lockspace from different places.
Also add the new flag DLM_LSFL_NEWEXCL to create a lockspace with
the previous behavior of returning -EEXIST if the lockspace already
exists.
Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/user.c')
-rw-r--r-- | fs/dlm/user.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 34f14a14fb4e..6542110c0da4 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved. | 2 | * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This copyrighted material is made available to anyone wishing to use, | 4 | * This copyrighted material is made available to anyone wishing to use, |
5 | * modify, copy, or redistribute it subject to the terms and conditions | 5 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -340,10 +340,15 @@ static int device_user_deadlock(struct dlm_user_proc *proc, | |||
340 | return error; | 340 | return error; |
341 | } | 341 | } |
342 | 342 | ||
343 | static int create_misc_device(struct dlm_ls *ls, char *name) | 343 | static int dlm_device_register(struct dlm_ls *ls, char *name) |
344 | { | 344 | { |
345 | int error, len; | 345 | int error, len; |
346 | 346 | ||
347 | /* The device is already registered. This happens when the | ||
348 | lockspace is created multiple times from userspace. */ | ||
349 | if (ls->ls_device.name) | ||
350 | return 0; | ||
351 | |||
347 | error = -ENOMEM; | 352 | error = -ENOMEM; |
348 | len = strlen(name) + strlen(name_prefix) + 2; | 353 | len = strlen(name) + strlen(name_prefix) + 2; |
349 | ls->ls_device.name = kzalloc(len, GFP_KERNEL); | 354 | ls->ls_device.name = kzalloc(len, GFP_KERNEL); |
@@ -363,6 +368,22 @@ fail: | |||
363 | return error; | 368 | return error; |
364 | } | 369 | } |
365 | 370 | ||
371 | int dlm_device_deregister(struct dlm_ls *ls) | ||
372 | { | ||
373 | int error; | ||
374 | |||
375 | /* The device is not registered. This happens when the lockspace | ||
376 | was never used from userspace, or when device_create_lockspace() | ||
377 | calls dlm_release_lockspace() after the register fails. */ | ||
378 | if (!ls->ls_device.name) | ||
379 | return 0; | ||
380 | |||
381 | error = misc_deregister(&ls->ls_device); | ||
382 | if (!error) | ||
383 | kfree(ls->ls_device.name); | ||
384 | return error; | ||
385 | } | ||
386 | |||
366 | static int device_user_purge(struct dlm_user_proc *proc, | 387 | static int device_user_purge(struct dlm_user_proc *proc, |
367 | struct dlm_purge_params *params) | 388 | struct dlm_purge_params *params) |
368 | { | 389 | { |
@@ -397,7 +418,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params) | |||
397 | if (!ls) | 418 | if (!ls) |
398 | return -ENOENT; | 419 | return -ENOENT; |
399 | 420 | ||
400 | error = create_misc_device(ls, params->name); | 421 | error = dlm_device_register(ls, params->name); |
401 | dlm_put_lockspace(ls); | 422 | dlm_put_lockspace(ls); |
402 | 423 | ||
403 | if (error) | 424 | if (error) |
@@ -421,31 +442,22 @@ static int device_remove_lockspace(struct dlm_lspace_params *params) | |||
421 | if (!ls) | 442 | if (!ls) |
422 | return -ENOENT; | 443 | return -ENOENT; |
423 | 444 | ||
424 | /* Deregister the misc device first, so we don't have | ||
425 | * a device that's not attached to a lockspace. If | ||
426 | * dlm_release_lockspace fails then we can recreate it | ||
427 | */ | ||
428 | error = misc_deregister(&ls->ls_device); | ||
429 | if (error) { | ||
430 | dlm_put_lockspace(ls); | ||
431 | goto out; | ||
432 | } | ||
433 | kfree(ls->ls_device.name); | ||
434 | |||
435 | if (params->flags & DLM_USER_LSFLG_FORCEFREE) | 445 | if (params->flags & DLM_USER_LSFLG_FORCEFREE) |
436 | force = 2; | 446 | force = 2; |
437 | 447 | ||
438 | lockspace = ls->ls_local_handle; | 448 | lockspace = ls->ls_local_handle; |
449 | dlm_put_lockspace(ls); | ||
439 | 450 | ||
440 | /* dlm_release_lockspace waits for references to go to zero, | 451 | /* The final dlm_release_lockspace waits for references to go to |
441 | so all processes will need to close their device for the ls | 452 | zero, so all processes will need to close their device for the |
442 | before the release will procede */ | 453 | ls before the release will proceed. release also calls the |
454 | device_deregister above. Converting a positive return value | ||
455 | from release to zero means that userspace won't know when its | ||
456 | release was the final one, but it shouldn't need to know. */ | ||
443 | 457 | ||
444 | dlm_put_lockspace(ls); | ||
445 | error = dlm_release_lockspace(lockspace, force); | 458 | error = dlm_release_lockspace(lockspace, force); |
446 | if (error) | 459 | if (error > 0) |
447 | create_misc_device(ls, ls->ls_name); | 460 | error = 0; |
448 | out: | ||
449 | return error; | 461 | return error; |
450 | } | 462 | } |
451 | 463 | ||