• Chao Yu's avatar
    f2fs: compress: fix race condition of overwrite vs truncate · a949dc5f
    Chao Yu authored
    pos_fsstress testcase complains a panic as belew:
    
    ------------[ cut here ]------------
    kernel BUG at fs/f2fs/compress.c:1082!
    invalid opcode: 0000 [#1] SMP PTI
    CPU: 4 PID: 2753477 Comm: kworker/u16:2 Tainted: G           OE     5.12.0-rc1-custom #1
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
    Workqueue: writeback wb_workfn (flush-252:16)
    RIP: 0010:prepare_compress_overwrite+0x4c0/0x760 [f2fs]
    Call Trace:
     f2fs_prepare_compress_overwrite+0x5f/0x80 [f2fs]
     f2fs_write_cache_pages+0x468/0x8a0 [f2fs]
     f2fs_write_data_pages+0x2a4/0x2f0 [f2fs]
     do_writepages+0x38/0xc0
     __writeback_single_inode+0x44/0x2a0
     writeback_sb_inodes+0x223/0x4d0
     __writeback_inodes_wb+0x56/0xf0
     wb_writeback+0x1dd/0x290
     wb_workfn+0x309/0x500
     process_one_work+0x220/0x3c0
     worker_thread+0x53/0x420
     kthread+0x12f/0x150
     ret_from_fork+0x22/0x30
    
    The root cause is truncate() may race with overwrite as below,
    so that one reference count left in page can not guarantee the
    page attaching in mapping tree all the time, after truncation,
    later find_lock_page() may return NULL pointer.
    
    - prepare_compress_overwrite
     - f2fs_pagecache_get_page
     - unlock_page
    					- f2fs_setattr
    					 - truncate_setsize
    					  - truncate_inode_page
    					   - delete_from_page_cache
     - find_lock_page
    
    Fix this by avoiding referencing updated page.
    
    Fixes: 4c8ff709 ("f2fs: support data compression")
    Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
    Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
    a949dc5f
compress.c 40.6 KB