lkml.org 
[lkml]   [2018]   [Nov]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 049/143] ocfs2: fix crash in ocfs2_duplicate_clusters_by_page()
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

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

    [ Upstream commit 69eb7765b9c6902444c89c54e7043242faf981e5 ]

    ocfs2_duplicate_clusters_by_page() may crash if one of the extent's pages
    is dirty. When a page has not been written back, it is still in dirty
    state. If ocfs2_duplicate_clusters_by_page() is called against the dirty
    page, the crash happens.

    To fix this bug, we can just unlock the page and wait until the page until
    its not dirty.

    The following is the backtrace:

    kernel BUG at /root/code/ocfs2/refcounttree.c:2961!
    [exception RIP: ocfs2_duplicate_clusters_by_page+822]
    __ocfs2_move_extent+0x80/0x450 [ocfs2]
    ? __ocfs2_claim_clusters+0x130/0x250 [ocfs2]
    ocfs2_defrag_extent+0x5b8/0x5e0 [ocfs2]
    __ocfs2_move_extents_range+0x2a4/0x470 [ocfs2]
    ocfs2_move_extents+0x180/0x3b0 [ocfs2]
    ? ocfs2_wait_for_recovery+0x13/0x70 [ocfs2]
    ocfs2_ioctl_move_extents+0x133/0x2d0 [ocfs2]
    ocfs2_ioctl+0x253/0x640 [ocfs2]
    do_vfs_ioctl+0x90/0x5f0
    SyS_ioctl+0x74/0x80
    do_syscall_64+0x74/0x140
    entry_SYSCALL_64_after_hwframe+0x3d/0xa2

    Once we find the page is dirty, we do not wait until it's clean, rather we
    use write_one_page() to write it back

    Link: http://lkml.kernel.org/r/20180829074740.9438-1-lchen@suse.com
    [lchen@suse.com: update comments]
    Link: http://lkml.kernel.org/r/20180830075041.14879-1-lchen@suse.com
    [akpm@linux-foundation.org: coding-style fixes]
    Signed-off-by: Larry Chen <lchen@suse.com>
    Acked-by: Changwei Ge <ge.changwei@h3c.com>
    Cc: Mark Fasheh <mark@fasheh.com>
    Cc: Joel Becker <jlbec@evilplan.org>
    Cc: Junxiao Bi <junxiao.bi@oracle.com>
    Cc: Joseph Qi <jiangqi903@gmail.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/ocfs2/refcounttree.c | 16 ++++++++++++----
    1 file changed, 12 insertions(+), 4 deletions(-)

    diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
    index 1b1283f07941..824f407df1db 100644
    --- a/fs/ocfs2/refcounttree.c
    +++ b/fs/ocfs2/refcounttree.c
    @@ -2946,6 +2946,7 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle,
    if (map_end & (PAGE_SIZE - 1))
    to = map_end & (PAGE_SIZE - 1);

    +retry:
    page = find_or_create_page(mapping, page_index, GFP_NOFS);
    if (!page) {
    ret = -ENOMEM;
    @@ -2954,11 +2955,18 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle,
    }

    /*
    - * In case PAGE_SIZE <= CLUSTER_SIZE, This page
    - * can't be dirtied before we CoW it out.
    + * In case PAGE_SIZE <= CLUSTER_SIZE, we do not expect a dirty
    + * page, so write it back.
    */
    - if (PAGE_SIZE <= OCFS2_SB(sb)->s_clustersize)
    - BUG_ON(PageDirty(page));
    + if (PAGE_SIZE <= OCFS2_SB(sb)->s_clustersize) {
    + if (PageDirty(page)) {
    + /*
    + * write_on_page will unlock the page on return
    + */
    + ret = write_one_page(page);
    + goto retry;
    + }
    + }

    if (!PageUptodate(page)) {
    ret = block_read_full_page(page, ocfs2_get_block);
    --
    2.17.1


    \
     
     \ /
      Last update: 2018-11-02 20:01    [W:4.338 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site