From: Youling Tang <tangyoul...@kylinos.cn> Separating bchfs_fallocate() into two functions to handle FALLOC_FL_ALLOCATE_RANGE and FALLOC_FL_ZERO_RANGE respectively makes the code more readable.
Signed-off-by: Youling Tang <tangyoul...@kylinos.cn> --- fs/bcachefs/fs-io.c | 111 ++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 34 deletions(-) diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 69d3ddd4c6a1..430b59c7b7a3 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -627,7 +627,7 @@ static noinline long bchfs_fcollapse_finsert(struct bch_inode_info *inode, return ret; } -static noinline int __bchfs_fallocate(struct bch_inode_info *inode, int mode, +static noinline int bchfs_fallocate(struct bch_inode_info *inode, int mode, u64 start_sector, u64 end_sector) { struct bch_fs *c = inode->v.i_sb->s_fs_info; @@ -757,59 +757,100 @@ static noinline int __bchfs_fallocate(struct bch_inode_info *inode, int mode, return ret; } -static noinline long bchfs_fallocate(struct bch_inode_info *inode, int mode, +static int bchfs_falloc_newsize(struct file *file, int mode, loff_t offset, + loff_t len, loff_t *new_size) +{ + struct inode *inode = file_inode(file); + + if ((mode & FALLOC_FL_KEEP_SIZE) || offset + len <= i_size_read(inode)) + return 0; + *new_size = offset + len; + return inode_newsize_ok(inode, *new_size); +} + +static int bchfs_falloc_setsize(struct bch_fs *c, struct bch_inode_info *inode, + loff_t new_size) +{ + int ret; + + spin_lock(&inode->v.i_lock); + i_size_write(&inode->v, new_size); + spin_unlock(&inode->v.i_lock); + + mutex_lock(&inode->ei_update_lock); + ret = bch2_write_inode_size(c, inode, new_size, 0); + mutex_unlock(&inode->ei_update_lock); + + return ret; +} + +static noinline long bchfs_falloc_allocate_range(struct file *file, int mode, loff_t offset, loff_t len) { + struct bch_inode_info *inode = file_bch_inode(file); struct bch_fs *c = inode->v.i_sb->s_fs_info; u64 end = offset + len; + loff_t new_size = 0; u64 block_start = round_down(offset, block_bytes(c)); u64 block_end = round_up(end, block_bytes(c)); + int ret; + + ret = bchfs_falloc_newsize(file, mode, offset, len, &new_size); + if (ret) + return ret; + + ret = bchfs_fallocate(inode, mode, block_start >> 9, block_end >> 9); + if (ret) + return ret; + + if (mode & FALLOC_FL_KEEP_SIZE && end > inode->v.i_size) + new_size = inode->v.i_size; + + if (new_size) + ret = bchfs_falloc_setsize(c, inode, new_size); + + return ret; +} + +static noinline long bchfs_falloc_zero_range(struct file *file, int mode, + loff_t offset, loff_t len) +{ + struct bch_inode_info *inode = file_bch_inode(file); + struct bch_fs *c = inode->v.i_sb->s_fs_info; + u64 end = offset + len; + loff_t new_size = 0; + u64 block_start = round_up(offset, block_bytes(c)); + u64 block_end = round_down(end, block_bytes(c)); bool truncated_last_page = false; int ret, ret2 = 0; - if (!(mode & FALLOC_FL_KEEP_SIZE) && end > inode->v.i_size) { - ret = inode_newsize_ok(&inode->v, end); - if (ret) - return ret; - } - - if (mode & FALLOC_FL_ZERO_RANGE) { - ret = bch2_truncate_folios(inode, offset, end); - if (unlikely(ret < 0)) - return ret; + ret = bchfs_falloc_newsize(file, mode, offset, len, &new_size); + if (ret) + return ret; - truncated_last_page = ret; + ret = bch2_truncate_folios(inode, offset, end); + if (unlikely(ret < 0)) + return ret; - truncate_pagecache_range(&inode->v, offset, end - 1); + truncated_last_page = ret; - block_start = round_up(offset, block_bytes(c)); - block_end = round_down(end, block_bytes(c)); - } + truncate_pagecache_range(&inode->v, offset, end - 1); - ret = __bchfs_fallocate(inode, mode, block_start >> 9, block_end >> 9); + ret = bchfs_fallocate(inode, mode, block_start >> 9, block_end >> 9); /* * On -ENOSPC in ZERO_RANGE mode, we still want to do the inode update, * so that the VFS cache i_size is consistent with the btree i_size: */ - if (ret && - !(bch2_err_matches(ret, ENOSPC) && (mode & FALLOC_FL_ZERO_RANGE))) + if (ret && !(bch2_err_matches(ret, ENOSPC))) return ret; if (mode & FALLOC_FL_KEEP_SIZE && end > inode->v.i_size) - end = inode->v.i_size; - - if (end >= inode->v.i_size && - (((mode & FALLOC_FL_ZERO_RANGE) && !truncated_last_page) || - !(mode & FALLOC_FL_KEEP_SIZE))) { - spin_lock(&inode->v.i_lock); - i_size_write(&inode->v, end); - spin_unlock(&inode->v.i_lock); - - mutex_lock(&inode->ei_update_lock); - ret2 = bch2_write_inode_size(c, inode, end, 0); - mutex_unlock(&inode->ei_update_lock); - } + new_size = inode->v.i_size; + + if (new_size && + ((!truncated_last_page) || !(mode & FALLOC_FL_KEEP_SIZE))) + ret2 = bchfs_falloc_setsize(c, inode, new_size); return ret ?: ret2; } @@ -843,8 +884,10 @@ long bch2_fallocate_dispatch(struct file *file, int mode, switch (mode & FALLOC_FL_MODE_MASK) { case FALLOC_FL_ALLOCATE_RANGE: + ret = bchfs_falloc_allocate_range(file, mode, offset, len); + break; case FALLOC_FL_ZERO_RANGE: - ret = bchfs_fallocate(inode, mode, offset, len); + ret = bchfs_falloc_zero_range(file, mode, offset, len); break; case FALLOC_FL_PUNCH_HOLE: ret = bchfs_fpunch(inode, offset, len); -- 2.34.1