lkml.org 
[lkml]   [2017]   [Jan]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 203/206] xfs: fix crash and data corruption due to removal of busy COW extents
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

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


    commit a1b7a4dea6166cf46be895bce4aac67ea5160fe8 upstream.

    There is a race window between write_cache_pages calling
    clear_page_dirty_for_io and XFS calling set_page_writeback, in which
    the mapping for an inode is tagged neither as dirty, nor as writeback.

    If the COW shrinker hits in exactly that window we'll remove the delayed
    COW extents and writepages trying to write it back, which in release
    kernels will manifest as corruption of the bmap btree, and in debug
    kernels will trip the ASSERT about now calling xfs_bmapi_write with the
    COWFORK flag for holes. A complex customer load manages to hit this
    window fairly reliably, probably by always having COW writeback in flight
    while the cow shrinker runs.

    This patch adds another check for having the I_DIRTY_PAGES flag set,
    which is still set during this race window. While this fixes the problem
    I'm still not overly happy about the way the COW shrinker works as it
    still seems a bit fragile.

    Signed-off-by: Christoph Hellwig <hch@lst.de>
    Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
    Cc: Christoph Hellwig <hch@lst.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/xfs/xfs_icache.c | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)

    --- a/fs/xfs/xfs_icache.c
    +++ b/fs/xfs/xfs_icache.c
    @@ -1599,7 +1599,8 @@ xfs_inode_free_cowblocks(
    * If the mapping is dirty or under writeback we cannot touch the
    * CoW fork. Leave it alone if we're in the midst of a directio.
    */
    - if (mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_DIRTY) ||
    + if ((VFS_I(ip)->i_state & I_DIRTY_PAGES) ||
    + mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_DIRTY) ||
    mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_WRITEBACK) ||
    atomic_read(&VFS_I(ip)->i_dio_count))
    return 0;

    \
     
     \ /
      Last update: 2017-01-10 14:56    [W:4.116 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site