lkml.org 
[lkml]   [2017]   [Apr]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.10 24/81] xfs: only reclaim unwritten COW extents periodically
    Date
    4.10-stable review patch.  If anyone has any objections, please let me know.

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

    From: Christoph Hellwig <hch@lst.de>

    commit 3802a345321a08093ba2ddb1849e736f84e8d450 upstream.

    We only want to reclaim preallocations from our periodic work item.
    Currently this is archived by looking for a dirty inode, but that check
    is rather fragile. Instead add a flag to xfs_reflink_cancel_cow_* so
    that the caller can ask for just cancelling unwritten extents in the COW
    fork.

    Signed-off-by: Christoph Hellwig <hch@lst.de>
    Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
    [darrick: fix typos in commit message]
    Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/xfs/xfs_aops.c | 2 +-
    fs/xfs/xfs_icache.c | 2 +-
    fs/xfs/xfs_inode.c | 2 +-
    fs/xfs/xfs_reflink.c | 23 ++++++++++++++++-------
    fs/xfs/xfs_reflink.h | 4 ++--
    fs/xfs/xfs_super.c | 2 +-
    6 files changed, 22 insertions(+), 13 deletions(-)

    --- a/fs/xfs/xfs_aops.c
    +++ b/fs/xfs/xfs_aops.c
    @@ -293,7 +293,7 @@ xfs_end_io(
    goto done;
    if (ioend->io_bio->bi_error) {
    error = xfs_reflink_cancel_cow_range(ip,
    - ioend->io_offset, ioend->io_size);
    + ioend->io_offset, ioend->io_size, true);
    goto done;
    }
    error = xfs_reflink_end_cow(ip, ioend->io_offset,
    --- a/fs/xfs/xfs_icache.c
    +++ b/fs/xfs/xfs_icache.c
    @@ -1608,7 +1608,7 @@ xfs_inode_free_cowblocks(
    xfs_ilock(ip, XFS_IOLOCK_EXCL);
    xfs_ilock(ip, XFS_MMAPLOCK_EXCL);

    - ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF);
    + ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, false);

    xfs_iunlock(ip, XFS_MMAPLOCK_EXCL);
    xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    --- a/fs/xfs/xfs_inode.c
    +++ b/fs/xfs/xfs_inode.c
    @@ -1615,7 +1615,7 @@ xfs_itruncate_extents(

    /* Remove all pending CoW reservations. */
    error = xfs_reflink_cancel_cow_blocks(ip, &tp, first_unmap_block,
    - last_block);
    + last_block, true);
    if (error)
    goto out;

    --- a/fs/xfs/xfs_reflink.c
    +++ b/fs/xfs/xfs_reflink.c
    @@ -549,14 +549,18 @@ xfs_reflink_trim_irec_to_next_cow(
    }

    /*
    - * Cancel all pending CoW reservations for some block range of an inode.
    + * Cancel CoW reservations for some block range of an inode.
    + *
    + * If cancel_real is true this function cancels all COW fork extents for the
    + * inode; if cancel_real is false, real extents are not cleared.
    */
    int
    xfs_reflink_cancel_cow_blocks(
    struct xfs_inode *ip,
    struct xfs_trans **tpp,
    xfs_fileoff_t offset_fsb,
    - xfs_fileoff_t end_fsb)
    + xfs_fileoff_t end_fsb,
    + bool cancel_real)
    {
    struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
    struct xfs_bmbt_irec got, del;
    @@ -580,7 +584,7 @@ xfs_reflink_cancel_cow_blocks(
    &idx, &got, &del);
    if (error)
    break;
    - } else {
    + } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
    xfs_trans_ijoin(*tpp, ip, 0);
    xfs_defer_init(&dfops, &firstfsb);

    @@ -622,13 +626,17 @@ xfs_reflink_cancel_cow_blocks(
    }

    /*
    - * Cancel all pending CoW reservations for some byte range of an inode.
    + * Cancel CoW reservations for some byte range of an inode.
    + *
    + * If cancel_real is true this function cancels all COW fork extents for the
    + * inode; if cancel_real is false, real extents are not cleared.
    */
    int
    xfs_reflink_cancel_cow_range(
    struct xfs_inode *ip,
    xfs_off_t offset,
    - xfs_off_t count)
    + xfs_off_t count,
    + bool cancel_real)
    {
    struct xfs_trans *tp;
    xfs_fileoff_t offset_fsb;
    @@ -654,7 +662,8 @@ xfs_reflink_cancel_cow_range(
    xfs_trans_ijoin(tp, ip, 0);

    /* Scrape out the old CoW reservations */
    - error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb);
    + error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb,
    + cancel_real);
    if (error)
    goto out_cancel;

    @@ -1451,7 +1460,7 @@ next:
    * We didn't find any shared blocks so turn off the reflink flag.
    * First, get rid of any leftover CoW mappings.
    */
    - error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF);
    + error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true);
    if (error)
    return error;

    --- a/fs/xfs/xfs_reflink.h
    +++ b/fs/xfs/xfs_reflink.h
    @@ -39,9 +39,9 @@ extern void xfs_reflink_trim_irec_to_nex

    extern int xfs_reflink_cancel_cow_blocks(struct xfs_inode *ip,
    struct xfs_trans **tpp, xfs_fileoff_t offset_fsb,
    - xfs_fileoff_t end_fsb);
    + xfs_fileoff_t end_fsb, bool cancel_real);
    extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset,
    - xfs_off_t count);
    + xfs_off_t count, bool cancel_real);
    extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
    xfs_off_t count);
    extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
    --- a/fs/xfs/xfs_super.c
    +++ b/fs/xfs/xfs_super.c
    @@ -953,7 +953,7 @@ xfs_fs_destroy_inode(
    XFS_STATS_INC(ip->i_mount, vn_remove);

    if (xfs_is_reflink_inode(ip)) {
    - error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF);
    + error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true);
    if (error && !XFS_FORCED_SHUTDOWN(ip->i_mount))
    xfs_warn(ip->i_mount,
    "Error %d while evicting CoW blocks for inode %llu.",

    \
     
     \ /
      Last update: 2017-04-06 11:06    [W:4.527 / U:0.568 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site