mirror of https://gitee.com/openkylin/linux.git
xfs: only reclaim unwritten COW extents periodically
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>
This commit is contained in:
parent
c771c14baa
commit
3802a34532
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -548,14 +548,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;
|
||||
|
@ -579,7 +583,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);
|
||||
|
||||
|
@ -621,13 +625,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;
|
||||
|
@ -653,7 +661,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;
|
||||
|
||||
|
@ -1450,7 +1459,7 @@ xfs_reflink_clear_inode_flag(
|
|||
* 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;
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ extern void xfs_reflink_trim_irec_to_next_cow(struct xfs_inode *ip,
|
|||
|
||||
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);
|
||||
|
|
|
@ -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.",
|
||||
|
|
Loading…
Reference in New Issue