diff options
Diffstat (limited to 'fs/gfs2/recovery.c')
| -rw-r--r-- | fs/gfs2/recovery.c | 51 | 
1 files changed, 29 insertions, 22 deletions
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index f2a02edcac8..94555d4c569 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -52,9 +52,9 @@ int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,  	return error;  } -int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) +int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)  { -	struct list_head *head = &sdp->sd_revoke_list; +	struct list_head *head = &jd->jd_revoke_list;  	struct gfs2_revoke_replay *rr;  	int found = 0; @@ -81,13 +81,13 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)  	return 1;  } -int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) +int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)  {  	struct gfs2_revoke_replay *rr;  	int wrap, a, b, revoke;  	int found = 0; -	list_for_each_entry(rr, &sdp->sd_revoke_list, rr_list) { +	list_for_each_entry(rr, &jd->jd_revoke_list, rr_list) {  		if (rr->rr_blkno == blkno) {  			found = 1;  			break; @@ -97,17 +97,17 @@ int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)  	if (!found)  		return 0; -	wrap = (rr->rr_where < sdp->sd_replay_tail); -	a = (sdp->sd_replay_tail < where); +	wrap = (rr->rr_where < jd->jd_replay_tail); +	a = (jd->jd_replay_tail < where);  	b = (where < rr->rr_where);  	revoke = (wrap) ? (a || b) : (a && b);  	return revoke;  } -void gfs2_revoke_clean(struct gfs2_sbd *sdp) +void gfs2_revoke_clean(struct gfs2_jdesc *jd)  { -	struct list_head *head = &sdp->sd_revoke_list; +	struct list_head *head = &jd->jd_revoke_list;  	struct gfs2_revoke_replay *rr;  	while (!list_empty(head)) { @@ -436,12 +436,16 @@ static void gfs2_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,  	char env_status[20];  	char *envp[] = { env_jid, env_status, NULL };  	struct lm_lockstruct *ls = &sdp->sd_lockstruct; +          ls->ls_recover_jid_done = jid;          ls->ls_recover_jid_status = message;  	sprintf(env_jid, "JID=%d", jid);  	sprintf(env_status, "RECOVERY=%s",  		message == LM_RD_SUCCESS ? "Done" : "Failed");          kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp); + +	if (sdp->sd_lockstruct.ls_ops->lm_recovery_result) +		sdp->sd_lockstruct.ls_ops->lm_recovery_result(sdp, jid, message);  }  void gfs2_recover_func(struct work_struct *work) @@ -450,7 +454,7 @@ void gfs2_recover_func(struct work_struct *work)  	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);  	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);  	struct gfs2_log_header_host head; -	struct gfs2_holder j_gh, ji_gh, t_gh; +	struct gfs2_holder j_gh, ji_gh, thaw_gh;  	unsigned long t;  	int ro = 0;  	unsigned int pass; @@ -504,15 +508,17 @@ void gfs2_recover_func(struct work_struct *work)  		t = jiffies; -		/* Acquire a shared hold on the transaction lock */ +		/* Acquire a shared hold on the freeze lock */ -		error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, -					   LM_FLAG_NOEXP | LM_FLAG_PRIORITY | -					   GL_NOCACHE, &t_gh); +		error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, +					   LM_FLAG_NOEXP | LM_FLAG_PRIORITY, +					   &thaw_gh);  		if (error)  			goto fail_gunlock_ji; -		if (test_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags)) { +		if (test_bit(SDF_RORECOVERY, &sdp->sd_flags)) { +			ro = 1; +		} else if (test_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags)) {  			if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))  				ro = 1;  		} else { @@ -532,7 +538,7 @@ void gfs2_recover_func(struct work_struct *work)  			fs_warn(sdp, "jid=%u: Can't replay: read-only block "  				"device\n", jd->jd_jid);  			error = -EROFS; -			goto fail_gunlock_tr; +			goto fail_gunlock_thaw;  		}  		fs_info(sdp, "jid=%u: Replaying journal...\n", jd->jd_jid); @@ -543,14 +549,14 @@ void gfs2_recover_func(struct work_struct *work)  						   head.lh_blkno, pass);  			lops_after_scan(jd, error, pass);  			if (error) -				goto fail_gunlock_tr; +				goto fail_gunlock_thaw;  		}  		error = clean_journal(jd, &head);  		if (error) -			goto fail_gunlock_tr; +			goto fail_gunlock_thaw; -		gfs2_glock_dq_uninit(&t_gh); +		gfs2_glock_dq_uninit(&thaw_gh);  		t = DIV_ROUND_UP(jiffies - t, HZ);  		fs_info(sdp, "jid=%u: Journal replayed in %lus\n",  			jd->jd_jid, t); @@ -566,8 +572,8 @@ void gfs2_recover_func(struct work_struct *work)  	fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);  	goto done; -fail_gunlock_tr: -	gfs2_glock_dq_uninit(&t_gh); +fail_gunlock_thaw: +	gfs2_glock_dq_uninit(&thaw_gh);  fail_gunlock_ji:  	if (jlocked) {  		gfs2_glock_dq_uninit(&ji_gh); @@ -577,10 +583,11 @@ fail_gunlock_j:  	fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done");  fail: +	jd->jd_recover_error = error;  	gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);  done:  	clear_bit(JDF_RECOVERY, &jd->jd_flags); -	smp_mb__after_clear_bit(); +	smp_mb__after_atomic();  	wake_up_bit(&jd->jd_flags, JDF_RECOVERY);  } @@ -605,6 +612,6 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd, bool wait)  		wait_on_bit(&jd->jd_flags, JDF_RECOVERY, gfs2_recovery_wait,  			    TASK_UNINTERRUPTIBLE); -	return 0; +	return wait ? jd->jd_recover_error : 0;  }  | 
