lkml.org 
[lkml]   [2018]   [Nov]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.18 189/350] f2fs: fix to recover cold bit of inode block during POR
    Date
    4.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Chao Yu <yuchao0@huawei.com>

    commit ef2a007134b4eaa39264c885999f296577bc87d2 upstream.

    Testcase to reproduce this bug:
    1. mkfs.f2fs /dev/sdd
    2. mount -t f2fs /dev/sdd /mnt/f2fs
    3. touch /mnt/f2fs/file
    4. sync
    5. chattr +A /mnt/f2fs/file
    6. xfs_io -f /mnt/f2fs/file -c "fsync"
    7. godown /mnt/f2fs
    8. umount /mnt/f2fs
    9. mount -t f2fs /dev/sdd /mnt/f2fs
    10. chattr -A /mnt/f2fs/file
    11. xfs_io -f /mnt/f2fs/file -c "fsync"
    12. umount /mnt/f2fs
    13. mount -t f2fs /dev/sdd /mnt/f2fs
    14. lsattr /mnt/f2fs/file

    -----------------N- /mnt/f2fs/file

    But actually, we expect the corrct result is:

    -------A---------N- /mnt/f2fs/file

    The reason is in step 9) we missed to recover cold bit flag in inode
    block, so later, in fsync, we will skip write inode block due to below
    condition check, result in lossing data in another SPOR.

    f2fs_fsync_node_pages()
    if (!IS_DNODE(page) || !is_cold_node(page))
    continue;

    Note that, I guess that some non-dir inode has already lost cold bit
    during POR, so in order to reenable recovery for those inode, let's
    try to recover cold bit in f2fs_iget() to save more fsynced data.

    Fixes: c56675750d7c ("f2fs: remove unneeded set_cold_node()")
    Cc: <stable@vger.kernel.org> 4.17+
    Signed-off-by: Chao Yu <yuchao0@huawei.com>
    Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/f2fs/inode.c | 6 ++++++
    fs/f2fs/node.c | 2 +-
    2 files changed, 7 insertions(+), 1 deletion(-)

    --- a/fs/f2fs/inode.c
    +++ b/fs/f2fs/inode.c
    @@ -287,6 +287,12 @@ static int do_read_inode(struct inode *i
    if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode))
    __recover_inline_status(inode, node_page);

    + /* try to recover cold bit for non-dir inode */
    + if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) {
    + set_cold_node(node_page, false);
    + set_page_dirty(node_page);
    + }
    +
    /* get rdev by using inline_info */
    __get_inode_rdev(inode, ri);

    --- a/fs/f2fs/node.c
    +++ b/fs/f2fs/node.c
    @@ -2356,7 +2356,7 @@ retry:
    if (!PageUptodate(ipage))
    SetPageUptodate(ipage);
    fill_node_footer(ipage, ino, ino, 0, true);
    - set_cold_node(page, false);
    + set_cold_node(ipage, false);

    src = F2FS_INODE(page);
    dst = F2FS_INODE(ipage);

    \
     
     \ /
      Last update: 2018-11-12 00:29    [W:2.581 / U:0.384 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site