Commit cf52eed7 authored by Linus Torvalds's avatar Linus Torvalds

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
parents eaadbbaa 6c02757c
...@@ -349,9 +349,10 @@ static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count) ...@@ -349,9 +349,10 @@ static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
return; return;
} }
/* /*
* If i_disksize got extended due to writeback of delalloc blocks while * If i_disksize got extended either due to writeback of delalloc
* the DIO was running we could fail to cleanup the orphan list in * blocks or extending truncate while the DIO was running we could fail
* ext4_handle_inode_extension(). Do it now. * to cleanup the orphan list in ext4_handle_inode_extension(). Do it
* now.
*/ */
if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) { if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); 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, ...@@ -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 * blocks. But the code in ext4_iomap_alloc() is careful to use
* zeroed/unwritten extents if this is possible; thus we won't leave * 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 * 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 size;
return ext4_handle_inode_extension(inode, pos, size); return ext4_handle_inode_extension(inode, pos, size);
} }
......
...@@ -4478,6 +4478,10 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, ...@@ -4478,6 +4478,10 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
start = max(start, rounddown(ac->ac_o_ex.fe_logical, start = max(start, rounddown(ac->ac_o_ex.fe_logical,
(ext4_lblk_t)EXT4_BLOCKS_PER_GROUP(ac->ac_sb))); (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 */ /* don't cover already allocated blocks in selected range */
if (ar->pleft && start <= ar->lleft) { if (ar->pleft && start <= ar->lleft) {
size -= ar->lleft + 1 - start; size -= ar->lleft + 1 - start;
......
...@@ -119,7 +119,7 @@ static int journal_submit_commit_record(journal_t *journal, ...@@ -119,7 +119,7 @@ static int journal_submit_commit_record(journal_t *journal,
struct commit_header *tmp; struct commit_header *tmp;
struct buffer_head *bh; struct buffer_head *bh;
struct timespec64 now; 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; *cbh = NULL;
...@@ -270,6 +270,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal, ...@@ -270,6 +270,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
if (!ret) if (!ret)
ret = err; ret = err;
} }
cond_resched();
spin_lock(&journal->j_list_lock); spin_lock(&journal->j_list_lock);
jinode->i_flags &= ~JI_COMMIT_RUNNING; jinode->i_flags &= ~JI_COMMIT_RUNNING;
smp_mb(); smp_mb();
...@@ -395,8 +396,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) ...@@ -395,8 +396,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
*/ */
jbd2_journal_update_sb_log_tail(journal, jbd2_journal_update_sb_log_tail(journal,
journal->j_tail_sequence, journal->j_tail_sequence,
journal->j_tail, journal->j_tail, 0);
REQ_SYNC);
mutex_unlock(&journal->j_checkpoint_mutex); mutex_unlock(&journal->j_checkpoint_mutex);
} else { } else {
jbd2_debug(3, "superblock not updated\n"); jbd2_debug(3, "superblock not updated\n");
...@@ -715,6 +715,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) ...@@ -715,6 +715,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
for (i = 0; i < bufs; i++) { for (i = 0; i < bufs; i++) {
struct buffer_head *bh = wbuf[i]; struct buffer_head *bh = wbuf[i];
/* /*
* Compute checksum. * Compute checksum.
*/ */
...@@ -727,7 +728,8 @@ void jbd2_journal_commit_transaction(journal_t *journal) ...@@ -727,7 +728,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
clear_buffer_dirty(bh); clear_buffer_dirty(bh);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
bh->b_end_io = journal_end_buffer_io_sync; 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(); cond_resched();
......
...@@ -1100,8 +1100,7 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) ...@@ -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 * space and if we lose sb update during power failure we'd replay
* old transaction with possibly newly overwritten data. * old transaction with possibly newly overwritten data.
*/ */
ret = jbd2_journal_update_sb_log_tail(journal, tid, block, ret = jbd2_journal_update_sb_log_tail(journal, tid, block, REQ_FUA);
REQ_SYNC | REQ_FUA);
if (ret) if (ret)
goto out; goto out;
...@@ -1775,8 +1774,7 @@ static int journal_reset(journal_t *journal) ...@@ -1775,8 +1774,7 @@ static int journal_reset(journal_t *journal)
*/ */
jbd2_journal_update_sb_log_tail(journal, jbd2_journal_update_sb_log_tail(journal,
journal->j_tail_sequence, journal->j_tail_sequence,
journal->j_tail, journal->j_tail, REQ_FUA);
REQ_SYNC | REQ_FUA);
mutex_unlock(&journal->j_checkpoint_mutex); mutex_unlock(&journal->j_checkpoint_mutex);
} }
return jbd2_journal_start_thread(journal); return jbd2_journal_start_thread(journal);
...@@ -1798,9 +1796,16 @@ static int jbd2_write_superblock(journal_t *journal, blk_opf_t write_flags) ...@@ -1798,9 +1796,16 @@ static int jbd2_write_superblock(journal_t *journal, blk_opf_t write_flags)
return -EIO; 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)) if (!(journal->j_flags & JBD2_BARRIER))
write_flags &= ~(REQ_FUA | REQ_PREFLUSH); write_flags &= ~(REQ_FUA | REQ_PREFLUSH);
trace_jbd2_write_superblock(journal, write_flags);
if (buffer_write_io_error(bh)) { if (buffer_write_io_error(bh)) {
/* /*
* Oh, dear. A previous attempt to write the journal * Oh, dear. A previous attempt to write the journal
...@@ -2050,7 +2055,7 @@ void jbd2_journal_update_sb_errno(journal_t *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); jbd2_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
sb->s_errno = cpu_to_be32(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); EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
...@@ -2171,8 +2176,7 @@ int jbd2_journal_destroy(journal_t *journal) ...@@ -2171,8 +2176,7 @@ int jbd2_journal_destroy(journal_t *journal)
++journal->j_transaction_sequence; ++journal->j_transaction_sequence;
write_unlock(&journal->j_state_lock); write_unlock(&journal->j_state_lock);
jbd2_mark_journal_empty(journal, jbd2_mark_journal_empty(journal, REQ_PREFLUSH | REQ_FUA);
REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
mutex_unlock(&journal->j_checkpoint_mutex); mutex_unlock(&journal->j_checkpoint_mutex);
} else } else
err = -EIO; err = -EIO;
...@@ -2473,7 +2477,7 @@ int jbd2_journal_flush(journal_t *journal, unsigned int flags) ...@@ -2473,7 +2477,7 @@ int jbd2_journal_flush(journal_t *journal, unsigned int flags)
* the magic code for a fully-recovered superblock. Any future * the magic code for a fully-recovered superblock. Any future
* commits of data to the journal will restore the current * commits of data to the journal will restore the current
* s_start value. */ * s_start value. */
jbd2_mark_journal_empty(journal, REQ_SYNC | REQ_FUA); jbd2_mark_journal_empty(journal, REQ_FUA);
if (flags) if (flags)
err = __jbd2_journal_erase(journal, flags); err = __jbd2_journal_erase(journal, flags);
...@@ -2519,7 +2523,7 @@ int jbd2_journal_wipe(journal_t *journal, int write) ...@@ -2519,7 +2523,7 @@ int jbd2_journal_wipe(journal_t *journal, int write)
if (write) { if (write) {
/* Lock to make assertions happy... */ /* Lock to make assertions happy... */
mutex_lock_io(&journal->j_checkpoint_mutex); 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); mutex_unlock(&journal->j_checkpoint_mutex);
} }
......
...@@ -1374,6 +1374,9 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2) ...@@ -1374,6 +1374,9 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2)
JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3) JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3)
JBD2_FEATURE_INCOMPAT_FUNCS(fast_commit, FAST_COMMIT) 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 * Journal flag definitions
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment