Commit 712bae96 authored by Christoph Hellwig's avatar Christoph Hellwig
Browse files

xfs: generalize the freespace and reserved blocks handling



xfs_{add,dec}_freecounter already handles the block and RT extent
percpu counters, but it currently hardcodes the passed in counter.

Add a freecounter abstraction that uses an enum to designate the counter
and add wrappers that hide the actual percpu_counters.  This will allow
expanding the reserved block handling to the RT extent counter in the
next step, and also prepares for adding yet another such counter that
can share the code.  Both these additions will be needed for the zoned
allocator.

Also switch the flooring of the frextents counter to 0 in statfs for the
rthinherit case to a manual min_t call to match the handling of the
fdblocks counter for normal file systems.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
parent cc3d2f55
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1927,7 +1927,7 @@ xfs_dialloc(
	 * that we can immediately allocate, but then we allow allocation on the
	 * second pass if we fail to find an AG with free inodes in it.
	 */
	if (percpu_counter_read_positive(&mp->m_fdblocks) <
	if (xfs_estimate_freecounter(mp, XC_FREE_BLOCKS) <
			mp->m_low_space[XFS_LOWSP_1_PCNT]) {
		ok_alloc = false;
		low_space = true;
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ xfs_metafile_resv_can_cover(
	 * There aren't enough blocks left in the inode's reservation, but it
	 * isn't critical unless there also isn't enough free space.
	 */
	return __percpu_counter_compare(&ip->i_mount->m_fdblocks,
	return xfs_compare_freecounter(ip->i_mount, XC_FREE_BLOCKS,
			rhs - ip->i_delayed_blks, 2048) >= 0;
}

+4 −4
Original line number Diff line number Diff line
@@ -1265,8 +1265,7 @@ xfs_log_sb(
		mp->m_sb.sb_ifree = min_t(uint64_t,
				percpu_counter_sum_positive(&mp->m_ifree),
				mp->m_sb.sb_icount);
		mp->m_sb.sb_fdblocks =
				percpu_counter_sum_positive(&mp->m_fdblocks);
		mp->m_sb.sb_fdblocks = xfs_sum_freecounter(mp, XC_FREE_BLOCKS);
	}

	/*
@@ -1275,9 +1274,10 @@ xfs_log_sb(
	 * we handle nearly-lockless reservations, so we must use the _positive
	 * variant here to avoid writing out nonsense frextents.
	 */
	if (xfs_has_rtgroups(mp))
	if (xfs_has_rtgroups(mp)) {
		mp->m_sb.sb_frextents =
				percpu_counter_sum_positive(&mp->m_frextents);
				xfs_sum_freecounter(mp, XC_FREE_RTEXTENTS);
	}

	xfs_sb_to_disk(bp->b_addr, &mp->m_sb);
	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
+17 −0
Original line number Diff line number Diff line
@@ -233,6 +233,23 @@ enum xfs_group_type {
	{ XG_TYPE_AG,	"ag" }, \
	{ XG_TYPE_RTG,	"rtg" }

enum xfs_free_counter {
	/*
	 * Number of free blocks on the data device.
	 */
	XC_FREE_BLOCKS,

	/*
	 * Number of free RT extents on the RT device.
	 */
	XC_FREE_RTEXTENTS,
	XC_FREE_NR,
};

#define XFS_FREECOUNTER_STR \
	{ XC_FREE_BLOCKS,		"blocks" }, \
	{ XC_FREE_RTEXTENTS,		"rtextents" }

/*
 * Type verifier functions
 */
+6 −5
Original line number Diff line number Diff line
@@ -513,8 +513,8 @@ xchk_fscounters(
	/* Snapshot the percpu counters. */
	icount = percpu_counter_sum(&mp->m_icount);
	ifree = percpu_counter_sum(&mp->m_ifree);
	fdblocks = percpu_counter_sum(&mp->m_fdblocks);
	frextents = percpu_counter_sum(&mp->m_frextents);
	fdblocks = xfs_sum_freecounter_raw(mp, XC_FREE_BLOCKS);
	frextents = xfs_sum_freecounter_raw(mp, XC_FREE_RTEXTENTS);

	/* No negative values, please! */
	if (icount < 0 || ifree < 0)
@@ -589,15 +589,16 @@ xchk_fscounters(
			try_again = true;
	}

	if (!xchk_fscount_within_range(sc, fdblocks, &mp->m_fdblocks,
			fsc->fdblocks)) {
	if (!xchk_fscount_within_range(sc, fdblocks,
			&mp->m_free[XC_FREE_BLOCKS].count, fsc->fdblocks)) {
		if (fsc->frozen)
			xchk_set_corrupt(sc);
		else
			try_again = true;
	}

	if (!xchk_fscount_within_range(sc, frextents, &mp->m_frextents,
	if (!xchk_fscount_within_range(sc, frextents,
			&mp->m_free[XC_FREE_RTEXTENTS].count,
			fsc->frextents - fsc->frextents_delayed)) {
		if (fsc->frozen)
			xchk_set_corrupt(sc);
Loading