lkml.org 
[lkml]   [2020]   [Aug]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 099/228] xfs: fix reflink quota reservation accounting error
    Date
    From: Darrick J. Wong <darrick.wong@oracle.com>

    [ Upstream commit 83895227aba1ade33e81f586aa7b6b1e143096a5 ]

    Quota reservations are supposed to account for the blocks that might be
    allocated due to a bmap btree split. Reflink doesn't do this, so fix
    this to make the quota accounting more accurate before we start
    rearranging things.

    Fixes: 862bb360ef56 ("xfs: reflink extents from one file to another")
    Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
    Reviewed-by: Brian Foster <bfoster@redhat.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/xfs/xfs_reflink.c | 21 ++++++++++++++-------
    1 file changed, 14 insertions(+), 7 deletions(-)

    diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
    index db7f9fdd20a30..4d37f1b59436c 100644
    --- a/fs/xfs/xfs_reflink.c
    +++ b/fs/xfs/xfs_reflink.c
    @@ -1076,6 +1076,7 @@ xfs_reflink_remap_extent(
    xfs_filblks_t rlen;
    xfs_filblks_t unmap_len;
    xfs_off_t newlen;
    + int64_t qres;
    int error;

    unmap_len = irec->br_startoff + irec->br_blockcount - destoff;
    @@ -1098,13 +1099,19 @@ xfs_reflink_remap_extent(
    xfs_ilock(ip, XFS_ILOCK_EXCL);
    xfs_trans_ijoin(tp, ip, 0);

    - /* If we're not just clearing space, then do we have enough quota? */
    - if (real_extent) {
    - error = xfs_trans_reserve_quota_nblks(tp, ip,
    - irec->br_blockcount, 0, XFS_QMOPT_RES_REGBLKS);
    - if (error)
    - goto out_cancel;
    - }
    + /*
    + * Reserve quota for this operation. We don't know if the first unmap
    + * in the dest file will cause a bmap btree split, so we always reserve
    + * at least enough blocks for that split. If the extent being mapped
    + * in is written, we need to reserve quota for that too.
    + */
    + qres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
    + if (real_extent)
    + qres += irec->br_blockcount;
    + error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0,
    + XFS_QMOPT_RES_REGBLKS);
    + if (error)
    + goto out_cancel;

    trace_xfs_reflink_remap(ip, irec->br_startoff,
    irec->br_blockcount, irec->br_startblock);
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-08-20 12:11    [W:6.943 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site