lkml.org 
[lkml]   [2013]   [Jan]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 109/221] ext4: fix extent tree corruption caused by hole punch
    Date
    3.7-stable review patch.  If anyone has any objections, please let me know.

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

    From: Forrest Liu <forrestl@synology.com>

    commit c36575e663e302dbaa4d16b9c72d2c9a913a9aef upstream.

    When depth of extent tree is greater than 1, logical start value of
    interior node is not correctly updated in ext4_ext_rm_idx.

    Signed-off-by: Forrest Liu <forrestl@synology.com>
    Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
    Reviewed-by: Ashish Sangwan <ashishsangwan2@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/ext4/extents.c | 22 ++++++++++++++++++----
    1 file changed, 18 insertions(+), 4 deletions(-)

    --- a/fs/ext4/extents.c
    +++ b/fs/ext4/extents.c
    @@ -2190,13 +2190,14 @@ errout:
    * removes index from the index block.
    */
    static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
    - struct ext4_ext_path *path)
    + struct ext4_ext_path *path, int depth)
    {
    int err;
    ext4_fsblk_t leaf;

    /* free index block */
    - path--;
    + depth--;
    + path = path + depth;
    leaf = ext4_idx_pblock(path->p_idx);
    if (unlikely(path->p_hdr->eh_entries == 0)) {
    EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
    @@ -2221,6 +2222,19 @@ static int ext4_ext_rm_idx(handle_t *han

    ext4_free_blocks(handle, inode, NULL, leaf, 1,
    EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
    +
    + while (--depth >= 0) {
    + if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr))
    + break;
    + path--;
    + err = ext4_ext_get_access(handle, inode, path);
    + if (err)
    + break;
    + path->p_idx->ei_block = (path+1)->p_idx->ei_block;
    + err = ext4_ext_dirty(handle, inode, path);
    + if (err)
    + break;
    + }
    return err;
    }

    @@ -2557,7 +2571,7 @@ ext4_ext_rm_leaf(handle_t *handle, struc
    /* if this leaf is free, then we should
    * remove it from index block above */
    if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
    - err = ext4_ext_rm_idx(handle, inode, path + depth);
    + err = ext4_ext_rm_idx(handle, inode, path, depth);

    out:
    return err;
    @@ -2760,7 +2774,7 @@ again:
    /* index is empty, remove it;
    * handle must be already prepared by the
    * truncatei_leaf() */
    - err = ext4_ext_rm_idx(handle, inode, path + i);
    + err = ext4_ext_rm_idx(handle, inode, path, i);
    }
    /* root level has p_bh == NULL, brelse() eats this */
    brelse(path[i].p_bh);



    \
     
     \ /
      Last update: 2013-01-16 01:21    [W:4.057 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site