• Zhihao Cheng's avatar
    ubifs: ubifs_releasepage: Remove ubifs_assert(0) to valid this process · 66f4742e
    Zhihao Cheng authored
    There are two states for ubifs writing pages:
    1. Dirty, Private
    2. Not Dirty, Not Private
    
    The normal process cannot go to ubifs_releasepage() which means there
    exists pages being private but not dirty. Reproducer[1] shows that it
    could occur (which maybe related to [2]) with following process:
    
         PA                     PB                    PC
    lock(page)[PA]
    ubifs_write_end
      attach_page_private         // set Private
      __set_page_dirty_nobuffers  // set Dirty
    unlock(page)
    
    write_cache_pages[PA]
      lock(page)
      clear_page_dirty_for_io(page)	// clear Dirty
      ubifs_writepage
    
                            do_truncation[PB]
    			  truncate_setsize
    			    i_size_write(inode, newsize) // newsize = 0
    
        i_size = i_size_read(inode)	// i_size = 0
        end_index = i_size >> PAGE_SHIFT
        if (page->index > end_index)
          goto out // jump
    out:
    unlock(page)   // Private, Not Dirty
    
    						generic_fadvise[PC]
    						  lock(page)
    						  invalidate_inode_page
    						    try_to_release_page
    						      ubifs_releasepage
    						        ubifs_assert(c, 0)
    		                                        // bad assertion!
    						  unlock(page)
    			  truncate_pagecache[PB]
    
    Then we may get following assertion failed:
      UBIFS error (ubi0:0 pid 1683): ubifs_assert_failed [ubifs]:
      UBIFS assert failed: 0, in fs/ubifs/file.c:1513
      UBIFS warning (ubi0:0 pid 1683): ubifs_ro_mode [ubifs]:
      switched to read-only mode, error -22
      CPU: 2 PID: 1683 Comm: aa Not tainted 5.16.0-rc5-00184-g0bca5994cacc-dirty #308
      Call Trace:
        dump_stack+0x13/0x1b
        ubifs_ro_mode+0x54/0x60 [ubifs]
        ubifs_assert_failed+0x4b/0x80 [ubifs]
        ubifs_releasepage+0x67/0x1d0 [ubifs]
        try_to_release_page+0x57/0xe0
        invalidate_inode_page+0xfb/0x130
        __invalidate_mapping_pages+0xb9/0x280
        invalidate_mapping_pagevec+0x12/0x20
        generic_fadvise+0x303/0x3c0
        ksys_fadvise64_64+0x4c/0xb0
    
    [1] https://bugzilla.kernel.org/show_bug.cgi?id=215373
    [2] https://linux-mtd.infradead.narkive.com/NQoBeT1u/patch-rfc-ubifs-fix-assert-failed-in-ubifs-set-page-dirty
    
    Fixes: 1e51764a ("UBIFS: add new flash file system")
    Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
    Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
    66f4742e
file.c 46.9 KB