diff options
author | David Teigland <teigland@redhat.com> | 2012-06-14 13:17:32 -0400 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2012-07-16 15:18:01 -0400 |
commit | 05c32f47bfae74dabff05208957768078b53cc49 (patch) | |
tree | 71034eba054f49723a0dac41f6bcd9d4f37eb2bc /fs/dlm/lockspace.c | |
parent | 1d7c484eeb167fc374294e38ae402de4097c8611 (diff) |
dlm: fix race between remove and lookup
It was possible for a remove message on an old
rsb to be sent after a lookup message on a new
rsb, where the rsbs were for the same resource
name. This could lead to a missing directory
entry for the new rsb.
It is fixed by keeping a copy of the resource
name being removed until after the remove has
been sent. A lookup checks if this in-progress
remove matches the name it is looking up.
Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/lockspace.c')
-rw-r--r-- | fs/dlm/lockspace.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index d4d3b3165c6c..952557d00ccd 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -506,6 +506,15 @@ static int new_lockspace(const char *name, const char *cluster, | |||
506 | spin_lock_init(&ls->ls_rsbtbl[i].lock); | 506 | spin_lock_init(&ls->ls_rsbtbl[i].lock); |
507 | } | 507 | } |
508 | 508 | ||
509 | spin_lock_init(&ls->ls_remove_spin); | ||
510 | |||
511 | for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) { | ||
512 | ls->ls_remove_names[i] = kzalloc(DLM_RESNAME_MAXLEN+1, | ||
513 | GFP_KERNEL); | ||
514 | if (!ls->ls_remove_names[i]) | ||
515 | goto out_rsbtbl; | ||
516 | } | ||
517 | |||
509 | idr_init(&ls->ls_lkbidr); | 518 | idr_init(&ls->ls_lkbidr); |
510 | spin_lock_init(&ls->ls_lkbidr_spin); | 519 | spin_lock_init(&ls->ls_lkbidr_spin); |
511 | 520 | ||
@@ -556,7 +565,7 @@ static int new_lockspace(const char *name, const char *cluster, | |||
556 | 565 | ||
557 | ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS); | 566 | ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS); |
558 | if (!ls->ls_recover_buf) | 567 | if (!ls->ls_recover_buf) |
559 | goto out_lkbfree; | 568 | goto out_lkbidr; |
560 | 569 | ||
561 | ls->ls_slot = 0; | 570 | ls->ls_slot = 0; |
562 | ls->ls_num_slots = 0; | 571 | ls->ls_num_slots = 0; |
@@ -640,8 +649,13 @@ static int new_lockspace(const char *name, const char *cluster, | |||
640 | spin_unlock(&lslist_lock); | 649 | spin_unlock(&lslist_lock); |
641 | idr_destroy(&ls->ls_recover_idr); | 650 | idr_destroy(&ls->ls_recover_idr); |
642 | kfree(ls->ls_recover_buf); | 651 | kfree(ls->ls_recover_buf); |
643 | out_lkbfree: | 652 | out_lkbidr: |
644 | idr_destroy(&ls->ls_lkbidr); | 653 | idr_destroy(&ls->ls_lkbidr); |
654 | for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) { | ||
655 | if (ls->ls_remove_names[i]) | ||
656 | kfree(ls->ls_remove_names[i]); | ||
657 | } | ||
658 | out_rsbtbl: | ||
645 | vfree(ls->ls_rsbtbl); | 659 | vfree(ls->ls_rsbtbl); |
646 | out_lsfree: | 660 | out_lsfree: |
647 | if (do_unreg) | 661 | if (do_unreg) |
@@ -796,6 +810,9 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |||
796 | 810 | ||
797 | vfree(ls->ls_rsbtbl); | 811 | vfree(ls->ls_rsbtbl); |
798 | 812 | ||
813 | for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) | ||
814 | kfree(ls->ls_remove_names[i]); | ||
815 | |||
799 | while (!list_empty(&ls->ls_new_rsb)) { | 816 | while (!list_empty(&ls->ls_new_rsb)) { |
800 | rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, | 817 | rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, |
801 | res_hashchain); | 818 | res_hashchain); |