Unverified Commit 2212880a authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3833 xfs: fix block space problems

Merge Pull Request from: @ci-robot 
 
PR sync from: Long Li <leo.lilong@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/4W77HTXJVL3MCZ4J5UP2H3LXSX4CVAEG/ 
*** BLURB HERE ***
This patch set fix block space problems

Gao Xiang (1):
  xfs: account extra freespace btree splits for multiple allocations

Guo Xuenan (1):
  xfs: set minleft correctly for randomly sparse inode allocations

yangerkun (2):
  xfs: fix xfs shutdown since we reserve more blocks in agfl fixup
  xfs: longest free extent no need consider postalloc


-- 
2.31.1
 
https://gitee.com/openeuler/kernel/issues/I8TRWW 
 
Link:https://gitee.com/openeuler/kernel/pulls/3833

 

Reviewed-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents ddef94f9 b4d7cd97
Loading
Loading
Loading
Loading
+42 −7
Original line number Diff line number Diff line
@@ -92,6 +92,25 @@ xfs_prealloc_blocks(
 */
#define XFS_ALLOCBT_AGFL_RESERVE	4

/*
 * Twice fixup for the same ag may happen within exact one tp, and the consume
 * of agfl after first fixup may trigger second fixup's failure, then xfs will
 * shutdown. To avoid that, we reserve blocks which can satisfy the second
 * fixup.
 */
xfs_extlen_t
xfs_ag_fixup_aside(
		struct xfs_mount	*mp)
{
	xfs_extlen_t ret;

	ret = 2 * mp->m_alloc_maxlevels;
	if (xfs_has_rmapbt(mp))
		ret += mp->m_rmap_maxlevels;

	return ret;
}

/*
 * Compute the number of blocks that we set aside to guarantee the ability to
 * refill the AGFL and handle a full bmap btree split.
@@ -114,7 +133,8 @@ unsigned int
xfs_alloc_set_aside(
	struct xfs_mount	*mp)
{
	return mp->m_sb.sb_agcount * (XFS_ALLOCBT_AGFL_RESERVE + 4);
	return mp->m_sb.sb_agcount * (XFS_ALLOCBT_AGFL_RESERVE +
			4 + xfs_ag_fixup_aside(mp));
}

/*
@@ -147,6 +167,8 @@ xfs_alloc_ag_max_usable(
	if (xfs_has_reflink(mp))
		blocks++;		/* refcount root block */

	blocks += xfs_ag_fixup_aside(mp);

	return mp->m_sb.sb_agblocks - blocks;
}

@@ -2298,6 +2320,7 @@ xfs_alloc_min_freelist(
static bool
xfs_alloc_space_available(
	struct xfs_alloc_arg	*args,
	xfs_extlen_t		need,
	xfs_extlen_t		min_free,
	int			flags)
{
@@ -2314,7 +2337,7 @@ xfs_alloc_space_available(

	/* do we have enough contiguous free space for the allocation? */
	alloc_len = args->minlen + (args->alignment - 1) + args->minalignslop;
	longest = xfs_alloc_longest_free_extent(pag, min_free, reservation);
	longest = xfs_alloc_longest_free_extent(pag, need, reservation);
	if (longest < alloc_len)
		return false;

@@ -2323,7 +2346,7 @@ xfs_alloc_space_available(
	 * account extra agfl blocks because we are about to defer free them,
	 * making them unavailable until the current transaction commits.
	 */
	agflcount = min_t(xfs_extlen_t, pag->pagf_flcount, min_free);
	agflcount = min_t(xfs_extlen_t, pag->pagf_flcount, need);
	available = (int)(pag->pagf_freeblks + agflcount -
			  reservation - min_free - args->minleft);
	if (available < (int)max(args->total, alloc_len))
@@ -2618,6 +2641,7 @@ xfs_alloc_fix_freelist(
	struct xfs_alloc_arg	targs;	/* local allocation arguments */
	xfs_agblock_t		bno;	/* freelist block */
	xfs_extlen_t		need;	/* total blocks needed in freelist */
	xfs_extlen_t		minfree;
	int			error = 0;

	/* deferred ops (AGFL block frees) require permanent transactions */
@@ -2645,8 +2669,16 @@ xfs_alloc_fix_freelist(
		goto out_agbp_relse;
	}

	need = xfs_alloc_min_freelist(mp, pag);
	if (!xfs_alloc_space_available(args, need, alloc_flags |
	/*
	 * Also need to fulfill freespace btree splits by reservaing more
	 * blocks to perform multiple allocations from a single AG and
	 * transaction if needed.
	 */
	minfree = need = xfs_alloc_min_freelist(mp, pag);
	if (args->postallocs)
		minfree += xfs_ag_fixup_aside(mp);

	if (!xfs_alloc_space_available(args, need, minfree, alloc_flags |
			XFS_ALLOC_FLAG_CHECK))
		goto out_agbp_relse;

@@ -2669,8 +2701,11 @@ xfs_alloc_fix_freelist(
		xfs_agfl_reset(tp, agbp, pag);

	/* If there isn't enough total space or single-extent, reject it. */
	need = xfs_alloc_min_freelist(mp, pag);
	if (!xfs_alloc_space_available(args, need, alloc_flags))
	minfree = need = xfs_alloc_min_freelist(mp, pag);
	if (args->postallocs)
		minfree += xfs_ag_fixup_aside(mp);

	if (!xfs_alloc_space_available(args, need, minfree, alloc_flags))
		goto out_agbp_relse;

#ifdef DEBUG
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ typedef struct xfs_alloc_arg {
	int		datatype;	/* mask defining data type treatment */
	char		wasdel;		/* set if allocation was prev delayed */
	char		wasfromfl;	/* set if allocation is from freelist */
	bool		postallocs;	/* number of post-allocations */
	struct xfs_owner_info	oinfo;	/* owner of blocks being allocated */
	enum xfs_ag_resv_type	resv;	/* block reservation to use */
#ifdef DEBUG
+1 −0
Original line number Diff line number Diff line
@@ -3692,6 +3692,7 @@ xfs_bmap_btalloc(
		.datatype	= ap->datatype,
		.alignment	= 1,
		.minalignslop	= 0,
		.postallocs	= 1,
	};
	xfs_fileoff_t		orig_offset;
	xfs_extlen_t		orig_length;
+3 −0
Original line number Diff line number Diff line
@@ -652,6 +652,7 @@ xfs_ialloc_ag_alloc(
	int			do_sparse = 0;

	memset(&args, 0, sizeof(args));
	args.postallocs = 1;
	args.tp = tp;
	args.mp = tp->t_mountp;
	args.fsbno = NULLFSBLOCK;
@@ -782,6 +783,8 @@ xfs_ialloc_ag_alloc(
		args.alignment = args.mp->m_sb.sb_spino_align;
		args.prod = 1;

		/* Allow space for the inode btree to split */
		args.minleft = igeo->inobt_maxlevels;
		args.minlen = igeo->ialloc_min_blks;
		args.maxlen = args.minlen;

+9 −0
Original line number Diff line number Diff line
@@ -693,6 +693,15 @@ xfs_mountfs(

	xfs_agbtree_compute_maxlevels(mp);

	/*
	 * We now need m_ag_maxlevels/m_rmap_maxlevels to initialize
	 * m_alloc_set_aside/m_ag_max_usable. And when we first do the
	 * init in xfs_sb_mount_common, m_alloc_set_aside/m_ag_max_usable
	 * still equals to 0. Redo it now.
	 */
	mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
	mp->m_ag_max_usable = xfs_alloc_ag_max_usable(mp);

	/*
	 * Check if sb_agblocks is aligned at stripe boundary.  If sb_agblocks
	 * is NOT aligned turn off m_dalign since allocator alignment is within