Commit cf52eed7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -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);
}
+4 −0
Original line number Diff line number Diff line
@@ -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;
+6 −4
Original line number Diff line number Diff line
@@ -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 @@ void jbd2_journal_commit_transaction(journal_t *journal)

			for (i = 0; i < bufs; i++) {
				struct buffer_head *bh = wbuf[i];

				/*
				 * Compute checksum.
				 */
@@ -727,7 +728,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
				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();

+14 −10
Original line number Diff line number Diff line
@@ -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);
	}

+3 −0
Original line number Diff line number Diff line
@@ -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
 */