Reserve blocks on released compress inode while writing, so compressed files with released space are allowed to be rewritten.
Signed-off-by: Yangtao Li <[email protected]> --- fs/f2fs/file.c | 86 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 15dabeac4690..749b5af17141 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -3612,39 +3612,15 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count) return reserved_blocks; } -static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) +static int f2fs_reserve_file(struct inode *inode, unsigned int *blocks) { - struct inode *inode = file_inode(filp); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); pgoff_t page_idx = 0, last_idx; unsigned int reserved_blocks = 0; int ret; - if (!f2fs_sb_has_compression(F2FS_I_SB(inode))) - return -EOPNOTSUPP; - - if (!f2fs_compressed_file(inode)) - return -EINVAL; - - if (f2fs_readonly(sbi->sb)) - return -EROFS; - - ret = mnt_want_write_file(filp); - if (ret) - return ret; - - if (atomic_read(&F2FS_I(inode)->i_compr_blocks)) - goto out; - f2fs_balance_fs(F2FS_I_SB(inode), true); - inode_lock(inode); - - if (!is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { - ret = -EINVAL; - goto unlock_inode; - } - f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); filemap_invalidate_lock(inode->i_mapping); @@ -3688,14 +3664,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) clear_inode_flag(inode, FI_COMPRESS_RELEASED); inode->i_ctime = current_time(inode); f2fs_mark_inode_dirty_sync(inode, true); - } -unlock_inode: - inode_unlock(inode); -out: - mnt_drop_write_file(filp); - - if (ret >= 0) { - ret = put_user(reserved_blocks, (u64 __user *)arg); + if (blocks) + *blocks = reserved_blocks; } else if (reserved_blocks && atomic_read(&F2FS_I(inode)->i_compr_blocks)) { set_sbi_flag(sbi, SBI_NEED_FSCK); @@ -3710,6 +3680,49 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) return ret; } +static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + unsigned int reserved_blocks = 0; + int ret; + + if (!f2fs_sb_has_compression(F2FS_I_SB(inode))) + return -EOPNOTSUPP; + + if (!f2fs_compressed_file(inode)) + return -EINVAL; + + if (f2fs_readonly(sbi->sb)) + return -EROFS; + + ret = mnt_want_write_file(filp); + if (ret) + return ret; + + if (atomic_read(&F2FS_I(inode)->i_compr_blocks)) + goto out; + + inode_lock(inode); + + if (!is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { + ret = -EINVAL; + goto unlock_inode; + } + + ret = f2fs_reserve_file(inode, &reserved_blocks); + +unlock_inode: + inode_unlock(inode); +out: + mnt_drop_write_file(filp); + + if (ret >= 0) + ret = put_user(reserved_blocks, (u64 __user *)arg); + + return ret; +} + static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode, pgoff_t off, block_t block, block_t len, u32 flags) { @@ -4412,8 +4425,11 @@ static ssize_t f2fs_write_checks(struct kiocb *iocb, struct iov_iter *from) if (IS_IMMUTABLE(inode)) return -EPERM; - if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) - return -EPERM; + if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { + err = f2fs_reserve_file(inode, NULL); + if (err < 0) + return err; + } count = generic_write_checks(iocb, from); if (count <= 0) -- 2.39.0 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
