aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/lockspace.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2012-06-14 13:17:32 -0400
committerDavid Teigland <teigland@redhat.com>2012-07-16 15:18:01 -0400
commit05c32f47bfae74dabff05208957768078b53cc49 (patch)
tree71034eba054f49723a0dac41f6bcd9d4f37eb2bc /fs/dlm/lockspace.c
parent1d7c484eeb167fc374294e38ae402de4097c8611 (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.c21
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);