Skip to content

Commit 2f6d721

Browse files
wangxiuhong134Jaegeuk Kim
authored andcommitted
f2fs: compress: fix reserve_cblocks counting error when out of space
When a file only needs one direct_node, performing the following operations will cause the file to be unrepairable: unisoc # ./f2fs_io compress test.apk unisoc #df -h | grep dm-48 /dev/block/dm-48 112G 112G 1.2M 100% /data unisoc # ./f2fs_io release_cblocks test.apk 924 unisoc # df -h | grep dm-48 /dev/block/dm-48 112G 112G 4.8M 100% /data unisoc # dd if=/dev/random of=file4 bs=1M count=3 3145728 bytes (3.0 M) copied, 0.025 s, 120 M/s unisoc # df -h | grep dm-48 /dev/block/dm-48 112G 112G 1.8M 100% /data unisoc # ./f2fs_io reserve_cblocks test.apk F2FS_IOC_RESERVE_COMPRESS_BLOCKS failed: No space left on device adb reboot unisoc # df -h | grep dm-48 /dev/block/dm-48 112G 112G 11M 100% /data unisoc # ./f2fs_io reserve_cblocks test.apk 0 This is because the file has only one direct_node. After returning to -ENOSPC, reserved_blocks += ret will not be executed. As a result, the reserved_blocks at this time is still 0, which is not the real number of reserved blocks. Therefore, fsck cannot be set to repair the file. After this patch, the fsck flag will be set to fix this problem. unisoc # df -h | grep dm-48 /dev/block/dm-48 112G 112G 1.8M 100% /data unisoc # ./f2fs_io reserve_cblocks test.apk F2FS_IOC_RESERVE_COMPRESS_BLOCKS failed: No space left on device adb reboot then fsck will be executed unisoc # df -h | grep dm-48 /dev/block/dm-48 112G 112G 11M 100% /data unisoc # ./f2fs_io reserve_cblocks test.apk 924 Fixes: c75488f ("f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS") Signed-off-by: Xiuhong Wang <[email protected]> Signed-off-by: Zhiguo Niu <[email protected]> Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent b7d797d commit 2f6d721

File tree

1 file changed

+7
-8
lines changed

1 file changed

+7
-8
lines changed

fs/f2fs/file.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3624,10 +3624,10 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
36243624
return ret;
36253625
}
36263626

3627-
static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
3627+
static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
3628+
unsigned int *reserved_blocks)
36283629
{
36293630
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
3630-
unsigned int reserved_blocks = 0;
36313631
int cluster_size = F2FS_I(dn->inode)->i_cluster_size;
36323632
block_t blkaddr;
36333633
int i;
@@ -3691,12 +3691,12 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
36913691

36923692
f2fs_i_compr_blocks_update(dn->inode, compr_blocks, true);
36933693

3694-
reserved_blocks += reserved;
3694+
*reserved_blocks += reserved;
36953695
next:
36963696
count -= cluster_size;
36973697
}
36983698

3699-
return reserved_blocks;
3699+
return 0;
37003700
}
37013701

37023702
static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
@@ -3757,21 +3757,20 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
37573757
count = min(end_offset - dn.ofs_in_node, last_idx - page_idx);
37583758
count = round_up(count, F2FS_I(inode)->i_cluster_size);
37593759

3760-
ret = reserve_compress_blocks(&dn, count);
3760+
ret = reserve_compress_blocks(&dn, count, &reserved_blocks);
37613761

37623762
f2fs_put_dnode(&dn);
37633763

37643764
if (ret < 0)
37653765
break;
37663766

37673767
page_idx += count;
3768-
reserved_blocks += ret;
37693768
}
37703769

37713770
filemap_invalidate_unlock(inode->i_mapping);
37723771
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
37733772

3774-
if (ret >= 0) {
3773+
if (!ret) {
37753774
clear_inode_flag(inode, FI_COMPRESS_RELEASED);
37763775
inode_set_ctime_current(inode);
37773776
f2fs_mark_inode_dirty_sync(inode, true);
@@ -3780,7 +3779,7 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
37803779
inode_unlock(inode);
37813780
mnt_drop_write_file(filp);
37823781

3783-
if (ret >= 0) {
3782+
if (!ret) {
37843783
ret = put_user(reserved_blocks, (u64 __user *)arg);
37853784
} else if (reserved_blocks &&
37863785
atomic_read(&F2FS_I(inode)->i_compr_blocks)) {

0 commit comments

Comments
 (0)