lkml.org 
[lkml]   [2020]   [Dec]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 121/132] jffs2: Fix GC exit abnormally
    Date
    From: Zhe Li <lizhe67@huawei.com>

    commit 9afc9a8a4909fece0e911e72b1060614ba2f7969 upstream.

    The log of this problem is:
    jffs2: Error garbage collecting node at 0x***!
    jffs2: No space for garbage collection. Aborting GC thread

    This is because GC believe that it do nothing, so it abort.

    After going over the image of jffs2, I find a scene that
    can trigger this problem stably.
    The scene is: there is a normal dirent node at summary-area,
    but abnormal at corresponding not-summary-area with error
    name_crc.

    The reason that GC exit abnormally is because it find that
    abnormal dirent node to GC, but when it goes to function
    jffs2_add_fd_to_list, it cannot meet the condition listed
    below:

    if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name))

    So no node is marked obsolete, statistical information of
    erase_block do not change, which cause GC exit abnormally.

    The root cause of this problem is: we do not check the
    name_crc of the abnormal dirent node with summary is enabled.

    Noticed that in function jffs2_scan_dirent_node, we use
    function jffs2_scan_dirty_space to deal with the dirent
    node with error name_crc. So this patch add a checking
    code in function read_direntry to ensure the correctness
    of dirent node. If checked failed, the dirent node will
    be marked obsolete so GC will pass this node and this
    problem will be fixed.

    Cc: <stable@vger.kernel.org>
    Signed-off-by: Zhe Li <lizhe67@huawei.com>
    Signed-off-by: Richard Weinberger <richard@nod.at>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/jffs2/readinode.c | 16 ++++++++++++++++
    1 file changed, 16 insertions(+)

    --- a/fs/jffs2/readinode.c
    +++ b/fs/jffs2/readinode.c
    @@ -672,6 +672,22 @@ static inline int read_direntry(struct j
    jffs2_free_full_dirent(fd);
    return -EIO;
    }
    +
    +#ifdef CONFIG_JFFS2_SUMMARY
    + /*
    + * we use CONFIG_JFFS2_SUMMARY because without it, we
    + * have checked it while mounting
    + */
    + crc = crc32(0, fd->name, rd->nsize);
    + if (unlikely(crc != je32_to_cpu(rd->name_crc))) {
    + JFFS2_NOTICE("name CRC failed on dirent node at"
    + "%#08x: read %#08x,calculated %#08x\n",
    + ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
    + jffs2_mark_node_obsolete(c, ref);
    + jffs2_free_full_dirent(fd);
    + return 0;
    + }
    +#endif
    }

    fd->nhash = full_name_hash(fd->name, rd->nsize);

    \
     
     \ /
      Last update: 2020-12-28 13:59    [W:4.052 / U:0.456 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site