Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a365bdd5 authored by Nathan Scott's avatar Nathan Scott
Browse files

[XFS] Reduce stack usage within xfs_bmapi by rearranging some code,


splitting realtime/btree allocators apart.  Based on Glens original
patches.

SGI-PV: 947312
SGI-Modid: xfs-linux-melb:xfs-kern:25372a

Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent 39269e29
Loading
Loading
Loading
Loading
+345 −323
Original line number Diff line number Diff line
@@ -2294,25 +2294,15 @@ xfs_bmap_extsize_align(

#define XFS_ALLOC_GAP_UNITS	4

/*
 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
 * It figures out where to ask the underlying allocator to put the new extent.
 */
STATIC int
xfs_bmap_alloc(
xfs_bmap_adjacent(
	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
{
	xfs_fsblock_t	adjust;		/* adjustment to block numbers */
	xfs_alloctype_t	atype=0;	/* type for allocation routines */
	int		error;		/* error return value */
	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
	xfs_mount_t	*mp;		/* mount point structure */
	int		nullfb;		/* true if ap->firstblock isn't set */
	int		rt;		/* true if inode is realtime */
	xfs_extlen_t	prod = 0;	/* product factor for allocators */
	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
	xfs_extlen_t	align;		/* minimum allocation alignment */
	xfs_rtblock_t	rtx;

#define	ISVALID(x,y)	\
	(rt ? \
@@ -2321,75 +2311,10 @@ xfs_bmap_alloc(
		XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
		XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)

	/*
	 * Set up variables.
	 */
	mp = ap->ip->i_mount;
	nullfb = ap->firstblock == NULLFSBLOCK;
	rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
	if (rt) {
		align = ap->ip->i_d.di_extsize ?
			ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
		/* Set prod to match the extent size */
		prod = align / mp->m_sb.sb_rextsize;

		error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
						align, rt, ap->eof, 0,
						ap->conv, &ap->off, &ap->alen);
		if (error)
			return error;
		ASSERT(ap->alen);
		ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);

		/*
		 * If the offset & length are not perfectly aligned
		 * then kill prod, it will just get us in trouble.
		 */
		if (do_mod(ap->off, align) || ap->alen % align)
			prod = 1;
		/*
		 * Set ralen to be the actual requested length in rtextents.
		 */
		ralen = ap->alen / mp->m_sb.sb_rextsize;
		/*
		 * If the old value was close enough to MAXEXTLEN that
		 * we rounded up to it, cut it back so it's valid again.
		 * Note that if it's a really large request (bigger than
		 * MAXEXTLEN), we don't hear about that number, and can't
		 * adjust the starting point to match it.
		 */
		if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
			ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
		/*
		 * If it's an allocation to an empty file at offset 0,
		 * pick an extent that will space things out in the rt area.
		 */
		if (ap->eof && ap->off == 0) {
			error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
			if (error)
				return error;
			ap->rval = rtx * mp->m_sb.sb_rextsize;
		} else
			ap->rval = 0;
	} else {
		align = (ap->userdata && ap->ip->i_d.di_extsize &&
			(ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
			ap->ip->i_d.di_extsize : 0;
		if (unlikely(align)) {
			error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
							align, rt,
							ap->eof, 0, ap->conv,
							&ap->off, &ap->alen);
			ASSERT(!error);
			ASSERT(ap->alen);
		}
		if (nullfb)
			ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
		else
			ap->rval = ap->firstblock;
	}

	/*
	 * If allocating at eof, and there's a previous real block,
	 * try to use it's last block as our starting point.
@@ -2514,25 +2439,73 @@ xfs_bmap_alloc(
		else if (gotbno != NULLFSBLOCK)
			ap->rval = gotbno;
	}
#undef ISVALID
	return 0;
}

STATIC int
xfs_bmap_rtalloc(
	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
{
	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
	int		error;		/* error return value */
	xfs_mount_t	*mp;		/* mount point structure */
	xfs_extlen_t	prod = 0;	/* product factor for allocators */
	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
	xfs_extlen_t	align;		/* minimum allocation alignment */
	xfs_rtblock_t	rtx;		/* realtime extent number */
	xfs_rtblock_t	rtb;

	mp = ap->ip->i_mount;
	align = ap->ip->i_d.di_extsize ?
		ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
	prod = align / mp->m_sb.sb_rextsize;
	error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
					align, 1, ap->eof, 0,
					ap->conv, &ap->off, &ap->alen);
	if (error)
		return error;
	ASSERT(ap->alen);
	ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);

	/*
	 * If allowed, use ap->rval; otherwise must use firstblock since
	 * it's in the right allocation group.
	 * If the offset & length are not perfectly aligned
	 * then kill prod, it will just get us in trouble.
	 */
	if (nullfb || rt || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
		;
	else
		ap->rval = ap->firstblock;
	if (do_mod(ap->off, align) || ap->alen % align)
		prod = 1;
	/*
	 * Realtime allocation, done through xfs_rtallocate_extent.
	 * Set ralen to be the actual requested length in rtextents.
	 */
	if (rt) {
#ifndef __KERNEL__
		ASSERT(0);
#else
		xfs_rtblock_t	rtb;
	ralen = ap->alen / mp->m_sb.sb_rextsize;
	/*
	 * If the old value was close enough to MAXEXTLEN that
	 * we rounded up to it, cut it back so it's valid again.
	 * Note that if it's a really large request (bigger than
	 * MAXEXTLEN), we don't hear about that number, and can't
	 * adjust the starting point to match it.
	 */
	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
	/*
	 * If it's an allocation to an empty file at offset 0,
	 * pick an extent that will space things out in the rt area.
	 */
	if (ap->eof && ap->off == 0) {
		error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
		if (error)
			return error;
		ap->rval = rtx * mp->m_sb.sb_rextsize;
	} else {
		ap->rval = 0;
	}

		atype = ap->rval == 0 ?
			XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
	xfs_bmap_adjacent(ap);

	/*
	 * Realtime allocation, done through xfs_rtallocate_extent.
	 */
	atype = ap->rval == 0 ?  XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
	do_div(ap->rval, mp->m_sb.sb_rextsize);
	rtb = ap->rval;
	ap->alen = ralen;
@@ -2559,29 +2532,67 @@ xfs_bmap_alloc(
		 */
		XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
			ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
						XFS_TRANS_DQ_RTBCOUNT,
				(long) ralen);
		} else
					XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
	} else {
		ap->alen = 0;
#endif	/* __KERNEL__ */
	}
	/*
	 * Normal allocation, done through xfs_alloc_vextent.
	 */
	else {
	return 0;
}

STATIC int
xfs_bmap_btalloc(
	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
{
	xfs_mount_t	*mp;		/* mount point structure */
	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
	xfs_extlen_t	align;		/* minimum allocation alignment */
	xfs_agnumber_t	ag;
	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
	xfs_agnumber_t	startag;
	xfs_alloc_arg_t	args;
	xfs_extlen_t	blen;
	xfs_extlen_t	delta;
		int		isaligned;
	xfs_extlen_t	longest;
	xfs_extlen_t	need;
	xfs_extlen_t	nextminlen = 0;
		int		notinit;
	xfs_perag_t	*pag;
		xfs_agnumber_t	startag;
	int		nullfb;		/* true if ap->firstblock isn't set */
	int		isaligned;
	int		notinit;
	int		tryagain;
	int		error;

	mp = ap->ip->i_mount;
	align = (ap->userdata && ap->ip->i_d.di_extsize &&
		(ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
		ap->ip->i_d.di_extsize : 0;
	if (unlikely(align)) {
		error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
						align, 0, ap->eof, 0, ap->conv,
						&ap->off, &ap->alen);
		ASSERT(!error);
		ASSERT(ap->alen);
	}
	nullfb = ap->firstblock == NULLFSBLOCK;
	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
	if (nullfb)
		ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
	else
		ap->rval = ap->firstblock;

	xfs_bmap_adjacent(ap);

	/*
	 * If allowed, use ap->rval; otherwise must use firstblock since
	 * it's in the right allocation group.
	 */
	if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
		;
	else
		ap->rval = ap->firstblock;
	/*
	 * Normal allocation, done through xfs_alloc_vextent.
	 */
	tryagain = isaligned = 0;
	args.tp = ap->tp;
	args.mp = mp;
@@ -2786,9 +2797,20 @@ xfs_bmap_alloc(
		ap->rval = NULLFSBLOCK;
		ap->alen = 0;
	}
	}
	return 0;
#undef	ISVALID
}

/*
 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
 * It figures out where to ask the underlying allocator to put the new extent.
 */
STATIC int
xfs_bmap_alloc(
	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
{
	if ((ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata)
		return xfs_bmap_rtalloc(ap);
	return xfs_bmap_btalloc(ap);
}

/*