Skip to content

Commit f063db5

Browse files
matthewbobrowskitytso
authored andcommitted
ext4: split IOMAP_WRITE branch in ext4_iomap_begin() into helper
In preparation for porting across the ext4 direct I/O path over to the iomap infrastructure, split up the IOMAP_WRITE branch that's currently within ext4_iomap_begin() into a separate helper ext4_alloc_iomap(). This way, when we add in the necessary code for direct I/O, we don't end up with ext4_iomap_begin() becoming a monstrous twisty maze. Signed-off-by: Matthew Bobrowski <[email protected]> Reviewed-by: Jan Kara <[email protected]> Reviewed-by: Ritesh Harjani <[email protected]> Link: https://lore.kernel.org/r/50eef383add1ea529651640574111076c55aca9f.1572949325.git.mbobrowski@mbobrowski.org Signed-off-by: Theodore Ts'o <[email protected]>
1 parent c8fdfe2 commit f063db5

File tree

1 file changed

+61
-52
lines changed

1 file changed

+61
-52
lines changed

fs/ext4/inode.c

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3493,6 +3493,63 @@ static void ext4_set_iomap(struct inode *inode, struct iomap *iomap,
34933493
}
34943494
}
34953495

3496+
static int ext4_iomap_alloc(struct inode *inode, struct ext4_map_blocks *map,
3497+
unsigned int flags)
3498+
{
3499+
handle_t *handle;
3500+
u8 blkbits = inode->i_blkbits;
3501+
int ret, dio_credits, retries = 0;
3502+
3503+
/*
3504+
* Trim the mapping request to the maximum value that we can map at
3505+
* once for direct I/O.
3506+
*/
3507+
if (map->m_len > DIO_MAX_BLOCKS)
3508+
map->m_len = DIO_MAX_BLOCKS;
3509+
dio_credits = ext4_chunk_trans_blocks(inode, map->m_len);
3510+
3511+
retry:
3512+
/*
3513+
* Either we allocate blocks and then don't get an unwritten extent, so
3514+
* in that case we have reserved enough credits. Or, the blocks are
3515+
* already allocated and unwritten. In that case, the extent conversion
3516+
* fits into the credits as well.
3517+
*/
3518+
handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, dio_credits);
3519+
if (IS_ERR(handle))
3520+
return PTR_ERR(handle);
3521+
3522+
ret = ext4_map_blocks(handle, inode, map, EXT4_GET_BLOCKS_CREATE_ZERO);
3523+
if (ret < 0)
3524+
goto journal_stop;
3525+
3526+
/*
3527+
* If we've allocated blocks beyond EOF, we need to ensure that they're
3528+
* truncated if we crash before updating the inode size metadata within
3529+
* ext4_iomap_end(). For faults, we don't need to do that (and cannot
3530+
* due to orphan list operations needing an inode_lock()). If we happen
3531+
* to instantiate blocks beyond EOF, it is because we race with a
3532+
* truncate operation, which already has added the inode onto the
3533+
* orphan list.
3534+
*/
3535+
if (!(flags & IOMAP_FAULT) && map->m_lblk + map->m_len >
3536+
(i_size_read(inode) + (1 << blkbits) - 1) >> blkbits) {
3537+
int err;
3538+
3539+
err = ext4_orphan_add(handle, inode);
3540+
if (err < 0)
3541+
ret = err;
3542+
}
3543+
3544+
journal_stop:
3545+
ext4_journal_stop(handle);
3546+
if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
3547+
goto retry;
3548+
3549+
return ret;
3550+
}
3551+
3552+
34963553
static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
34973554
unsigned flags, struct iomap *iomap, struct iomap *srcmap)
34983555
{
@@ -3553,62 +3610,14 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
35533610
}
35543611
}
35553612
} else if (flags & IOMAP_WRITE) {
3556-
int dio_credits;
3557-
handle_t *handle;
3558-
int retries = 0;
3559-
3560-
/* Trim mapping request to maximum we can map at once for DIO */
3561-
if (map.m_len > DIO_MAX_BLOCKS)
3562-
map.m_len = DIO_MAX_BLOCKS;
3563-
dio_credits = ext4_chunk_trans_blocks(inode, map.m_len);
3564-
retry:
3565-
/*
3566-
* Either we allocate blocks and then we don't get unwritten
3567-
* extent so we have reserved enough credits, or the blocks
3568-
* are already allocated and unwritten and in that case
3569-
* extent conversion fits in the credits as well.
3570-
*/
3571-
handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
3572-
dio_credits);
3573-
if (IS_ERR(handle))
3574-
return PTR_ERR(handle);
3575-
3576-
ret = ext4_map_blocks(handle, inode, &map,
3577-
EXT4_GET_BLOCKS_CREATE_ZERO);
3578-
if (ret < 0) {
3579-
ext4_journal_stop(handle);
3580-
if (ret == -ENOSPC &&
3581-
ext4_should_retry_alloc(inode->i_sb, &retries))
3582-
goto retry;
3583-
return ret;
3584-
}
3585-
3586-
/*
3587-
* If we added blocks beyond i_size, we need to make sure they
3588-
* will get truncated if we crash before updating i_size in
3589-
* ext4_iomap_end(). For faults we don't need to do that (and
3590-
* even cannot because for orphan list operations inode_lock is
3591-
* required) - if we happen to instantiate block beyond i_size,
3592-
* it is because we race with truncate which has already added
3593-
* the inode to the orphan list.
3594-
*/
3595-
if (!(flags & IOMAP_FAULT) && first_block + map.m_len >
3596-
(i_size_read(inode) + (1 << blkbits) - 1) >> blkbits) {
3597-
int err;
3598-
3599-
err = ext4_orphan_add(handle, inode);
3600-
if (err < 0) {
3601-
ext4_journal_stop(handle);
3602-
return err;
3603-
}
3604-
}
3605-
ext4_journal_stop(handle);
3613+
ret = ext4_iomap_alloc(inode, &map, flags);
36063614
} else {
36073615
ret = ext4_map_blocks(NULL, inode, &map, 0);
3608-
if (ret < 0)
3609-
return ret;
36103616
}
36113617

3618+
if (ret < 0)
3619+
return ret;
3620+
36123621
ext4_set_iomap(inode, iomap, &map, offset, length);
36133622
if (delalloc && iomap->type == IOMAP_HOLE)
36143623
iomap->type = IOMAP_DELALLOC;

0 commit comments

Comments
 (0)