Commit c467c049 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Alex Elder
Browse files

xfs: split xfs_bmap_btalloc



Split out the nullfb case into a separate function to reduce the stack
footprint and make the code more readable.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent f7008d0a
Loading
Loading
Loading
Loading
+119 −101
Original line number Diff line number Diff line
@@ -2550,106 +2550,56 @@ xfs_bmap_rtalloc(
}

STATIC int
xfs_bmap_btalloc(
	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
xfs_bmap_btalloc_nullfb(
	struct xfs_bmalloca	*ap,
	struct xfs_alloc_arg	*args,
	xfs_extlen_t		*blen)
{
	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	nextminlen = 0;
	xfs_perag_t	*pag;
	int		nullfb;		/* true if ap->firstblock isn't set */
	int		isaligned;
	int		notinit;
	int		tryagain;
	struct xfs_mount	*mp = ap->ip->i_mount;
	struct xfs_perag	*pag;
	xfs_agnumber_t		ag, startag;
	int			notinit = 0;
	int			error;

	mp = ap->ip->i_mount;
	align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 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) {
		if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
			ag = xfs_filestream_lookup_ag(ap->ip);
			ag = (ag != NULLAGNUMBER) ? ag : 0;
			ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
		} else {
			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;
	args.fsbno = ap->rval;
	args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
	args.firstblock = ap->firstblock;
	blen = 0;
	if (nullfb) {
	if (ap->userdata && xfs_inode_is_filestream(ap->ip))
			args.type = XFS_ALLOCTYPE_NEAR_BNO;
		args->type = XFS_ALLOCTYPE_NEAR_BNO;
	else
			args.type = XFS_ALLOCTYPE_START_BNO;
		args.total = ap->total;
		args->type = XFS_ALLOCTYPE_START_BNO;
	args->total = ap->total;

	/*
		 * Search for an allocation group with a single extent
		 * large enough for the request.
		 *
		 * If one isn't found, then adjust the minimum allocation
		 * size to the largest space found.
	 * Search for an allocation group with a single extent large enough
	 * for the request.  If one isn't found, then adjust the minimum
	 * allocation size to the largest space found.
	 */
		startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
	startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
	if (startag == NULLAGNUMBER)
		startag = ag = 0;
		notinit = 0;

	pag = xfs_perag_get(mp, ag);
		while (blen < ap->alen) {
			if (!pag->pagf_init &&
			    (error = xfs_alloc_pagf_init(mp, args.tp,
				    ag, XFS_ALLOC_FLAG_TRYLOCK))) {
	while (*blen < ap->alen) {
		if (!pag->pagf_init) {
			error = xfs_alloc_pagf_init(mp, args->tp, ag,
						    XFS_ALLOC_FLAG_TRYLOCK);
			if (error) {
				xfs_perag_put(pag);
				return error;
			}
		}

		/*
		 * See xfs_alloc_fix_freelist...
		 */
		if (pag->pagf_init) {
			xfs_extlen_t	longest;
			longest = xfs_alloc_longest_free_extent(mp, pag);
				if (blen < longest)
					blen = longest;
			if (*blen < longest)
				*blen = longest;
		} else
			notinit = 1;

		if (xfs_inode_is_filestream(ap->ip)) {
				if (blen >= ap->alen)
			if (*blen >= ap->alen)
				break;

			if (ap->userdata) {
@@ -2684,31 +2634,99 @@ xfs_bmap_btalloc(
		pag = xfs_perag_get(mp, ag);
	}
	xfs_perag_put(pag);

	/*
	 * Since the above loop did a BUF_TRYLOCK, it is
	 * possible that there is space for this request.
	 */
		if (notinit || blen < ap->minlen)
			args.minlen = ap->minlen;
	if (notinit || *blen < ap->minlen)
		args->minlen = ap->minlen;
	/*
	 * If the best seen length is less than the request
	 * length, use the best as the minimum.
	 */
		else if (blen < ap->alen)
			args.minlen = blen;
	else if (*blen < ap->alen)
		args->minlen = *blen;
	/*
	 * Otherwise we've seen an extent as big as alen,
	 * use that as the minimum.
	 */
	else
			args.minlen = ap->alen;
		args->minlen = ap->alen;

	/*
	 * set the failure fallback case to look in the selected
	 * AG as the stream may have moved.
	 */
	if (xfs_inode_is_filestream(ap->ip))
			ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
		ap->rval = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);

	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	fb_agno;	/* ag number of ap->firstblock */
	xfs_agnumber_t	ag;
	xfs_alloc_arg_t	args;
	xfs_extlen_t	blen;
	xfs_extlen_t	nextminlen = 0;
	int		nullfb;		/* true if ap->firstblock isn't set */
	int		isaligned;
	int		tryagain;
	int		error;

	mp = ap->ip->i_mount;
	align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 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) {
		if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
			ag = xfs_filestream_lookup_ag(ap->ip);
			ag = (ag != NULLAGNUMBER) ? ag : 0;
			ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
		} else {
			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;
	args.fsbno = ap->rval;
	args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
	args.firstblock = ap->firstblock;
	blen = 0;
	if (nullfb) {
		error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
		if (error)
			return error;
	} else if (ap->low) {
		if (xfs_inode_is_filestream(ap->ip))
			args.type = XFS_ALLOCTYPE_FIRST_AG;