Skip to content

Commit f5cd931

Browse files
Jaegeuk Kimpundiramit
authored andcommitted
f2fs: do not activate auto_recovery for fallocated i_size
commit 26787236b36660baf4d136281d40b5bb33a570ec upstream. If a file needs to keep its i_size by fallocate, we need to turn off auto recovery during roll-forward recovery. This will resolve the below scenario. 1. xfs_io -f /mnt/f2fs/file -c "pwrite 0 4096" -c "fsync" 2. xfs_io -f /mnt/f2fs/file -c "falloc -k 4096 4096" -c "fsync" 3. md5sum /mnt/f2fs/file; 4. godown /mnt/f2fs/ 5. umount /mnt/f2fs/ 6. mount -t f2fs /dev/sdx /mnt/f2fs 7. md5sum /mnt/f2fs/file Reported-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 248e942 commit f5cd931

3 files changed

Lines changed: 31 additions & 20 deletions

File tree

fs/f2fs/f2fs.h

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ struct f2fs_map_blocks {
449449
#define FADVISE_LOST_PINO_BIT 0x02
450450
#define FADVISE_ENCRYPT_BIT 0x04
451451
#define FADVISE_ENC_NAME_BIT 0x08
452+
#define FADVISE_KEEP_SIZE_BIT 0x10
452453

453454
#define file_is_cold(inode) is_file(inode, FADVISE_COLD_BIT)
454455
#define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT)
@@ -461,6 +462,8 @@ struct f2fs_map_blocks {
461462
#define file_clear_encrypt(inode) clear_file(inode, FADVISE_ENCRYPT_BIT)
462463
#define file_enc_name(inode) is_file(inode, FADVISE_ENC_NAME_BIT)
463464
#define file_set_enc_name(inode) set_file(inode, FADVISE_ENC_NAME_BIT)
465+
#define file_keep_isize(inode) is_file(inode, FADVISE_KEEP_SIZE_BIT)
466+
#define file_set_keep_isize(inode) set_file(inode, FADVISE_KEEP_SIZE_BIT)
464467

465468
#define DEF_DIR_LEVEL 0
466469

@@ -1763,23 +1766,6 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
17631766
set_inode_flag(inode, FI_AUTO_RECOVER);
17641767
}
17651768

1766-
static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
1767-
{
1768-
if (dsync) {
1769-
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
1770-
bool ret;
1771-
1772-
spin_lock(&sbi->inode_lock[DIRTY_META]);
1773-
ret = list_empty(&F2FS_I(inode)->gdirty_list);
1774-
spin_unlock(&sbi->inode_lock[DIRTY_META]);
1775-
return ret;
1776-
}
1777-
if (!is_inode_flag_set(inode, FI_AUTO_RECOVER) ||
1778-
i_size_read(inode) & PAGE_MASK)
1779-
return false;
1780-
return F2FS_I(inode)->last_disk_size == i_size_read(inode);
1781-
}
1782-
17831769
static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth)
17841770
{
17851771
F2FS_I(inode)->i_current_depth = depth;
@@ -1932,6 +1918,24 @@ static inline void clear_file(struct inode *inode, int type)
19321918
f2fs_mark_inode_dirty_sync(inode, true);
19331919
}
19341920

1921+
static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
1922+
{
1923+
if (dsync) {
1924+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
1925+
bool ret;
1926+
1927+
spin_lock(&sbi->inode_lock[DIRTY_META]);
1928+
ret = list_empty(&F2FS_I(inode)->gdirty_list);
1929+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
1930+
return ret;
1931+
}
1932+
if (!is_inode_flag_set(inode, FI_AUTO_RECOVER) ||
1933+
file_keep_isize(inode) ||
1934+
i_size_read(inode) & PAGE_MASK)
1935+
return false;
1936+
return F2FS_I(inode)->last_disk_size == i_size_read(inode);
1937+
}
1938+
19351939
static inline int f2fs_readonly(struct super_block *sb)
19361940
{
19371941
return sb->s_flags & MS_RDONLY;

fs/f2fs/file.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,8 @@ static long f2fs_fallocate(struct file *file, int mode,
14031403
if (!ret) {
14041404
inode->i_mtime = inode->i_ctime = current_time(inode);
14051405
f2fs_mark_inode_dirty_sync(inode, false);
1406+
if (mode & FALLOC_FL_KEEP_SIZE)
1407+
file_set_keep_isize(inode);
14061408
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
14071409
}
14081410

fs/f2fs/recovery.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ static void recover_inode(struct inode *inode, struct page *page)
187187
inode->i_ctime.tv_nsec = le32_to_cpu(raw->i_ctime_nsec);
188188
inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
189189

190+
F2FS_I(inode)->i_advise = raw->i_advise;
191+
190192
if (file_enc_name(inode))
191193
name = "<encrypted>";
192194
else
@@ -425,7 +427,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
425427
continue;
426428
}
427429

428-
if (i_size_read(inode) <= (start << PAGE_SHIFT))
430+
if (!file_keep_isize(inode) &&
431+
(i_size_read(inode) <= (start << PAGE_SHIFT)))
429432
f2fs_i_size_write(inode, (start + 1) << PAGE_SHIFT);
430433

431434
/*
@@ -478,8 +481,10 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
478481
f2fs_put_dnode(&dn);
479482
out:
480483
f2fs_msg(sbi->sb, KERN_NOTICE,
481-
"recover_data: ino = %lx, recovered = %d blocks, err = %d",
482-
inode->i_ino, recovered, err);
484+
"recover_data: ino = %lx (i_size: %s) recovered = %d, err = %d",
485+
inode->i_ino,
486+
file_keep_isize(inode) ? "keep" : "recover",
487+
recovered, err);
483488
return err;
484489
}
485490

0 commit comments

Comments
 (0)