Skip to content

Commit efe70c2

Browse files
jankaratytso
authored andcommitted
ext4: move trans handling and completion deferal out of _ext4_get_block
There is no need to handle starting of a transaction and deferal of DIO completion in _ext4_get_block() function. We can move this out to get block functions for direct IO that need it. That way we can add stricter checks verifying things work as we expect. Signed-off-by: Jan Kara <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 705965b commit efe70c2

File tree

1 file changed

+59
-32
lines changed

1 file changed

+59
-32
lines changed

fs/ext4/inode.c

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -714,50 +714,26 @@ static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags)
714714
cmpxchg(&bh->b_state, old_state, new_state) != old_state));
715715
}
716716

717-
/* Maximum number of blocks we map for direct IO at once. */
718-
#define DIO_MAX_BLOCKS 4096
719-
720717
static int _ext4_get_block(struct inode *inode, sector_t iblock,
721718
struct buffer_head *bh, int flags)
722719
{
723-
handle_t *handle = ext4_journal_current_handle();
724720
struct ext4_map_blocks map;
725-
int ret = 0, started = 0;
726-
int dio_credits;
721+
int ret = 0;
727722

728723
if (ext4_has_inline_data(inode))
729724
return -ERANGE;
730725

731726
map.m_lblk = iblock;
732727
map.m_len = bh->b_size >> inode->i_blkbits;
733728

734-
if (flags && !handle) {
735-
/* Direct IO write... */
736-
if (map.m_len > DIO_MAX_BLOCKS)
737-
map.m_len = DIO_MAX_BLOCKS;
738-
dio_credits = ext4_chunk_trans_blocks(inode, map.m_len);
739-
handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
740-
dio_credits);
741-
if (IS_ERR(handle)) {
742-
ret = PTR_ERR(handle);
743-
return ret;
744-
}
745-
started = 1;
746-
}
747-
748-
ret = ext4_map_blocks(handle, inode, &map, flags);
729+
ret = ext4_map_blocks(ext4_journal_current_handle(), inode, &map,
730+
flags);
749731
if (ret > 0) {
750-
ext4_io_end_t *io_end = ext4_inode_aio(inode);
751-
752732
map_bh(bh, inode->i_sb, map.m_pblk);
753733
ext4_update_bh_state(bh, map.m_flags);
754-
if (io_end && io_end->flag & EXT4_IO_END_UNWRITTEN)
755-
set_buffer_defer_completion(bh);
756734
bh->b_size = inode->i_sb->s_blocksize * map.m_len;
757735
ret = 0;
758736
}
759-
if (started)
760-
ext4_journal_stop(handle);
761737
return ret;
762738
}
763739

@@ -782,12 +758,42 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
782758
EXT4_GET_BLOCKS_IO_CREATE_EXT);
783759
}
784760

761+
/* Maximum number of blocks we map for direct IO at once. */
762+
#define DIO_MAX_BLOCKS 4096
763+
764+
static handle_t *start_dio_trans(struct inode *inode,
765+
struct buffer_head *bh_result)
766+
{
767+
int dio_credits;
768+
769+
/* Trim mapping request to maximum we can map at once for DIO */
770+
if (bh_result->b_size >> inode->i_blkbits > DIO_MAX_BLOCKS)
771+
bh_result->b_size = DIO_MAX_BLOCKS << inode->i_blkbits;
772+
dio_credits = ext4_chunk_trans_blocks(inode,
773+
bh_result->b_size >> inode->i_blkbits);
774+
return ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
775+
}
776+
785777
/* Get block function for DIO reads and writes to inodes without extents */
786778
int ext4_dio_get_block(struct inode *inode, sector_t iblock,
787779
struct buffer_head *bh, int create)
788780
{
789-
return _ext4_get_block(inode, iblock, bh,
790-
create ? EXT4_GET_BLOCKS_CREATE : 0);
781+
handle_t *handle;
782+
int ret;
783+
784+
/* We don't expect handle for direct IO */
785+
WARN_ON_ONCE(ext4_journal_current_handle());
786+
787+
if (create) {
788+
handle = start_dio_trans(inode, bh);
789+
if (IS_ERR(handle))
790+
return PTR_ERR(handle);
791+
}
792+
ret = _ext4_get_block(inode, iblock, bh,
793+
create ? EXT4_GET_BLOCKS_CREATE : 0);
794+
if (create)
795+
ext4_journal_stop(handle);
796+
return ret;
791797
}
792798

793799
/*
@@ -798,10 +804,28 @@ int ext4_dio_get_block(struct inode *inode, sector_t iblock,
798804
static int ext4_dio_get_block_unwritten(struct inode *inode, sector_t iblock,
799805
struct buffer_head *bh_result, int create)
800806
{
807+
handle_t *handle;
808+
int ret;
809+
801810
ext4_debug("ext4_dio_get_block_unwritten: inode %lu, create flag %d\n",
802811
inode->i_ino, create);
803-
return _ext4_get_block(inode, iblock, bh_result,
804-
EXT4_GET_BLOCKS_IO_CREATE_EXT);
812+
/* We don't expect handle for direct IO */
813+
WARN_ON_ONCE(ext4_journal_current_handle());
814+
815+
handle = start_dio_trans(inode, bh_result);
816+
if (IS_ERR(handle))
817+
return PTR_ERR(handle);
818+
ret = _ext4_get_block(inode, iblock, bh_result,
819+
EXT4_GET_BLOCKS_IO_CREATE_EXT);
820+
ext4_journal_stop(handle);
821+
if (!ret && buffer_unwritten(bh_result)) {
822+
ext4_io_end_t *io_end = ext4_inode_aio(inode);
823+
824+
set_buffer_defer_completion(bh_result);
825+
WARN_ON_ONCE(io_end && !(io_end->flag & EXT4_IO_END_UNWRITTEN));
826+
}
827+
828+
return ret;
805829
}
806830

807831
static int ext4_dio_get_block_overwrite(struct inode *inode, sector_t iblock,
@@ -811,12 +835,15 @@ static int ext4_dio_get_block_overwrite(struct inode *inode, sector_t iblock,
811835

812836
ext4_debug("ext4_dio_get_block_overwrite: inode %lu, create flag %d\n",
813837
inode->i_ino, create);
838+
/* We don't expect handle for direct IO */
839+
WARN_ON_ONCE(ext4_journal_current_handle());
840+
814841
ret = _ext4_get_block(inode, iblock, bh_result, 0);
815842
/*
816843
* Blocks should have been preallocated! ext4_file_write_iter() checks
817844
* that.
818845
*/
819-
WARN_ON_ONCE(!buffer_mapped(bh_result));
846+
WARN_ON_ONCE(!buffer_mapped(bh_result) || buffer_unwritten(bh_result));
820847

821848
return ret;
822849
}

0 commit comments

Comments
 (0)