Commit a365bdd5 authored by Nathan Scott's avatar Nathan Scott

[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
...@@ -2294,25 +2294,15 @@ xfs_bmap_extsize_align( ...@@ -2294,25 +2294,15 @@ xfs_bmap_extsize_align(
#define XFS_ALLOC_GAP_UNITS 4 #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 STATIC int
xfs_bmap_alloc( xfs_bmap_adjacent(
xfs_bmalloca_t *ap) /* bmap alloc argument struct */ xfs_bmalloca_t *ap) /* bmap alloc argument struct */
{ {
xfs_fsblock_t adjust; /* adjustment to block numbers */ 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_agnumber_t fb_agno; /* ag number of ap->firstblock */
xfs_mount_t *mp; /* mount point structure */ xfs_mount_t *mp; /* mount point structure */
int nullfb; /* true if ap->firstblock isn't set */ int nullfb; /* true if ap->firstblock isn't set */
int rt; /* true if inode is realtime */ 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) \ #define ISVALID(x,y) \
(rt ? \ (rt ? \
...@@ -2321,75 +2311,10 @@ xfs_bmap_alloc( ...@@ -2321,75 +2311,10 @@ xfs_bmap_alloc(
XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \ XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
/*
* Set up variables.
*/
mp = ap->ip->i_mount; mp = ap->ip->i_mount;
nullfb = ap->firstblock == NULLFSBLOCK; nullfb = ap->firstblock == NULLFSBLOCK;
rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); 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, * If allocating at eof, and there's a previous real block,
* try to use it's last block as our starting point. * try to use it's last block as our starting point.
...@@ -2514,25 +2439,73 @@ xfs_bmap_alloc( ...@@ -2514,25 +2439,73 @@ xfs_bmap_alloc(
else if (gotbno != NULLFSBLOCK) else if (gotbno != NULLFSBLOCK)
ap->rval = gotbno; 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 * If the offset & length are not perfectly aligned
* it's in the right allocation group. * then kill prod, it will just get us in trouble.
*/ */
if (nullfb || rt || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno) if (do_mod(ap->off, align) || ap->alen % align)
; prod = 1;
else
ap->rval = ap->firstblock;
/* /*
* Realtime allocation, done through xfs_rtallocate_extent. * Set ralen to be the actual requested length in rtextents.
*/ */
if (rt) { ralen = ap->alen / mp->m_sb.sb_rextsize;
#ifndef __KERNEL__ /*
ASSERT(0); * If the old value was close enough to MAXEXTLEN that
#else * we rounded up to it, cut it back so it's valid again.
xfs_rtblock_t rtb; * 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_bmap_adjacent(ap);
XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
/*
* 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); do_div(ap->rval, mp->m_sb.sb_rextsize);
rtb = ap->rval; rtb = ap->rval;
ap->alen = ralen; ap->alen = ralen;
...@@ -2559,29 +2532,67 @@ xfs_bmap_alloc( ...@@ -2559,29 +2532,67 @@ xfs_bmap_alloc(
*/ */
XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
XFS_TRANS_DQ_RTBCOUNT, XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
(long) ralen); } else {
} else
ap->alen = 0; ap->alen = 0;
#endif /* __KERNEL__ */
} }
/* return 0;
* Normal allocation, done through xfs_alloc_vextent. }
*/
else { 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 ag;
xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */
xfs_agnumber_t startag;
xfs_alloc_arg_t args; xfs_alloc_arg_t args;
xfs_extlen_t blen; xfs_extlen_t blen;
xfs_extlen_t delta; xfs_extlen_t delta;
int isaligned;
xfs_extlen_t longest; xfs_extlen_t longest;
xfs_extlen_t need; xfs_extlen_t need;
xfs_extlen_t nextminlen=0; xfs_extlen_t nextminlen = 0;
int notinit;
xfs_perag_t *pag; xfs_perag_t *pag;
xfs_agnumber_t startag; int nullfb; /* true if ap->firstblock isn't set */
int isaligned;
int notinit;
int tryagain; 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; tryagain = isaligned = 0;
args.tp = ap->tp; args.tp = ap->tp;
args.mp = mp; args.mp = mp;
...@@ -2786,9 +2797,20 @@ xfs_bmap_alloc( ...@@ -2786,9 +2797,20 @@ xfs_bmap_alloc(
ap->rval = NULLFSBLOCK; ap->rval = NULLFSBLOCK;
ap->alen = 0; ap->alen = 0;
} }
}
return 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);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment