Commit 2dcba478 authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o

ext4: get rid of EXT4_GET_BLOCKS_NO_LOCK flag

When dioread_nolock mode is enabled, we grab i_data_sem in
ext4_ext_direct_IO() and therefore we need to instruct _ext4_get_block()
not to grab i_data_sem again using EXT4_GET_BLOCKS_NO_LOCK. However
holding i_data_sem over overwrite direct IO isn't needed these days. We
have exclusion against truncate / hole punching because we increase
i_dio_count under i_mutex in ext4_ext_direct_IO() so once
ext4_file_write_iter() verifies blocks are allocated & written, they are
guaranteed to stay so during the whole direct IO even after we drop
i_mutex.

So we can just remove this locking abuse and the no longer necessary
EXT4_GET_BLOCKS_NO_LOCK flag.
Signed-off-by: default avatarJan Kara <jack@suse.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent e74031fd
...@@ -555,10 +555,8 @@ enum { ...@@ -555,10 +555,8 @@ enum {
#define EXT4_GET_BLOCKS_NO_NORMALIZE 0x0040 #define EXT4_GET_BLOCKS_NO_NORMALIZE 0x0040
/* Request will not result in inode size update (user for fallocate) */ /* Request will not result in inode size update (user for fallocate) */
#define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080 #define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080
/* Do not take i_data_sem locking in ext4_map_blocks */
#define EXT4_GET_BLOCKS_NO_LOCK 0x0100
/* Convert written extents to unwritten */ /* Convert written extents to unwritten */
#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0200 #define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0100
/* /*
* The bit position of these flags must not overlap with any of the * The bit position of these flags must not overlap with any of the
......
...@@ -403,8 +403,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle, ...@@ -403,8 +403,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
* out taking i_data_sem. So at the time the unwritten extent * out taking i_data_sem. So at the time the unwritten extent
* could be converted. * could be converted.
*/ */
if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) down_read(&EXT4_I(inode)->i_data_sem);
down_read(&EXT4_I(inode)->i_data_sem);
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
retval = ext4_ext_map_blocks(handle, inode, map, flags & retval = ext4_ext_map_blocks(handle, inode, map, flags &
EXT4_GET_BLOCKS_KEEP_SIZE); EXT4_GET_BLOCKS_KEEP_SIZE);
...@@ -412,8 +411,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle, ...@@ -412,8 +411,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
retval = ext4_ind_map_blocks(handle, inode, map, flags & retval = ext4_ind_map_blocks(handle, inode, map, flags &
EXT4_GET_BLOCKS_KEEP_SIZE); EXT4_GET_BLOCKS_KEEP_SIZE);
} }
if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) up_read((&EXT4_I(inode)->i_data_sem));
up_read((&EXT4_I(inode)->i_data_sem));
/* /*
* We don't check m_len because extent will be collpased in status * We don't check m_len because extent will be collpased in status
...@@ -509,8 +507,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, ...@@ -509,8 +507,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
* Try to see if we can get the block without requesting a new * Try to see if we can get the block without requesting a new
* file system block. * file system block.
*/ */
if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) down_read(&EXT4_I(inode)->i_data_sem);
down_read(&EXT4_I(inode)->i_data_sem);
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
retval = ext4_ext_map_blocks(handle, inode, map, flags & retval = ext4_ext_map_blocks(handle, inode, map, flags &
EXT4_GET_BLOCKS_KEEP_SIZE); EXT4_GET_BLOCKS_KEEP_SIZE);
...@@ -541,8 +538,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, ...@@ -541,8 +538,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
if (ret < 0) if (ret < 0)
retval = ret; retval = ret;
} }
if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) up_read((&EXT4_I(inode)->i_data_sem));
up_read((&EXT4_I(inode)->i_data_sem));
found: found:
if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
...@@ -674,7 +670,7 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock, ...@@ -674,7 +670,7 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,
map.m_lblk = iblock; map.m_lblk = iblock;
map.m_len = bh->b_size >> inode->i_blkbits; map.m_len = bh->b_size >> inode->i_blkbits;
if (flags && !(flags & EXT4_GET_BLOCKS_NO_LOCK) && !handle) { if (flags && !handle) {
/* Direct IO write... */ /* Direct IO write... */
if (map.m_len > DIO_MAX_BLOCKS) if (map.m_len > DIO_MAX_BLOCKS)
map.m_len = DIO_MAX_BLOCKS; map.m_len = DIO_MAX_BLOCKS;
...@@ -879,9 +875,6 @@ int do_journal_get_write_access(handle_t *handle, ...@@ -879,9 +875,6 @@ int do_journal_get_write_access(handle_t *handle,
return ret; return ret;
} }
static int ext4_get_block_write_nolock(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create);
#ifdef CONFIG_EXT4_FS_ENCRYPTION #ifdef CONFIG_EXT4_FS_ENCRYPTION
static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
get_block_t *get_block) get_block_t *get_block)
...@@ -3054,13 +3047,21 @@ int ext4_get_block_write(struct inode *inode, sector_t iblock, ...@@ -3054,13 +3047,21 @@ int ext4_get_block_write(struct inode *inode, sector_t iblock,
EXT4_GET_BLOCKS_IO_CREATE_EXT); EXT4_GET_BLOCKS_IO_CREATE_EXT);
} }
static int ext4_get_block_write_nolock(struct inode *inode, sector_t iblock, static int ext4_get_block_overwrite(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create) struct buffer_head *bh_result, int create)
{ {
ext4_debug("ext4_get_block_write_nolock: inode %lu, create flag %d\n", int ret;
ext4_debug("ext4_get_block_overwrite: inode %lu, create flag %d\n",
inode->i_ino, create); inode->i_ino, create);
return _ext4_get_block(inode, iblock, bh_result, ret = _ext4_get_block(inode, iblock, bh_result, 0);
EXT4_GET_BLOCKS_NO_LOCK); /*
* Blocks should have been preallocated! ext4_file_write_iter() checks
* that.
*/
WARN_ON_ONCE(!buffer_mapped(bh_result));
return ret;
} }
int ext4_get_block_dax(struct inode *inode, sector_t iblock, int ext4_get_block_dax(struct inode *inode, sector_t iblock,
...@@ -3143,10 +3144,8 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter, ...@@ -3143,10 +3144,8 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
/* If we do a overwrite dio, i_mutex locking can be released */ /* If we do a overwrite dio, i_mutex locking can be released */
overwrite = *((int *)iocb->private); overwrite = *((int *)iocb->private);
if (overwrite) { if (overwrite)
down_read(&EXT4_I(inode)->i_data_sem);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
}
/* /*
* We could direct write to holes and fallocate. * We could direct write to holes and fallocate.
...@@ -3189,7 +3188,7 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter, ...@@ -3189,7 +3188,7 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
} }
if (overwrite) { if (overwrite) {
get_block_func = ext4_get_block_write_nolock; get_block_func = ext4_get_block_overwrite;
} else { } else {
get_block_func = ext4_get_block_write; get_block_func = ext4_get_block_write;
dio_flags = DIO_LOCKING; dio_flags = DIO_LOCKING;
...@@ -3245,10 +3244,8 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter, ...@@ -3245,10 +3244,8 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
if (iov_iter_rw(iter) == WRITE) if (iov_iter_rw(iter) == WRITE)
inode_dio_end(inode); inode_dio_end(inode);
/* take i_mutex locking again if we do a ovewrite dio */ /* take i_mutex locking again if we do a ovewrite dio */
if (overwrite) { if (overwrite)
up_read(&EXT4_I(inode)->i_data_sem);
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
}
return ret; return ret;
} }
......
...@@ -42,8 +42,7 @@ struct extent_status; ...@@ -42,8 +42,7 @@ struct extent_status;
{ EXT4_GET_BLOCKS_CONVERT, "CONVERT" }, \ { EXT4_GET_BLOCKS_CONVERT, "CONVERT" }, \
{ EXT4_GET_BLOCKS_METADATA_NOFAIL, "METADATA_NOFAIL" }, \ { EXT4_GET_BLOCKS_METADATA_NOFAIL, "METADATA_NOFAIL" }, \
{ EXT4_GET_BLOCKS_NO_NORMALIZE, "NO_NORMALIZE" }, \ { EXT4_GET_BLOCKS_NO_NORMALIZE, "NO_NORMALIZE" }, \
{ EXT4_GET_BLOCKS_KEEP_SIZE, "KEEP_SIZE" }, \ { EXT4_GET_BLOCKS_KEEP_SIZE, "KEEP_SIZE" })
{ EXT4_GET_BLOCKS_NO_LOCK, "NO_LOCK" })
#define show_mflags(flags) __print_flags(flags, "", \ #define show_mflags(flags) __print_flags(flags, "", \
{ EXT4_MAP_NEW, "N" }, \ { EXT4_MAP_NEW, "N" }, \
......
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