aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/recover.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2012-11-15 16:01:51 -0500
committerDavid Teigland <teigland@redhat.com>2012-11-16 12:20:42 -0500
commitda8c66638ae684c99abcb30e89d2803402e7ca20 (patch)
treee14974b7eb69db1d1c595892c94298a3f547ae23 /fs/dlm/recover.c
parenta3de56bdb980c63b01662cac05d430db60ff4374 (diff)
dlm: fix lvb invalidation conditions
When a node is removed that held a PW/EX lock, the existing master node should invalidate the lvb on the resource due to the purged lock. Previously, the existing master node was invalidating the lvb if it found only NL/CR locks on the resource during recovery for the removed node. This could lead to cases where it invalidated the lvb and shouldn't have, or cases where it should have invalidated and didn't. When recovery selects a *new* master node for a resource, and that new master finds only NL/CR locks on the resource after lock recovery, it should invalidate the lvb. This case was handled correctly (but was incorrectly applied to the existing master case also.) When a process exits while holding a PW/EX lock, the lvb on the resource should be invalidated. This was not happening. The lvb contents and VALNOTVALID flag should be recovered before granting locks in recovery so that the recovered lvb state is provided in the callback. The lvb was being recovered after the lock was granted. Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/recover.c')
-rw-r--r--fs/dlm/recover.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index 4a7a76e42fc3..aedea28a86a1 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -717,8 +717,14 @@ void dlm_recovered_lock(struct dlm_rsb *r)
717 * the VALNOTVALID flag if necessary, and determining the correct lvb contents 717 * the VALNOTVALID flag if necessary, and determining the correct lvb contents
718 * based on the lvb's of the locks held on the rsb. 718 * based on the lvb's of the locks held on the rsb.
719 * 719 *
720 * RSB_VALNOTVALID is set if there are only NL/CR locks on the rsb. If it 720 * RSB_VALNOTVALID is set in two cases:
721 * was already set prior to recovery, it's not cleared, regardless of locks. 721 *
722 * 1. we are master, but not new, and we purged an EX/PW lock held by a
723 * failed node (in dlm_recover_purge which set RSB_RECOVER_LVB_INVAL)
724 *
725 * 2. we are a new master, and there are only NL/CR locks left.
726 * (We could probably improve this by only invaliding in this way when
727 * the previous master left uncleanly. VMS docs mention that.)
722 * 728 *
723 * The LVB contents are only considered for changing when this is a new master 729 * The LVB contents are only considered for changing when this is a new master
724 * of the rsb (NEW_MASTER2). Then, the rsb's lvb is taken from any lkb with 730 * of the rsb (NEW_MASTER2). Then, the rsb's lvb is taken from any lkb with
@@ -734,6 +740,19 @@ static void recover_lvb(struct dlm_rsb *r)
734 int big_lock_exists = 0; 740 int big_lock_exists = 0;
735 int lvblen = r->res_ls->ls_lvblen; 741 int lvblen = r->res_ls->ls_lvblen;
736 742
743 if (!rsb_flag(r, RSB_NEW_MASTER2) &&
744 rsb_flag(r, RSB_RECOVER_LVB_INVAL)) {
745 /* case 1 above */
746 rsb_set_flag(r, RSB_VALNOTVALID);
747 return;
748 }
749
750 if (!rsb_flag(r, RSB_NEW_MASTER2))
751 return;
752
753 /* we are the new master, so figure out if VALNOTVALID should
754 be set, and set the rsb lvb from the best lkb available. */
755
737 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { 756 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
738 if (!(lkb->lkb_exflags & DLM_LKF_VALBLK)) 757 if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
739 continue; 758 continue;
@@ -772,13 +791,10 @@ static void recover_lvb(struct dlm_rsb *r)
772 if (!lock_lvb_exists) 791 if (!lock_lvb_exists)
773 goto out; 792 goto out;
774 793
794 /* lvb is invalidated if only NL/CR locks remain */
775 if (!big_lock_exists) 795 if (!big_lock_exists)
776 rsb_set_flag(r, RSB_VALNOTVALID); 796 rsb_set_flag(r, RSB_VALNOTVALID);
777 797
778 /* don't mess with the lvb unless we're the new master */
779 if (!rsb_flag(r, RSB_NEW_MASTER2))
780 goto out;
781
782 if (!r->res_lvbptr) { 798 if (!r->res_lvbptr) {
783 r->res_lvbptr = dlm_allocate_lvb(r->res_ls); 799 r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
784 if (!r->res_lvbptr) 800 if (!r->res_lvbptr)
@@ -852,12 +868,19 @@ void dlm_recover_rsbs(struct dlm_ls *ls)
852 if (is_master(r)) { 868 if (is_master(r)) {
853 if (rsb_flag(r, RSB_RECOVER_CONVERT)) 869 if (rsb_flag(r, RSB_RECOVER_CONVERT))
854 recover_conversion(r); 870 recover_conversion(r);
871
872 /* recover lvb before granting locks so the updated
873 lvb/VALNOTVALID is presented in the completion */
874 recover_lvb(r);
875
855 if (rsb_flag(r, RSB_NEW_MASTER2)) 876 if (rsb_flag(r, RSB_NEW_MASTER2))
856 recover_grant(r); 877 recover_grant(r);
857 recover_lvb(r);
858 count++; 878 count++;
879 } else {
880 rsb_clear_flag(r, RSB_VALNOTVALID);
859 } 881 }
860 rsb_clear_flag(r, RSB_RECOVER_CONVERT); 882 rsb_clear_flag(r, RSB_RECOVER_CONVERT);
883 rsb_clear_flag(r, RSB_RECOVER_LVB_INVAL);
861 rsb_clear_flag(r, RSB_NEW_MASTER2); 884 rsb_clear_flag(r, RSB_NEW_MASTER2);
862 unlock_rsb(r); 885 unlock_rsb(r);
863 } 886 }