Commit 7871da20 authored by Zhang Yi's avatar Zhang Yi Committed by Theodore Ts'o
Browse files

ext4: introduce ext4_check_map_extents_env() debug helper



Loading and modifying the extents tree and extent status tree without
holding the inode's i_rwsem or the mapping's invalidate_lock is not
permitted, except during the I/O writeback. Add a new debug helper
ext4_check_map_extents_env(), it will verify whether the extent
loading/modifying context is safe.

Signed-off-by: default avatarZhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20250423085257.122685-8-yi.zhang@huaweicloud.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 0b8e0bd4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2978,6 +2978,7 @@ static inline bool ext4_mb_cr_expensive(enum criteria cr)
void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw,
			 struct ext4_inode_info *ei);
int ext4_inode_is_fast_symlink(struct inode *inode);
void ext4_check_map_extents_env(struct inode *inode);
struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
+26 −0
Original line number Diff line number Diff line
@@ -416,6 +416,32 @@ int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
	return ret;
}

/*
 * For generic regular files, when updating the extent tree, Ext4 should
 * hold the i_rwsem and invalidate_lock exclusively. This ensures
 * exclusion against concurrent page faults, as well as reads and writes.
 */
#ifdef CONFIG_EXT4_DEBUG
void ext4_check_map_extents_env(struct inode *inode)
{
	if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
		return;

	if (!S_ISREG(inode->i_mode) ||
	    IS_NOQUOTA(inode) || IS_VERITY(inode) ||
	    is_special_ino(inode->i_sb, inode->i_ino) ||
	    (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) ||
	    ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
	    ext4_verity_in_progress(inode))
		return;

	WARN_ON_ONCE(!inode_is_locked(inode) &&
		     !rwsem_is_locked(&inode->i_mapping->invalidate_lock));
}
#else
void ext4_check_map_extents_env(struct inode *inode) {}
#endif

#define check_block_validity(inode, map)	\
	__check_block_validity((inode), __func__, __LINE__, (map))