1 ext4: move trans handling and completion deferal out of _ext4_get_block
3 From: Jan Kara <jack@suse.cz>
5 There is no need to handle starting of a transaction and deferal of DIO
6 completion in _ext4_get_block() function. We can move this out to get
7 block functions for direct IO that need it. That way we can add stricter
8 checks verifying things work as we expect.
10 Signed-off-by: Jan Kara <jack@suse.cz>
11 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 fs/ext4/inode.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
14 1 file changed, 59 insertions(+), 32 deletions(-)
16 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
17 index bf545d0..aea67d9 100644
20 @@ -714,16 +714,11 @@ static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags)
21 cmpxchg(&bh->b_state, old_state, new_state) != old_state));
24 -/* Maximum number of blocks we map for direct IO at once. */
25 -#define DIO_MAX_BLOCKS 4096
27 static int _ext4_get_block(struct inode *inode, sector_t iblock,
28 struct buffer_head *bh, int flags)
30 - handle_t *handle = ext4_journal_current_handle();
31 struct ext4_map_blocks map;
32 - int ret = 0, started = 0;
36 if (ext4_has_inline_data(inode))
38 @@ -731,33 +726,14 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,
40 map.m_len = bh->b_size >> inode->i_blkbits;
42 - if (flags && !handle) {
43 - /* Direct IO write... */
44 - if (map.m_len > DIO_MAX_BLOCKS)
45 - map.m_len = DIO_MAX_BLOCKS;
46 - dio_credits = ext4_chunk_trans_blocks(inode, map.m_len);
47 - handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
49 - if (IS_ERR(handle)) {
50 - ret = PTR_ERR(handle);
56 - ret = ext4_map_blocks(handle, inode, &map, flags);
57 + ret = ext4_map_blocks(ext4_journal_current_handle(), inode, &map,
60 - ext4_io_end_t *io_end = ext4_inode_aio(inode);
62 map_bh(bh, inode->i_sb, map.m_pblk);
63 ext4_update_bh_state(bh, map.m_flags);
64 - if (io_end && io_end->flag & EXT4_IO_END_UNWRITTEN)
65 - set_buffer_defer_completion(bh);
66 bh->b_size = inode->i_sb->s_blocksize * map.m_len;
70 - ext4_journal_stop(handle);
74 @@ -782,12 +758,42 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
75 EXT4_GET_BLOCKS_IO_CREATE_EXT);
78 +/* Maximum number of blocks we map for direct IO at once. */
79 +#define DIO_MAX_BLOCKS 4096
81 +static handle_t *start_dio_trans(struct inode *inode,
82 + struct buffer_head *bh_result)
86 + /* Trim mapping request to maximum we can map at once for DIO */
87 + if (bh_result->b_size >> inode->i_blkbits > DIO_MAX_BLOCKS)
88 + bh_result->b_size = DIO_MAX_BLOCKS << inode->i_blkbits;
89 + dio_credits = ext4_chunk_trans_blocks(inode,
90 + bh_result->b_size >> inode->i_blkbits);
91 + return ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
94 /* Get block function for DIO reads and writes to inodes without extents */
95 int ext4_dio_get_block(struct inode *inode, sector_t iblock,
96 struct buffer_head *bh, int create)
98 - return _ext4_get_block(inode, iblock, bh,
99 - create ? EXT4_GET_BLOCKS_CREATE : 0);
103 + /* We don't expect handle for direct IO */
104 + WARN_ON_ONCE(ext4_journal_current_handle());
107 + handle = start_dio_trans(inode, bh);
108 + if (IS_ERR(handle))
109 + return PTR_ERR(handle);
111 + ret = _ext4_get_block(inode, iblock, bh,
112 + create ? EXT4_GET_BLOCKS_CREATE : 0);
114 + ext4_journal_stop(handle);
119 @@ -798,10 +804,28 @@ int ext4_dio_get_block(struct inode *inode, sector_t iblock,
120 static int ext4_dio_get_block_unwritten(struct inode *inode, sector_t iblock,
121 struct buffer_head *bh_result, int create)
126 ext4_debug("ext4_dio_get_block_unwritten: inode %lu, create flag %d\n",
127 inode->i_ino, create);
128 - return _ext4_get_block(inode, iblock, bh_result,
129 - EXT4_GET_BLOCKS_IO_CREATE_EXT);
130 + /* We don't expect handle for direct IO */
131 + WARN_ON_ONCE(ext4_journal_current_handle());
133 + handle = start_dio_trans(inode, bh_result);
134 + if (IS_ERR(handle))
135 + return PTR_ERR(handle);
136 + ret = _ext4_get_block(inode, iblock, bh_result,
137 + EXT4_GET_BLOCKS_IO_CREATE_EXT);
138 + ext4_journal_stop(handle);
139 + if (!ret && buffer_unwritten(bh_result)) {
140 + ext4_io_end_t *io_end = ext4_inode_aio(inode);
142 + set_buffer_defer_completion(bh_result);
143 + WARN_ON_ONCE(io_end && !(io_end->flag & EXT4_IO_END_UNWRITTEN));
149 static int ext4_dio_get_block_overwrite(struct inode *inode, sector_t iblock,
150 @@ -811,12 +835,15 @@ static int ext4_dio_get_block_overwrite(struct inode *inode, sector_t iblock,
152 ext4_debug("ext4_dio_get_block_overwrite: inode %lu, create flag %d\n",
153 inode->i_ino, create);
154 + /* We don't expect handle for direct IO */
155 + WARN_ON_ONCE(ext4_journal_current_handle());
157 ret = _ext4_get_block(inode, iblock, bh_result, 0);
159 * Blocks should have been preallocated! ext4_file_write_iter() checks
162 - WARN_ON_ONCE(!buffer_mapped(bh_result));
163 + WARN_ON_ONCE(!buffer_mapped(bh_result) || buffer_unwritten(bh_result));