forked from Minki/linux
f2fs: do not activate auto_recovery for fallocated i_size
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>
This commit is contained in:
parent
8508e44ae9
commit
26787236b3
@ -401,6 +401,7 @@ struct f2fs_map_blocks {
|
||||
#define FADVISE_LOST_PINO_BIT 0x02
|
||||
#define FADVISE_ENCRYPT_BIT 0x04
|
||||
#define FADVISE_ENC_NAME_BIT 0x08
|
||||
#define FADVISE_KEEP_SIZE_BIT 0x10
|
||||
|
||||
#define file_is_cold(inode) is_file(inode, FADVISE_COLD_BIT)
|
||||
#define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT)
|
||||
@ -413,6 +414,8 @@ struct f2fs_map_blocks {
|
||||
#define file_clear_encrypt(inode) clear_file(inode, FADVISE_ENCRYPT_BIT)
|
||||
#define file_enc_name(inode) is_file(inode, FADVISE_ENC_NAME_BIT)
|
||||
#define file_set_enc_name(inode) set_file(inode, FADVISE_ENC_NAME_BIT)
|
||||
#define file_keep_isize(inode) is_file(inode, FADVISE_KEEP_SIZE_BIT)
|
||||
#define file_set_keep_isize(inode) set_file(inode, FADVISE_KEEP_SIZE_BIT)
|
||||
|
||||
#define DEF_DIR_LEVEL 0
|
||||
|
||||
@ -1716,23 +1719,6 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
|
||||
set_inode_flag(inode, FI_AUTO_RECOVER);
|
||||
}
|
||||
|
||||
static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
|
||||
{
|
||||
if (dsync) {
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||
bool ret;
|
||||
|
||||
spin_lock(&sbi->inode_lock[DIRTY_META]);
|
||||
ret = list_empty(&F2FS_I(inode)->gdirty_list);
|
||||
spin_unlock(&sbi->inode_lock[DIRTY_META]);
|
||||
return ret;
|
||||
}
|
||||
if (!is_inode_flag_set(inode, FI_AUTO_RECOVER) ||
|
||||
i_size_read(inode) & PAGE_MASK)
|
||||
return false;
|
||||
return F2FS_I(inode)->last_disk_size == i_size_read(inode);
|
||||
}
|
||||
|
||||
static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth)
|
||||
{
|
||||
F2FS_I(inode)->i_current_depth = depth;
|
||||
@ -1885,6 +1871,24 @@ static inline void clear_file(struct inode *inode, int type)
|
||||
f2fs_mark_inode_dirty_sync(inode, true);
|
||||
}
|
||||
|
||||
static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
|
||||
{
|
||||
if (dsync) {
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||
bool ret;
|
||||
|
||||
spin_lock(&sbi->inode_lock[DIRTY_META]);
|
||||
ret = list_empty(&F2FS_I(inode)->gdirty_list);
|
||||
spin_unlock(&sbi->inode_lock[DIRTY_META]);
|
||||
return ret;
|
||||
}
|
||||
if (!is_inode_flag_set(inode, FI_AUTO_RECOVER) ||
|
||||
file_keep_isize(inode) ||
|
||||
i_size_read(inode) & PAGE_MASK)
|
||||
return false;
|
||||
return F2FS_I(inode)->last_disk_size == i_size_read(inode);
|
||||
}
|
||||
|
||||
static inline int f2fs_readonly(struct super_block *sb)
|
||||
{
|
||||
return sb->s_flags & MS_RDONLY;
|
||||
|
@ -1399,6 +1399,8 @@ static long f2fs_fallocate(struct file *file, int mode,
|
||||
if (!ret) {
|
||||
inode->i_mtime = inode->i_ctime = current_time(inode);
|
||||
f2fs_mark_inode_dirty_sync(inode, false);
|
||||
if (mode & FALLOC_FL_KEEP_SIZE)
|
||||
file_set_keep_isize(inode);
|
||||
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
|
||||
}
|
||||
|
||||
|
@ -187,6 +187,8 @@ static void recover_inode(struct inode *inode, struct page *page)
|
||||
inode->i_ctime.tv_nsec = le32_to_cpu(raw->i_ctime_nsec);
|
||||
inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
|
||||
|
||||
F2FS_I(inode)->i_advise = raw->i_advise;
|
||||
|
||||
if (file_enc_name(inode))
|
||||
name = "<encrypted>";
|
||||
else
|
||||
@ -425,7 +427,8 @@ retry_dn:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i_size_read(inode) <= (start << PAGE_SHIFT))
|
||||
if (!file_keep_isize(inode) &&
|
||||
(i_size_read(inode) <= (start << PAGE_SHIFT)))
|
||||
f2fs_i_size_write(inode, (start + 1) << PAGE_SHIFT);
|
||||
|
||||
/*
|
||||
@ -478,8 +481,10 @@ err:
|
||||
f2fs_put_dnode(&dn);
|
||||
out:
|
||||
f2fs_msg(sbi->sb, KERN_NOTICE,
|
||||
"recover_data: ino = %lx, recovered = %d blocks, err = %d",
|
||||
inode->i_ino, recovered, err);
|
||||
"recover_data: ino = %lx (i_size: %s) recovered = %d, err = %d",
|
||||
inode->i_ino,
|
||||
file_keep_isize(inode) ? "keep" : "recover",
|
||||
recovered, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user