Commit f76823e3 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Carlos Maiolino
Browse files

xfs: split xfs_zone_record_blocks



xfs_zone_record_blocks not only records successfully written blocks that
now back file data, but is also used for blocks speculatively written by
garbage collection that were never linked to an inode and instantly
become invalid.

Split the latter functionality out to be easier to understand.  This also
make it clear that we don't need to attach the rmap inode to a
transaction for the skipped blocks case as we never dirty any peristent
data structure.

Also make the argument order to xfs_zone_record_blocks a bit more
natural.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarCarlos Maiolino <cem@kernel.org>
parent 5d94b19f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -455,6 +455,7 @@ DEFINE_EVENT(xfs_zone_alloc_class, name, \
		 xfs_extlen_t len),				\
	TP_ARGS(oz, rgbno, len))
DEFINE_ZONE_ALLOC_EVENT(xfs_zone_record_blocks);
DEFINE_ZONE_ALLOC_EVENT(xfs_zone_skip_blocks);
DEFINE_ZONE_ALLOC_EVENT(xfs_zone_alloc_blocks);

TRACE_EVENT(xfs_zone_gc_select_victim,
+29 −13
Original line number Diff line number Diff line
@@ -166,10 +166,9 @@ xfs_open_zone_mark_full(
static void
xfs_zone_record_blocks(
	struct xfs_trans	*tp,
	xfs_fsblock_t		fsbno,
	xfs_filblks_t		len,
	struct xfs_open_zone	*oz,
	bool			used)
	xfs_fsblock_t		fsbno,
	xfs_filblks_t		len)
{
	struct xfs_mount	*mp = tp->t_mountp;
	struct xfs_rtgroup	*rtg = oz->oz_rtg;
@@ -179,18 +178,37 @@ xfs_zone_record_blocks(

	xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
	xfs_rtgroup_trans_join(tp, rtg, XFS_RTGLOCK_RMAP);
	if (used) {
	rmapip->i_used_blocks += len;
	ASSERT(rmapip->i_used_blocks <= rtg_blocks(rtg));
	} else {
		xfs_add_frextents(mp, len);
	}
	oz->oz_written += len;
	if (oz->oz_written == rtg_blocks(rtg))
		xfs_open_zone_mark_full(oz);
	xfs_trans_log_inode(tp, rmapip, XFS_ILOG_CORE);
}

/*
 * Called for blocks that have been written to disk, but not actually linked to
 * an inode, which can happen when garbage collection races with user data
 * writes to a file.
 */
static void
xfs_zone_skip_blocks(
	struct xfs_open_zone	*oz,
	xfs_filblks_t		len)
{
	struct xfs_rtgroup	*rtg = oz->oz_rtg;

	trace_xfs_zone_skip_blocks(oz, 0, len);

	xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
	oz->oz_written += len;
	if (oz->oz_written == rtg_blocks(rtg))
		xfs_open_zone_mark_full(oz);
	xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP);

	xfs_add_frextents(rtg_mount(rtg), len);
}

static int
xfs_zoned_map_extent(
	struct xfs_trans	*tp,
@@ -250,8 +268,7 @@ xfs_zoned_map_extent(
		}
	}

	xfs_zone_record_blocks(tp, new->br_startblock, new->br_blockcount, oz,
			true);
	xfs_zone_record_blocks(tp, oz, new->br_startblock, new->br_blockcount);

	/* Map the new blocks into the data fork. */
	xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, new);
@@ -259,8 +276,7 @@ xfs_zoned_map_extent(

skip:
	trace_xfs_reflink_cow_remap_skip(ip, new);
	xfs_zone_record_blocks(tp, new->br_startblock, new->br_blockcount, oz,
			false);
	xfs_zone_skip_blocks(oz, new->br_blockcount);
	return 0;
}