Patch "ubifs: ubifs_writepage: Mark page dirty after writing inode failed" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ubifs: ubifs_writepage: Mark page dirty after writing inode failed

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ubifs-ubifs_writepage-mark-page-dirty-after-writing-.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 1cc7106267ad7fb4197e6719ed3d2ae034e0558a
Author: Zhihao Cheng <chengzhihao1@xxxxxxxxxx>
Date:   Wed Jun 1 10:59:59 2022 +0800

    ubifs: ubifs_writepage: Mark page dirty after writing inode failed
    
    [ Upstream commit fb8bc4c74ae4526d9489362ab2793a936d072b84 ]
    
    There are two states for ubifs writing pages:
    1. Dirty, Private
    2. Not Dirty, Not Private
    
    There is a third possibility which maybe related to [1] that page is
    private but not dirty caused by following process:
    
              PA
    lock(page)
    ubifs_write_end
      attach_page_private           // set Private
        __set_page_dirty_nobuffers  // set Dirty
    unlock(page)
    
    write_cache_pages
      lock(page)
      clear_page_dirty_for_io(page) // clear Dirty
      ubifs_writepage
        write_inode
        // fail, goto out, following codes are not executed
        // do_writepage
        //   set_page_writeback     // set Writeback
        //   detach_page_private    // clear Private
        //   end_page_writeback     // clear Writeback
        out:
        unlock(page)                // Private, Not Dirty
    
                                           PB
                                    ksys_fadvise64_64
                                      generic_fadvise
                                         invalidate_inode_page
                                         // page is neither Dirty nor Writeback
                                           invalidate_complete_page
                                           // page_has_private is true
                                             try_to_release_page
                                               ubifs_releasepage
                                                 ubifs_assert(c, 0) !!!
    
    Then we may get following assertion failed:
      UBIFS error (ubi0:0 pid 1492): ubifs_assert_failed [ubifs]:
      UBIFS assert failed: 0, in fs/ubifs/file.c:1499
      UBIFS warning (ubi0:0 pid 1492): ubifs_ro_mode [ubifs]:
      switched to read-only mode, error -22
      CPU: 2 PID: 1492 Comm: aa Not tainted 5.16.0-rc2-00012-g7bb767dee0ba-dirty
      Call Trace:
        dump_stack+0x13/0x1b
        ubifs_ro_mode+0x54/0x60 [ubifs]
        ubifs_assert_failed+0x4b/0x80 [ubifs]
        ubifs_releasepage+0x7e/0x1e0 [ubifs]
        try_to_release_page+0x57/0xe0
        invalidate_inode_page+0xfb/0x130
        invalidate_mapping_pagevec+0x12/0x20
        generic_fadvise+0x303/0x3c0
        vfs_fadvise+0x35/0x40
        ksys_fadvise64_64+0x4c/0xb0
    
    Jump [2] to find a reproducer.
    
    [1] https://linux-mtd.infradead.narkive.com/NQoBeT1u/patch-rfc-ubifs-fix-assert-failed-in-ubifs-set-page-dirty
    [2] https://bugzilla.kernel.org/show_bug.cgi?id=215357
    
    Fixes: 1e51764a3c2ac0 ("UBIFS: add new flash file system")
    Signed-off-by: Zhihao Cheng <chengzhihao1@xxxxxxxxxx>
    Signed-off-by: Richard Weinberger <richard@xxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 6069c63d833ae..177cd4a751ebb 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1031,7 +1031,7 @@ static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
 		if (page->index >= synced_i_size >> PAGE_SHIFT) {
 			err = inode->i_sb->s_op->write_inode(inode, NULL);
 			if (err)
-				goto out_unlock;
+				goto out_redirty;
 			/*
 			 * The inode has been written, but the write-buffer has
 			 * not been synchronized, so in case of an unclean
@@ -1059,11 +1059,17 @@ static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
 	if (i_size > synced_i_size) {
 		err = inode->i_sb->s_op->write_inode(inode, NULL);
 		if (err)
-			goto out_unlock;
+			goto out_redirty;
 	}
 
 	return do_writepage(page, len);
-
+out_redirty:
+	/*
+	 * redirty_page_for_writepage() won't call ubifs_dirty_inode() because
+	 * it passes I_DIRTY_PAGES flag while calling __mark_inode_dirty(), so
+	 * there is no need to do space budget for dirty inode.
+	 */
+	redirty_page_for_writepage(wbc, page);
 out_unlock:
 	unlock_page(page);
 	return err;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux