• Brian Foster's avatar
    xfs: fix shared extent data corruption due to missing cow reservation · c3a66bf4
    Brian Foster authored
    commit 59e42931 upstream.
    
    Page writeback indirectly handles shared extents via the existence
    of overlapping COW fork blocks. If COW fork blocks exist, writeback
    always performs the associated copy-on-write regardless if the
    underlying blocks are actually shared. If the blocks are shared,
    then overlapping COW fork blocks must always exist.
    
    fstests shared/010 reproduces a case where a buffered write occurs
    over a shared block without performing the requisite COW fork
    reservation.  This ultimately causes writeback to the shared extent
    and data corruption that is detected across md5 checks of the
    filesystem across a mount cycle.
    
    The problem occurs when a buffered write lands over a shared extent
    that crosses an extent size hint boundary and that also happens to
    have a partial COW reservation that doesn't cover the start and end
    blocks of the data fork extent.
    
    For example, a buffered write occurs across the file offset (in FSB
    units) range of [29, 57]. A shared extent exists at blocks [29, 35]
    and COW reservation already exists at blocks [32, 34]. After
    accommodating a COW extent size hint of 32 blocks and the existing
    reservation at offset 32, xfs_reflink_reserve_cow() allocates 32
    blocks of reservation at offset 0 and returns with COW reservation
    across the range of [0, 34]. The associated data fork extent is
    still [29, 35], however, which isn't fully covered by the COW
    reservation.
    
    This leads to a buffered write at file offset 35 over a shared
    extent without associated COW reservation. Writeback eventually
    kicks in, performs an overwrite of the underlying shared block and
    causes the associated data corruption.
    
    Update xfs_reflink_reserve_cow() to accommodate the fact that a
    delalloc allocation request may not fully cover the extent in the
    data fork. Trim the data fork extent appropriately, just as is done
    for shared extent boundaries and/or existing COW reservations that
    happen to overlap the start of the data fork extent. This prevents
    shared/010 failures due to data corruption on reflink enabled
    filesystems.
    Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
    Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
    c3a66bf4
xfs_reflink.c 46.8 KB