Commit fdbf69a7 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jaegeuk Kim

f2fs: refactor the hole reporting and allocation logic in f2fs_map_blocks

Add a is_hole local variable to figure out if the block number might need
allocation, and untangle to logic to report the hole or fill it with a
block allocation.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 817c968b
...@@ -1547,6 +1547,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) ...@@ -1547,6 +1547,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag)
block_t blkaddr; block_t blkaddr;
unsigned int start_pgofs; unsigned int start_pgofs;
int bidx = 0; int bidx = 0;
bool is_hole;
if (!maxblocks) if (!maxblocks)
return 0; return 0;
...@@ -1587,78 +1588,76 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) ...@@ -1587,78 +1588,76 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag)
next_block: next_block:
blkaddr = f2fs_data_blkaddr(&dn); blkaddr = f2fs_data_blkaddr(&dn);
is_hole = !__is_valid_data_blkaddr(blkaddr);
if (__is_valid_data_blkaddr(blkaddr) && if (!is_hole &&
!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) { !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
err = -EFSCORRUPTED; err = -EFSCORRUPTED;
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
goto sync_out; goto sync_out;
} }
if (__is_valid_data_blkaddr(blkaddr)) { /* use out-place-update for direct IO under LFS mode */
/* use out-place-update for driect IO under LFS mode */ if (map->m_may_create &&
if (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO && (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
map->m_may_create) { if (unlikely(f2fs_cp_error(sbi))) {
err = -EIO;
goto sync_out;
}
switch (flag) {
case F2FS_GET_BLOCK_PRE_AIO:
if (blkaddr == NULL_ADDR) {
prealloc++;
last_ofs_in_node = dn.ofs_in_node;
}
break;
case F2FS_GET_BLOCK_PRE_DIO:
case F2FS_GET_BLOCK_DIO:
err = __allocate_data_block(&dn, map->m_seg_type); err = __allocate_data_block(&dn, map->m_seg_type);
if (err) if (err)
goto sync_out; goto sync_out;
blkaddr = dn.data_blkaddr; if (flag == F2FS_GET_BLOCK_PRE_DIO)
file_need_truncate(inode);
set_inode_flag(inode, FI_APPEND_WRITE); set_inode_flag(inode, FI_APPEND_WRITE);
break;
default:
WARN_ON_ONCE(1);
err = -EIO;
goto sync_out;
} }
} else {
if (map->m_may_create) { blkaddr = dn.data_blkaddr;
if (unlikely(f2fs_cp_error(sbi))) { if (is_hole)
err = -EIO;
goto sync_out;
}
if (flag == F2FS_GET_BLOCK_PRE_AIO) {
if (blkaddr == NULL_ADDR) {
prealloc++;
last_ofs_in_node = dn.ofs_in_node;
}
} else {
WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO &&
flag != F2FS_GET_BLOCK_DIO);
err = __allocate_data_block(&dn,
map->m_seg_type);
if (!err) {
if (flag == F2FS_GET_BLOCK_PRE_DIO)
file_need_truncate(inode);
set_inode_flag(inode, FI_APPEND_WRITE);
}
}
if (err)
goto sync_out;
map->m_flags |= F2FS_MAP_NEW; map->m_flags |= F2FS_MAP_NEW;
blkaddr = dn.data_blkaddr; } else if (is_hole) {
} else { if (f2fs_compressed_file(inode) &&
if (f2fs_compressed_file(inode) && f2fs_sanity_check_cluster(&dn) &&
f2fs_sanity_check_cluster(&dn) && (flag != F2FS_GET_BLOCK_FIEMAP ||
(flag != F2FS_GET_BLOCK_FIEMAP || IS_ENABLED(CONFIG_F2FS_CHECK_FS))) {
IS_ENABLED(CONFIG_F2FS_CHECK_FS))) { err = -EFSCORRUPTED;
err = -EFSCORRUPTED; f2fs_handle_error(sbi,
f2fs_handle_error(sbi, ERROR_CORRUPTED_CLUSTER);
ERROR_CORRUPTED_CLUSTER); goto sync_out;
goto sync_out; }
}
if (flag == F2FS_GET_BLOCK_BMAP) { switch (flag) {
map->m_pblk = 0; case F2FS_GET_BLOCK_PRECACHE:
goto sync_out; goto sync_out;
} case F2FS_GET_BLOCK_BMAP:
if (flag == F2FS_GET_BLOCK_PRECACHE) map->m_pblk = 0;
goto sync_out; goto sync_out;
if (flag == F2FS_GET_BLOCK_FIEMAP && case F2FS_GET_BLOCK_FIEMAP:
blkaddr == NULL_ADDR) { if (blkaddr == NULL_ADDR) {
if (map->m_next_pgofs)
*map->m_next_pgofs = pgofs + 1;
goto sync_out;
}
if (flag != F2FS_GET_BLOCK_FIEMAP) {
/* for defragment case */
if (map->m_next_pgofs) if (map->m_next_pgofs)
*map->m_next_pgofs = pgofs + 1; *map->m_next_pgofs = pgofs + 1;
goto sync_out; goto sync_out;
} }
break;
default:
/* for defragment case */
if (map->m_next_pgofs)
*map->m_next_pgofs = pgofs + 1;
goto sync_out;
} }
} }
......
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