Commit 52f80706 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: support deferred bmap updates on the attr fork



The deferred bmap update log item has always supported the attr fork, so
plumb this in so that higher layers can access this.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 1b5453ba
Loading
Loading
Loading
Loading
+19 −28
Original line number Diff line number Diff line
@@ -6172,17 +6172,8 @@ xfs_bmap_split_extent(
	return error;
}

/* Deferred mapping is only for real extents in the data fork. */
static bool
xfs_bmap_is_update_needed(
	struct xfs_bmbt_irec	*bmap)
{
	return  bmap->br_startblock != HOLESTARTBLOCK &&
		bmap->br_startblock != DELAYSTARTBLOCK;
}

/* Record a bmap intent. */
static int
static inline void
__xfs_bmap_add(
	struct xfs_trans		*tp,
	enum xfs_bmap_intent_type	type,
@@ -6192,6 +6183,11 @@ __xfs_bmap_add(
{
	struct xfs_bmap_intent		*bi;

	if ((whichfork != XFS_DATA_FORK && whichfork != XFS_ATTR_FORK) ||
	    bmap->br_startblock == HOLESTARTBLOCK ||
	    bmap->br_startblock == DELAYSTARTBLOCK)
		return;

	bi = kmem_cache_alloc(xfs_bmap_intent_cache, GFP_KERNEL | __GFP_NOFAIL);
	INIT_LIST_HEAD(&bi->bi_list);
	bi->bi_type = type;
@@ -6200,7 +6196,6 @@ __xfs_bmap_add(
	bi->bi_bmap = *bmap;

	xfs_bmap_defer_add(tp, bi);
	return 0;
}

/* Map an extent into a file. */
@@ -6208,12 +6203,10 @@ void
xfs_bmap_map_extent(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	int			whichfork,
	struct xfs_bmbt_irec	*PREV)
{
	if (!xfs_bmap_is_update_needed(PREV))
		return;

	__xfs_bmap_add(tp, XFS_BMAP_MAP, ip, XFS_DATA_FORK, PREV);
	__xfs_bmap_add(tp, XFS_BMAP_MAP, ip, whichfork, PREV);
}

/* Unmap an extent out of a file. */
@@ -6221,12 +6214,10 @@ void
xfs_bmap_unmap_extent(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	int			whichfork,
	struct xfs_bmbt_irec	*PREV)
{
	if (!xfs_bmap_is_update_needed(PREV))
		return;

	__xfs_bmap_add(tp, XFS_BMAP_UNMAP, ip, XFS_DATA_FORK, PREV);
	__xfs_bmap_add(tp, XFS_BMAP_UNMAP, ip, whichfork, PREV);
}

/*
@@ -6240,29 +6231,29 @@ xfs_bmap_finish_one(
{
	struct xfs_bmbt_irec		*bmap = &bi->bi_bmap;
	int				error = 0;
	int				flags = 0;

	if (bi->bi_whichfork == XFS_ATTR_FORK)
		flags |= XFS_BMAPI_ATTRFORK;

	ASSERT(tp->t_highest_agno == NULLAGNUMBER);

	trace_xfs_bmap_deferred(bi);

	if (WARN_ON_ONCE(bi->bi_whichfork != XFS_DATA_FORK)) {
		xfs_bmap_mark_sick(bi->bi_owner, bi->bi_whichfork);
		return -EFSCORRUPTED;
	}

	if (XFS_TEST_ERROR(false, tp->t_mountp,
			XFS_ERRTAG_BMAP_FINISH_ONE))
	if (XFS_TEST_ERROR(false, tp->t_mountp, XFS_ERRTAG_BMAP_FINISH_ONE))
		return -EIO;

	switch (bi->bi_type) {
	case XFS_BMAP_MAP:
		error = xfs_bmapi_remap(tp, bi->bi_owner, bmap->br_startoff,
				bmap->br_blockcount, bmap->br_startblock, 0);
				bmap->br_blockcount, bmap->br_startblock,
				flags);
		bmap->br_blockcount = 0;
		break;
	case XFS_BMAP_UNMAP:
		error = __xfs_bunmapi(tp, bi->bi_owner, bmap->br_startoff,
				&bmap->br_blockcount, XFS_BMAPI_REMAP, 1);
				&bmap->br_blockcount, flags | XFS_BMAPI_REMAP,
				1);
		break;
	default:
		ASSERT(0);
+2 −2
Original line number Diff line number Diff line
@@ -247,9 +247,9 @@ struct xfs_bmap_intent {

int	xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_bmap_intent *bi);
void	xfs_bmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
		struct xfs_bmbt_irec *imap);
		int whichfork, struct xfs_bmbt_irec *imap);
void	xfs_bmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
		struct xfs_bmbt_irec *imap);
		int whichfork, struct xfs_bmbt_irec *imap);

static inline uint32_t xfs_bmap_fork_to_state(int whichfork)
{
+4 −4
Original line number Diff line number Diff line
@@ -1305,16 +1305,16 @@ xfs_swap_extent_rmap(
			}

			/* Remove the mapping from the donor file. */
			xfs_bmap_unmap_extent(tp, tip, &uirec);
			xfs_bmap_unmap_extent(tp, tip, XFS_DATA_FORK, &uirec);

			/* Remove the mapping from the source file. */
			xfs_bmap_unmap_extent(tp, ip, &irec);
			xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &irec);

			/* Map the donor file's blocks into the source file. */
			xfs_bmap_map_extent(tp, ip, &uirec);
			xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, &uirec);

			/* Map the source file's blocks into the donor file. */
			xfs_bmap_map_extent(tp, tip, &irec);
			xfs_bmap_map_extent(tp, tip, XFS_DATA_FORK, &irec);

			error = xfs_defer_finish(tpp);
			tp = *tpp;
+4 −4
Original line number Diff line number Diff line
@@ -806,7 +806,7 @@ xfs_reflink_end_cow_extent(
		 * If the extent we're remapping is backed by storage (written
		 * or not), unmap the extent and drop its refcount.
		 */
		xfs_bmap_unmap_extent(tp, ip, &data);
		xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &data);
		xfs_refcount_decrease_extent(tp, &data);
		xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT,
				-data.br_blockcount);
@@ -830,7 +830,7 @@ xfs_reflink_end_cow_extent(
	xfs_refcount_free_cow_extent(tp, del.br_startblock, del.br_blockcount);

	/* Map the new blocks into the data fork. */
	xfs_bmap_map_extent(tp, ip, &del);
	xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, &del);

	/* Charge this new data fork mapping to the on-disk quota. */
	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT,
@@ -1294,7 +1294,7 @@ xfs_reflink_remap_extent(
		 * If the extent we're unmapping is backed by storage (written
		 * or not), unmap the extent and drop its refcount.
		 */
		xfs_bmap_unmap_extent(tp, ip, &smap);
		xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &smap);
		xfs_refcount_decrease_extent(tp, &smap);
		qdelta -= smap.br_blockcount;
	} else if (smap.br_startblock == DELAYSTARTBLOCK) {
@@ -1319,7 +1319,7 @@ xfs_reflink_remap_extent(
	 */
	if (dmap_written) {
		xfs_refcount_increase_extent(tp, dmap);
		xfs_bmap_map_extent(tp, ip, dmap);
		xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, dmap);
		qdelta += dmap->br_blockcount;
	}