[Ocfs2-devel] [PATCH v2] ocfs2: add error handling path when jbd2 enter ABORT status

Heming Zhao heming.zhao at suse.com
Mon Jun 26 11:24:53 UTC 2023


fstest generic cases 347 361 628 629 trigger a same issue:
When jbd2 enter ABORT status, ocfs2 ignores it and keep going to commit
journal. This issue causes umount failure (hanging).

This commit gives ocfs2 ability to handle jbd2 ABORT case. After
patching, umount successfully and leave journal dirty status.

Signed-off-by: Heming Zhao <heming.zhao at suse.com>
---
v2:
   (this v2 only for patch [2/2], see below URL)
   add description in commit log.
   don't reset ->j_num_trans and leave journal dirty status on disk.

v1: https://oss.oracle.com/pipermail/ocfs2-devel/2023-April/000896.html
---
 fs/ocfs2/alloc.c      | 10 ++++++----
 fs/ocfs2/journal.c    | 17 +++++++++++++++--
 fs/ocfs2/journal.h    |  5 +++--
 fs/ocfs2/localalloc.c |  3 +++
 4 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 51c93929a146..d90961a1c433 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -6308,11 +6308,13 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb)
 
 	if (tl_inode) {
 		cancel_delayed_work(&osb->osb_truncate_log_wq);
-		flush_workqueue(osb->ocfs2_wq);
+		if (!is_journal_aborted(osb->journal->j_journal)) {
+			flush_workqueue(osb->ocfs2_wq);
 
-		status = ocfs2_flush_truncate_log(osb);
-		if (status < 0)
-			mlog_errno(status);
+			status = ocfs2_flush_truncate_log(osb);
+			if (status < 0)
+				mlog_errno(status);
+		}
 
 		brelse(osb->osb_tl_bh);
 		iput(osb->osb_tl_inode);
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 25d8072ccfce..30de277461b3 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -314,6 +314,11 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb)
 	if (status < 0) {
 		up_write(&journal->j_trans_barrier);
 		mlog_errno(status);
+		if (is_journal_aborted(journal->j_journal)) {
+			ocfs2_error(osb->sb, "jbd2 status: ABORT.\n");
+			wake_up(&journal->j_checkpointed);
+			status = -EROFS;
+		}
 		goto finally;
 	}
 
@@ -1010,6 +1015,8 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
 	if (!journal)
 		goto done;
 
+	status = is_journal_aborted(journal->j_journal);
+
 	inode = journal->j_inode;
 
 	if (journal->j_state != OCFS2_JOURNAL_LOADED)
@@ -1038,9 +1045,10 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
 		osb->commit_task = NULL;
 	}
 
-	BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
+	BUG_ON(!is_journal_aborted(journal->j_journal) &&
+			atomic_read(&(osb->journal->j_num_trans)) != 0);
 
-	if (ocfs2_mount_local(osb)) {
+	if (!status && ocfs2_mount_local(osb)) {
 		jbd2_journal_lock_updates(journal->j_journal);
 		status = jbd2_journal_flush(journal->j_journal, 0);
 		jbd2_journal_unlock_updates(journal->j_journal);
@@ -2352,6 +2360,11 @@ static int ocfs2_commit_thread(void *arg)
 			if (printk_timed_ratelimit(&abort_warn_time, 60*HZ))
 				mlog(ML_ERROR, "status = %d, journal is "
 						"already aborted.\n", status);
+
+			if (status == -EROFS) {
+				osb->commit_task = NULL;
+				return status;
+			}
 			/*
 			 * After ocfs2_commit_cache() fails, j_num_trans has a
 			 * non-zero value.  Sleep here to avoid a busy-wait
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 41c382f68529..080726ffa24d 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -192,7 +192,7 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
 {
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-	if (ocfs2_mount_local(osb))
+	if (ocfs2_mount_local(osb) || sb_rdonly(inode->i_sb))
 		return;
 
 	if (!ocfs2_ci_fully_checkpointed(INODE_CACHE(inode))) {
@@ -205,7 +205,8 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
 		ocfs2_start_checkpoint(osb);
 
 		wait_event(osb->journal->j_checkpointed,
-			   ocfs2_ci_fully_checkpointed(INODE_CACHE(inode)));
+			   ocfs2_ci_fully_checkpointed(INODE_CACHE(inode)) ||
+			   sb_rdonly(inode->i_sb));
 	}
 }
 
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index c4426d12a2ad..e2e3400717b0 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -378,6 +378,9 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
 	if (osb->ocfs2_wq)
 		flush_workqueue(osb->ocfs2_wq);
 
+	if (is_journal_aborted(osb->journal->j_journal))
+		goto out;
+
 	if (osb->local_alloc_state == OCFS2_LA_UNUSED)
 		goto out;
 
-- 
2.41.0




More information about the Ocfs2-devel mailing list