Commit cce77bcf authored by Dave Chinner's avatar Dave Chinner Committed by Darrick J. Wong

xfs: factor out AG header initialisation from growfs core

The intialisation of new AG headers is mostly common with the
userspace mkfs code and growfs in the kernel, so start factoring it
out so we can move it to libxfs and use it in both places.
Signed-Off-By: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 879de98e
......@@ -71,77 +71,27 @@ xfs_growfs_get_hdr_buf(
return bp;
}
static int
xfs_growfs_data_private(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_growfs_data_t *in) /* growfs data input struct */
{
xfs_agf_t *agf;
struct xfs_agfl *agfl;
xfs_agi_t *agi;
xfs_agnumber_t agno;
xfs_extlen_t agsize;
xfs_extlen_t tmpsize;
xfs_alloc_rec_t *arec;
xfs_buf_t *bp;
int bucket;
int dpct;
int error, saved_error = 0;
xfs_agnumber_t nagcount;
xfs_agnumber_t nagimax = 0;
xfs_rfsblock_t nb, nb_mod;
xfs_rfsblock_t new;
xfs_rfsblock_t nfree;
xfs_agnumber_t oagcount;
int pct;
xfs_trans_t *tp;
nb = in->newblocks;
pct = in->imaxpct;
if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
return -EINVAL;
if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
return error;
dpct = pct - mp->m_sb.sb_imax_pct;
error = xfs_buf_read_uncached(mp->m_ddev_targp,
XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
if (error)
return error;
xfs_buf_relse(bp);
new = nb; /* use new as a temporary here */
nb_mod = do_div(new, mp->m_sb.sb_agblocks);
nagcount = new + (nb_mod != 0);
if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
nagcount--;
nb = (xfs_rfsblock_t)nagcount * mp->m_sb.sb_agblocks;
if (nb < mp->m_sb.sb_dblocks)
return -EINVAL;
}
new = nb - mp->m_sb.sb_dblocks;
oagcount = mp->m_sb.sb_agcount;
/* allocate the new per-ag structures */
if (nagcount > oagcount) {
error = xfs_initialize_perag(mp, nagcount, &nagimax);
if (error)
return error;
}
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp);
if (error)
return error;
/*
/*
* Write new AG headers to disk. Non-transactional, but written
* synchronously so they are completed prior to the growfs transaction
* being logged.
*/
nfree = 0;
for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
static int
xfs_grow_ag_headers(
struct xfs_mount *mp,
xfs_agnumber_t agno,
xfs_extlen_t agsize,
xfs_rfsblock_t *nfree)
{
struct xfs_agf *agf;
struct xfs_agi *agi;
struct xfs_agfl *agfl;
__be32 *agfl_bno;
xfs_alloc_rec_t *arec;
struct xfs_buf *bp;
int bucket;
xfs_extlen_t tmpsize;
int error = 0;
/*
* AG freespace header block
......@@ -152,19 +102,13 @@ xfs_growfs_data_private(
&xfs_agf_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
agf = XFS_BUF_TO_AGF(bp);
agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
agf->agf_seqno = cpu_to_be32(agno);
if (agno == nagcount - 1)
agsize =
nb -
(agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
else
agsize = mp->m_sb.sb_agblocks;
agf->agf_length = cpu_to_be32(agsize);
agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp));
agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
......@@ -195,7 +139,7 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
/*
* AG freelist header block
......@@ -206,7 +150,7 @@ xfs_growfs_data_private(
&xfs_agfl_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
agfl = XFS_BUF_TO_AGFL(bp);
......@@ -223,7 +167,7 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
/*
* AG inode header block
......@@ -234,7 +178,7 @@ xfs_growfs_data_private(
&xfs_agi_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
agi = XFS_BUF_TO_AGI(bp);
......@@ -260,7 +204,7 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
/*
* BNO btree root block
......@@ -272,7 +216,7 @@ xfs_growfs_data_private(
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, agno, 0);
......@@ -285,7 +229,7 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
/*
* CNT btree root block
......@@ -296,7 +240,7 @@ xfs_growfs_data_private(
&xfs_allocbt_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, agno, 0);
......@@ -305,12 +249,12 @@ xfs_growfs_data_private(
arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
arec->ar_blockcount = cpu_to_be32(
agsize - be32_to_cpu(arec->ar_startblock));
nfree += be32_to_cpu(arec->ar_blockcount);
*nfree += be32_to_cpu(arec->ar_blockcount);
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
/* RMAP btree root block */
if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
......@@ -323,7 +267,7 @@ xfs_growfs_data_private(
&xfs_rmapbt_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
xfs_btree_init_block(mp, bp, XFS_BTNUM_RMAP, 0, 0,
......@@ -375,8 +319,7 @@ xfs_growfs_data_private(
/* account for refc btree root */
if (xfs_sb_version_hasreflink(&mp->m_sb)) {
rrec = XFS_RMAP_REC_ADDR(block, 5);
rrec->rm_startblock = cpu_to_be32(
xfs_refc_block(mp));
rrec->rm_startblock = cpu_to_be32(xfs_refc_block(mp));
rrec->rm_blockcount = cpu_to_be32(1);
rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC);
rrec->rm_offset = 0;
......@@ -386,7 +329,7 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
}
/*
......@@ -398,7 +341,7 @@ xfs_growfs_data_private(
&xfs_inobt_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
xfs_btree_init_block(mp, bp, XFS_BTNUM_INO , 0, 0, agno, 0);
......@@ -406,7 +349,7 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
/*
* FINO btree root block
......@@ -418,7 +361,7 @@ xfs_growfs_data_private(
&xfs_inobt_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
xfs_btree_init_block(mp, bp, XFS_BTNUM_FINO,
......@@ -427,7 +370,7 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
}
/*
......@@ -440,7 +383,7 @@ xfs_growfs_data_private(
&xfs_refcountbt_buf_ops);
if (!bp) {
error = -ENOMEM;
goto error0;
goto out_error;
}
xfs_btree_init_block(mp, bp, XFS_BTNUM_REFC,
......@@ -449,10 +392,92 @@ xfs_growfs_data_private(
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
goto error0;
goto out_error;
}
out_error:
return error;
}
static int
xfs_growfs_data_private(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_growfs_data_t *in) /* growfs data input struct */
{
xfs_agf_t *agf;
xfs_agi_t *agi;
xfs_agnumber_t agno;
xfs_extlen_t agsize;
xfs_buf_t *bp;
int dpct;
int error, saved_error = 0;
xfs_agnumber_t nagcount;
xfs_agnumber_t nagimax = 0;
xfs_rfsblock_t nb, nb_mod;
xfs_rfsblock_t new;
xfs_rfsblock_t nfree;
xfs_agnumber_t oagcount;
int pct;
xfs_trans_t *tp;
nb = in->newblocks;
pct = in->imaxpct;
if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
return -EINVAL;
if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
return error;
dpct = pct - mp->m_sb.sb_imax_pct;
error = xfs_buf_read_uncached(mp->m_ddev_targp,
XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
if (error)
return error;
xfs_buf_relse(bp);
new = nb; /* use new as a temporary here */
nb_mod = do_div(new, mp->m_sb.sb_agblocks);
nagcount = new + (nb_mod != 0);
if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
nagcount--;
nb = (xfs_rfsblock_t)nagcount * mp->m_sb.sb_agblocks;
if (nb < mp->m_sb.sb_dblocks)
return -EINVAL;
}
new = nb - mp->m_sb.sb_dblocks;
oagcount = mp->m_sb.sb_agcount;
/* allocate the new per-ag structures */
if (nagcount > oagcount) {
error = xfs_initialize_perag(mp, nagcount, &nagimax);
if (error)
return error;
}
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp);
if (error)
return error;
/*
* Write new AG headers to disk. Non-transactional, but written
* synchronously so they are completed prior to the growfs transaction
* being logged.
*/
nfree = 0;
for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
if (agno == nagcount - 1)
agsize = nb -
(agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
else
agsize = mp->m_sb.sb_agblocks;
error = xfs_grow_ag_headers(mp, agno, agsize, &nfree);
if (error)
goto error0;
}
xfs_trans_agblocks_delta(tp, nfree);
/*
* There are new blocks in the old last a.g.
*/
......
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