Commit c691783a authored by Zhang Yi's avatar Zhang Yi
Browse files

ext4: partial enable iomap for regular file's buffered IO path

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9DN5Z


CVE: NA

--------------------------------

Partial enable iomap for regular file's buffered IO path on default
mount option, support default filesystem features and bigalloc feature,
doesn't support inline data, fs_verity, fs_crypt, defrag and
data=journal mode yet (these would be supported gradually in the
future). ext4 will fallback to buffered_head path automatically if these
options or features are enable.

Signed-off-by: default avatarZhang Yi <yi.zhang@huawei.com>
parent 2a158d54
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2972,6 +2972,7 @@ int ext4_walk_page_buffers(handle_t *handle,
				     struct buffer_head *bh));
int do_journal_get_write_access(handle_t *handle, struct inode *inode,
				struct buffer_head *bh);
bool ext4_should_use_buffered_iomap(struct inode *inode);
int ext4_nonda_switch(struct super_block *sb);
#define FALL_BACK_TO_NONDELALLOC 1
#define CONVERT_INLINE_DATA	 2
+3 −0
Original line number Diff line number Diff line
@@ -1336,6 +1336,9 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,
		}
	}

	if (ext4_should_use_buffered_iomap(inode))
		ext4_set_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP);

	if (ext4_handle_valid(handle)) {
		ei->i_sync_tid = handle->h_transaction->t_tid;
		ei->i_datasync_tid = handle->h_transaction->t_tid;
+32 −0
Original line number Diff line number Diff line
@@ -793,6 +793,8 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,

	if (ext4_has_inline_data(inode))
		return -ERANGE;
	if (WARN_ON(ext4_test_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP)))
		return -EINVAL;

	map.m_lblk = iblock;
	map.m_len = bh->b_size >> inode->i_blkbits;
@@ -2599,6 +2601,9 @@ static int ext4_do_writepages(struct mpage_da_data *mpd)

	trace_ext4_writepages(inode, wbc);

	if (WARN_ON(ext4_test_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP)))
		return -EINVAL;

	/*
	 * No pages to write? This is mainly a kludge to avoid starting
	 * a transaction for special inodes like journal inode on last iput()
@@ -5138,6 +5143,30 @@ static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
	return NULL;
}

bool ext4_should_use_buffered_iomap(struct inode *inode)
{
	struct super_block *sb = inode->i_sb;

	if (ext4_has_feature_inline_data(sb))
		return false;
	if (ext4_has_feature_verity(sb))
		return false;
	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
		return false;
	if (!S_ISREG(inode->i_mode))
		return false;
	if (IS_DAX(inode))
		return false;
	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
		return false;
	if (ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE))
		return false;
	if (ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT))
		return false;

	return true;
}

struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
			  ext4_iget_flags flags, const char *function,
			  unsigned int line)
@@ -5402,6 +5431,9 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
	if (ret)
		goto bad_inode;

	if (ext4_should_use_buffered_iomap(inode))
		ext4_set_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP);

	if (S_ISREG(inode->i_mode)) {
		inode->i_op = &ext4_file_inode_operations;
		inode->i_fop = &ext4_file_operations;