diff options
Diffstat (limited to 'fs/dlm/recover.c')
| -rw-r--r-- | fs/dlm/recover.c | 37 | 
1 files changed, 30 insertions, 7 deletions
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index 4a7a76e42fc..aedea28a86a 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c @@ -717,8 +717,14 @@ void dlm_recovered_lock(struct dlm_rsb *r)   * the VALNOTVALID flag if necessary, and determining the correct lvb contents   * based on the lvb's of the locks held on the rsb.   * - * RSB_VALNOTVALID is set if there are only NL/CR locks on the rsb.  If it - * was already set prior to recovery, it's not cleared, regardless of locks. + * RSB_VALNOTVALID is set in two cases: + * + * 1. we are master, but not new, and we purged an EX/PW lock held by a + * failed node (in dlm_recover_purge which set RSB_RECOVER_LVB_INVAL) + * + * 2. we are a new master, and there are only NL/CR locks left. + * (We could probably improve this by only invaliding in this way when + * the previous master left uncleanly.  VMS docs mention that.)   *   * The LVB contents are only considered for changing when this is a new master   * 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)  	int big_lock_exists = 0;  	int lvblen = r->res_ls->ls_lvblen; +	if (!rsb_flag(r, RSB_NEW_MASTER2) && +	    rsb_flag(r, RSB_RECOVER_LVB_INVAL)) { +		/* case 1 above */ +		rsb_set_flag(r, RSB_VALNOTVALID); +		return; +	} + +	if (!rsb_flag(r, RSB_NEW_MASTER2)) +		return; + +	/* we are the new master, so figure out if VALNOTVALID should +	   be set, and set the rsb lvb from the best lkb available. */ +  	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {  		if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))  			continue; @@ -772,13 +791,10 @@ static void recover_lvb(struct dlm_rsb *r)  	if (!lock_lvb_exists)  		goto out; +	/* lvb is invalidated if only NL/CR locks remain */  	if (!big_lock_exists)  		rsb_set_flag(r, RSB_VALNOTVALID); -	/* don't mess with the lvb unless we're the new master */ -	if (!rsb_flag(r, RSB_NEW_MASTER2)) -		goto out; -  	if (!r->res_lvbptr) {  		r->res_lvbptr = dlm_allocate_lvb(r->res_ls);  		if (!r->res_lvbptr) @@ -852,12 +868,19 @@ void dlm_recover_rsbs(struct dlm_ls *ls)  		if (is_master(r)) {  			if (rsb_flag(r, RSB_RECOVER_CONVERT))  				recover_conversion(r); + +			/* recover lvb before granting locks so the updated +			   lvb/VALNOTVALID is presented in the completion */ +			recover_lvb(r); +  			if (rsb_flag(r, RSB_NEW_MASTER2))  				recover_grant(r); -			recover_lvb(r);  			count++; +		} else { +			rsb_clear_flag(r, RSB_VALNOTVALID);  		}  		rsb_clear_flag(r, RSB_RECOVER_CONVERT); +		rsb_clear_flag(r, RSB_RECOVER_LVB_INVAL);  		rsb_clear_flag(r, RSB_NEW_MASTER2);  		unlock_rsb(r);  	}  |