mirror of
https://github.com/torvalds/linux.git
synced 2024-11-13 23:51:39 +00:00
Fix various bugs / regressions for ext4, including a soft lockup, a
WARN_ON, and a BUG. -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAmV4tMwACgkQ8vlZVpUN gaNZRAf/ejQZne9iZck8SSV62mkR9E7EwN9J2+gkWFrlsyurErZlVsBA5yRB+i9A V1v6DRGDnYFwKFNHJhR/RW9NhEwpYkX9Vo3miksSCq8rsAB1kjSs3xVrTBIYi/8c ztw4ncyxW7RRFRmruzFfUEKriiyJzxJYx+EqbNsQHcl5ET6Y2/5zM0bChV9MwuN3 iS1Rm98RbHVrylzKbGG562MaGdJyUYvQ+mnRCgma1mTu6K9SWLJg211icLTsDhHg XEB/QGWji2O7xOudcry8wLIpoR6rYPAhWfbkLekW1K9hjV3iXuJoVjj7eB9LctMf FAXr8u0FKJI0iIQyrQrEEqIuh+jKBA== =4zQL -----END PGP SIGNATURE----- Merge tag 'ext4_for_linus-6.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 Pull ext4 fixes from Ted Ts'o: "Fix various bugs / regressions for ext4, including a soft lockup, a WARN_ON, and a BUG" * tag 'ext4_for_linus-6.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: jbd2: fix soft lockup in journal_finish_inode_data_buffers() ext4: fix warning in ext4_dio_write_end_io() jbd2: increase the journal IO's priority jbd2: correct the printing of write_flags in jbd2_write_superblock() ext4: prevent the normalized size from exceeding EXT_MAX_BLOCKS
This commit is contained in:
commit
cf52eed70e
@ -349,9 +349,10 @@ static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* If i_disksize got extended due to writeback of delalloc blocks while
|
||||
* the DIO was running we could fail to cleanup the orphan list in
|
||||
* ext4_handle_inode_extension(). Do it now.
|
||||
* If i_disksize got extended either due to writeback of delalloc
|
||||
* blocks or extending truncate while the DIO was running we could fail
|
||||
* to cleanup the orphan list in ext4_handle_inode_extension(). Do it
|
||||
* now.
|
||||
*/
|
||||
if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
|
||||
handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
|
||||
@ -386,10 +387,11 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
|
||||
* blocks. But the code in ext4_iomap_alloc() is careful to use
|
||||
* zeroed/unwritten extents if this is possible; thus we won't leave
|
||||
* uninitialized blocks in a file even if we didn't succeed in writing
|
||||
* as much as we intended.
|
||||
* as much as we intended. Also we can race with truncate or write
|
||||
* expanding the file so we have to be a bit careful here.
|
||||
*/
|
||||
WARN_ON_ONCE(i_size_read(inode) < READ_ONCE(EXT4_I(inode)->i_disksize));
|
||||
if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize))
|
||||
if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize) &&
|
||||
pos + size <= i_size_read(inode))
|
||||
return size;
|
||||
return ext4_handle_inode_extension(inode, pos, size);
|
||||
}
|
||||
|
@ -4478,6 +4478,10 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
|
||||
start = max(start, rounddown(ac->ac_o_ex.fe_logical,
|
||||
(ext4_lblk_t)EXT4_BLOCKS_PER_GROUP(ac->ac_sb)));
|
||||
|
||||
/* avoid unnecessary preallocation that may trigger assertions */
|
||||
if (start + size > EXT_MAX_BLOCKS)
|
||||
size = EXT_MAX_BLOCKS - start;
|
||||
|
||||
/* don't cover already allocated blocks in selected range */
|
||||
if (ar->pleft && start <= ar->lleft) {
|
||||
size -= ar->lleft + 1 - start;
|
||||
|
@ -119,7 +119,7 @@ static int journal_submit_commit_record(journal_t *journal,
|
||||
struct commit_header *tmp;
|
||||
struct buffer_head *bh;
|
||||
struct timespec64 now;
|
||||
blk_opf_t write_flags = REQ_OP_WRITE | REQ_SYNC;
|
||||
blk_opf_t write_flags = REQ_OP_WRITE | JBD2_JOURNAL_REQ_FLAGS;
|
||||
|
||||
*cbh = NULL;
|
||||
|
||||
@ -270,6 +270,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
|
||||
if (!ret)
|
||||
ret = err;
|
||||
}
|
||||
cond_resched();
|
||||
spin_lock(&journal->j_list_lock);
|
||||
jinode->i_flags &= ~JI_COMMIT_RUNNING;
|
||||
smp_mb();
|
||||
@ -395,8 +396,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
||||
*/
|
||||
jbd2_journal_update_sb_log_tail(journal,
|
||||
journal->j_tail_sequence,
|
||||
journal->j_tail,
|
||||
REQ_SYNC);
|
||||
journal->j_tail, 0);
|
||||
mutex_unlock(&journal->j_checkpoint_mutex);
|
||||
} else {
|
||||
jbd2_debug(3, "superblock not updated\n");
|
||||
@ -715,6 +715,7 @@ start_journal_io:
|
||||
|
||||
for (i = 0; i < bufs; i++) {
|
||||
struct buffer_head *bh = wbuf[i];
|
||||
|
||||
/*
|
||||
* Compute checksum.
|
||||
*/
|
||||
@ -727,7 +728,8 @@ start_journal_io:
|
||||
clear_buffer_dirty(bh);
|
||||
set_buffer_uptodate(bh);
|
||||
bh->b_end_io = journal_end_buffer_io_sync;
|
||||
submit_bh(REQ_OP_WRITE | REQ_SYNC, bh);
|
||||
submit_bh(REQ_OP_WRITE | JBD2_JOURNAL_REQ_FLAGS,
|
||||
bh);
|
||||
}
|
||||
cond_resched();
|
||||
|
||||
|
@ -1100,8 +1100,7 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
|
||||
* space and if we lose sb update during power failure we'd replay
|
||||
* old transaction with possibly newly overwritten data.
|
||||
*/
|
||||
ret = jbd2_journal_update_sb_log_tail(journal, tid, block,
|
||||
REQ_SYNC | REQ_FUA);
|
||||
ret = jbd2_journal_update_sb_log_tail(journal, tid, block, REQ_FUA);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -1775,8 +1774,7 @@ static int journal_reset(journal_t *journal)
|
||||
*/
|
||||
jbd2_journal_update_sb_log_tail(journal,
|
||||
journal->j_tail_sequence,
|
||||
journal->j_tail,
|
||||
REQ_SYNC | REQ_FUA);
|
||||
journal->j_tail, REQ_FUA);
|
||||
mutex_unlock(&journal->j_checkpoint_mutex);
|
||||
}
|
||||
return jbd2_journal_start_thread(journal);
|
||||
@ -1798,9 +1796,16 @@ static int jbd2_write_superblock(journal_t *journal, blk_opf_t write_flags)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
trace_jbd2_write_superblock(journal, write_flags);
|
||||
/*
|
||||
* Always set high priority flags to exempt from block layer's
|
||||
* QOS policies, e.g. writeback throttle.
|
||||
*/
|
||||
write_flags |= JBD2_JOURNAL_REQ_FLAGS;
|
||||
if (!(journal->j_flags & JBD2_BARRIER))
|
||||
write_flags &= ~(REQ_FUA | REQ_PREFLUSH);
|
||||
|
||||
trace_jbd2_write_superblock(journal, write_flags);
|
||||
|
||||
if (buffer_write_io_error(bh)) {
|
||||
/*
|
||||
* Oh, dear. A previous attempt to write the journal
|
||||
@ -2050,7 +2055,7 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
|
||||
jbd2_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
|
||||
sb->s_errno = cpu_to_be32(errcode);
|
||||
|
||||
jbd2_write_superblock(journal, REQ_SYNC | REQ_FUA);
|
||||
jbd2_write_superblock(journal, REQ_FUA);
|
||||
}
|
||||
EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
|
||||
|
||||
@ -2171,8 +2176,7 @@ int jbd2_journal_destroy(journal_t *journal)
|
||||
++journal->j_transaction_sequence;
|
||||
write_unlock(&journal->j_state_lock);
|
||||
|
||||
jbd2_mark_journal_empty(journal,
|
||||
REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
|
||||
jbd2_mark_journal_empty(journal, REQ_PREFLUSH | REQ_FUA);
|
||||
mutex_unlock(&journal->j_checkpoint_mutex);
|
||||
} else
|
||||
err = -EIO;
|
||||
@ -2473,7 +2477,7 @@ int jbd2_journal_flush(journal_t *journal, unsigned int flags)
|
||||
* the magic code for a fully-recovered superblock. Any future
|
||||
* commits of data to the journal will restore the current
|
||||
* s_start value. */
|
||||
jbd2_mark_journal_empty(journal, REQ_SYNC | REQ_FUA);
|
||||
jbd2_mark_journal_empty(journal, REQ_FUA);
|
||||
|
||||
if (flags)
|
||||
err = __jbd2_journal_erase(journal, flags);
|
||||
@ -2519,7 +2523,7 @@ int jbd2_journal_wipe(journal_t *journal, int write)
|
||||
if (write) {
|
||||
/* Lock to make assertions happy... */
|
||||
mutex_lock_io(&journal->j_checkpoint_mutex);
|
||||
jbd2_mark_journal_empty(journal, REQ_SYNC | REQ_FUA);
|
||||
jbd2_mark_journal_empty(journal, REQ_FUA);
|
||||
mutex_unlock(&journal->j_checkpoint_mutex);
|
||||
}
|
||||
|
||||
|
@ -1374,6 +1374,9 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2)
|
||||
JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3)
|
||||
JBD2_FEATURE_INCOMPAT_FUNCS(fast_commit, FAST_COMMIT)
|
||||
|
||||
/* Journal high priority write IO operation flags */
|
||||
#define JBD2_JOURNAL_REQ_FLAGS (REQ_META | REQ_SYNC | REQ_IDLE)
|
||||
|
||||
/*
|
||||
* Journal flag definitions
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user