• Chao Yu's avatar
    f2fs: fix to flush all dirty inodes recovered in readonly fs · cd295fdd
    Chao Yu authored
    [ Upstream commit 1378752b ]
    
    generic/417 reported as blow:
    
    ------------[ cut here ]------------
    kernel BUG at /home/yuchao/git/devf2fs/inode.c:695!
    invalid opcode: 0000 [#1] PREEMPT SMP
    CPU: 1 PID: 21697 Comm: umount Tainted: G        W  O      4.18.0-rc2+ #39
    Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
    EIP: f2fs_evict_inode+0x556/0x580 [f2fs]
    Call Trace:
     ? _raw_spin_unlock+0x2c/0x50
     evict+0xa8/0x170
     dispose_list+0x34/0x40
     evict_inodes+0x118/0x120
     generic_shutdown_super+0x41/0x100
     ? rcu_read_lock_sched_held+0x97/0xa0
     kill_block_super+0x22/0x50
     kill_f2fs_super+0x6f/0x80 [f2fs]
     deactivate_locked_super+0x3d/0x70
     deactivate_super+0x40/0x60
     cleanup_mnt+0x39/0x70
     __cleanup_mnt+0x10/0x20
     task_work_run+0x81/0xa0
     exit_to_usermode_loop+0x59/0xa7
     do_fast_syscall_32+0x1f5/0x22c
     entry_SYSENTER_32+0x53/0x86
    EIP: f2fs_evict_inode+0x556/0x580 [f2fs]
    
    It can simply reproduced with scripts:
    
    Enable quota feature during mkfs.
    
    Testcase1:
    1. mkfs.f2fs /dev/zram0
    2. mount -t f2fs /dev/zram0 /mnt/f2fs
    3. xfs_io -f /mnt/f2fs/file -c "pwrite 0 4k" -c "fsync"
    4. godown /mnt/f2fs
    5. umount /mnt/f2fs
    6. mount -t f2fs -o ro /dev/zram0 /mnt/f2fs
    7. umount /mnt/f2fs
    
    Testcase2:
    1. mkfs.f2fs /dev/zram0
    2. mount -t f2fs /dev/zram0 /mnt/f2fs
    3. touch /mnt/f2fs/file
    4. create process[pid = x] do:
    	a) open /mnt/f2fs/file;
    	b) unlink /mnt/f2fs/file
    5. godown -f /mnt/f2fs
    6. kill process[pid = x]
    7. umount /mnt/f2fs
    8. mount -t f2fs -o ro /dev/zram0 /mnt/f2fs
    9. umount /mnt/f2fs
    
    The reason is: during recovery, i_{c,m}time of inode will be updated, then
    the inode can be set dirty w/o being tracked in sbi->inode_list[DIRTY_META]
    global list, so later write_checkpoint will not flush such dirty inode into
    node page.
    
    Once umount is called, sync_filesystem() in generic_shutdown_super() will
    skip syncng dirty inodes due to sb_rdonly check, leaving dirty inodes
    there.
    
    To solve this issue, during umount, add remove SB_RDONLY flag in
    sb->s_flags, to make sure sync_filesystem() will not be skipped.
    Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
    Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
    Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    cd295fdd
checkpoint.c 37.9 KB