diff options
| -rw-r--r-- | fs/jbd2/transaction.c | 16 | 
1 files changed, 16 insertions, 0 deletions
| diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index e65e0aca2826..6250c9faa4cb 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -2120,6 +2120,7 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal,  {  	struct buffer_head *head;  	struct buffer_head *bh; +	bool has_write_io_error = false;  	int ret = 0;  	J_ASSERT(PageLocked(page)); @@ -2144,11 +2145,26 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal,  		jbd2_journal_put_journal_head(jh);  		if (buffer_jbd(bh))  			goto busy; + +		/* +		 * If we free a metadata buffer which has been failed to +		 * write out, the jbd2 checkpoint procedure will not detect +		 * this failure and may lead to filesystem inconsistency +		 * after cleanup journal tail. +		 */ +		if (buffer_write_io_error(bh)) { +			pr_err("JBD2: Error while async write back metadata bh %llu.", +			       (unsigned long long)bh->b_blocknr); +			has_write_io_error = true; +		}  	} while ((bh = bh->b_this_page) != head);  	ret = try_to_free_buffers(page);  busy: +	if (has_write_io_error) +		jbd2_journal_abort(journal, -EIO); +  	return ret;  } | 
