[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: Nathan Scott <nathans@sgi.com>
This commit is contained in:
@@ -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(
|
|||||||
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(
|
|||||||
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;
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
xfs_bmap_adjacent(ap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Realtime allocation, done through xfs_rtallocate_extent.
|
* Realtime allocation, done through xfs_rtallocate_extent.
|
||||||
*/
|
*/
|
||||||
if (rt) {
|
atype = ap->rval == 0 ? XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
|
||||||
#ifndef __KERNEL__
|
|
||||||
ASSERT(0);
|
|
||||||
#else
|
|
||||||
xfs_rtblock_t rtb;
|
|
||||||
|
|
||||||
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(
|
|||||||
*/
|
*/
|
||||||
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(
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user