Commit c6aee248 authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner

xfs: make last AG grow/shrink perag centric

Because the perag must exist for these operations, look it up as
part of the common shrink operations and pass it instead of the
mount/agno pair.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent 7561cea5
...@@ -761,11 +761,11 @@ xfs_ag_init_headers( ...@@ -761,11 +761,11 @@ xfs_ag_init_headers(
int int
xfs_ag_shrink_space( xfs_ag_shrink_space(
struct xfs_mount *mp, struct xfs_perag *pag,
struct xfs_trans **tpp, struct xfs_trans **tpp,
xfs_agnumber_t agno,
xfs_extlen_t delta) xfs_extlen_t delta)
{ {
struct xfs_mount *mp = pag->pag_mount;
struct xfs_alloc_arg args = { struct xfs_alloc_arg args = {
.tp = *tpp, .tp = *tpp,
.mp = mp, .mp = mp,
...@@ -782,14 +782,14 @@ xfs_ag_shrink_space( ...@@ -782,14 +782,14 @@ xfs_ag_shrink_space(
xfs_agblock_t aglen; xfs_agblock_t aglen;
int error, err2; int error, err2;
ASSERT(agno == mp->m_sb.sb_agcount - 1); ASSERT(pag->pag_agno == mp->m_sb.sb_agcount - 1);
error = xfs_ialloc_read_agi(mp, *tpp, agno, &agibp); error = xfs_ialloc_read_agi(mp, *tpp, pag->pag_agno, &agibp);
if (error) if (error)
return error; return error;
agi = agibp->b_addr; agi = agibp->b_addr;
error = xfs_alloc_read_agf(mp, *tpp, agno, 0, &agfbp); error = xfs_alloc_read_agf(mp, *tpp, pag->pag_agno, 0, &agfbp);
if (error) if (error)
return error; return error;
...@@ -801,13 +801,14 @@ xfs_ag_shrink_space( ...@@ -801,13 +801,14 @@ xfs_ag_shrink_space(
if (delta >= aglen) if (delta >= aglen)
return -EINVAL; return -EINVAL;
args.fsbno = XFS_AGB_TO_FSB(mp, agno, aglen - delta); args.fsbno = XFS_AGB_TO_FSB(mp, pag->pag_agno, aglen - delta);
/* /*
* Make sure that the last inode cluster cannot overlap with the new * Make sure that the last inode cluster cannot overlap with the new
* end of the AG, even if it's sparse. * end of the AG, even if it's sparse.
*/ */
error = xfs_ialloc_check_shrink(*tpp, agno, agibp, aglen - delta); error = xfs_ialloc_check_shrink(*tpp, pag->pag_agno, agibp,
aglen - delta);
if (error) if (error)
return error; return error;
...@@ -883,9 +884,8 @@ xfs_ag_shrink_space( ...@@ -883,9 +884,8 @@ xfs_ag_shrink_space(
*/ */
int int
xfs_ag_extend_space( xfs_ag_extend_space(
struct xfs_mount *mp, struct xfs_perag *pag,
struct xfs_trans *tp, struct xfs_trans *tp,
struct aghdr_init_data *id,
xfs_extlen_t len) xfs_extlen_t len)
{ {
struct xfs_buf *bp; struct xfs_buf *bp;
...@@ -893,23 +893,20 @@ xfs_ag_extend_space( ...@@ -893,23 +893,20 @@ xfs_ag_extend_space(
struct xfs_agf *agf; struct xfs_agf *agf;
int error; int error;
/* ASSERT(pag->pag_agno == pag->pag_mount->m_sb.sb_agcount - 1);
* Change the agi length.
*/ error = xfs_ialloc_read_agi(pag->pag_mount, tp, pag->pag_agno, &bp);
error = xfs_ialloc_read_agi(mp, tp, id->agno, &bp);
if (error) if (error)
return error; return error;
agi = bp->b_addr; agi = bp->b_addr;
be32_add_cpu(&agi->agi_length, len); be32_add_cpu(&agi->agi_length, len);
ASSERT(id->agno == mp->m_sb.sb_agcount - 1 ||
be32_to_cpu(agi->agi_length) == mp->m_sb.sb_agblocks);
xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH); xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH);
/* /*
* Change agf length. * Change agf length.
*/ */
error = xfs_alloc_read_agf(mp, tp, id->agno, 0, &bp); error = xfs_alloc_read_agf(pag->pag_mount, tp, pag->pag_agno, 0, &bp);
if (error) if (error)
return error; return error;
...@@ -924,13 +921,12 @@ xfs_ag_extend_space( ...@@ -924,13 +921,12 @@ xfs_ag_extend_space(
* XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that * XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that
* this doesn't actually exist in the rmap btree. * this doesn't actually exist in the rmap btree.
*/ */
error = xfs_rmap_free(tp, bp, bp->b_pag, error = xfs_rmap_free(tp, bp, pag, be32_to_cpu(agf->agf_length) - len,
be32_to_cpu(agf->agf_length) - len,
len, &XFS_RMAP_OINFO_SKIP_UPDATE); len, &XFS_RMAP_OINFO_SKIP_UPDATE);
if (error) if (error)
return error; return error;
return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno, return xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
be32_to_cpu(agf->agf_length) - len), be32_to_cpu(agf->agf_length) - len),
len, &XFS_RMAP_OINFO_SKIP_UPDATE, len, &XFS_RMAP_OINFO_SKIP_UPDATE,
XFS_AG_RESV_NONE); XFS_AG_RESV_NONE);
...@@ -939,34 +935,29 @@ xfs_ag_extend_space( ...@@ -939,34 +935,29 @@ xfs_ag_extend_space(
/* Retrieve AG geometry. */ /* Retrieve AG geometry. */
int int
xfs_ag_get_geometry( xfs_ag_get_geometry(
struct xfs_mount *mp, struct xfs_perag *pag,
xfs_agnumber_t agno,
struct xfs_ag_geometry *ageo) struct xfs_ag_geometry *ageo)
{ {
struct xfs_buf *agi_bp; struct xfs_buf *agi_bp;
struct xfs_buf *agf_bp; struct xfs_buf *agf_bp;
struct xfs_agi *agi; struct xfs_agi *agi;
struct xfs_agf *agf; struct xfs_agf *agf;
struct xfs_perag *pag;
unsigned int freeblks; unsigned int freeblks;
int error; int error;
if (agno >= mp->m_sb.sb_agcount)
return -EINVAL;
/* Lock the AG headers. */ /* Lock the AG headers. */
error = xfs_ialloc_read_agi(mp, NULL, agno, &agi_bp); error = xfs_ialloc_read_agi(pag->pag_mount, NULL, pag->pag_agno,
&agi_bp);
if (error) if (error)
return error; return error;
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agf_bp); error = xfs_alloc_read_agf(pag->pag_mount, NULL, pag->pag_agno, 0,
&agf_bp);
if (error) if (error)
goto out_agi; goto out_agi;
pag = agi_bp->b_pag;
/* Fill out form. */ /* Fill out form. */
memset(ageo, 0, sizeof(*ageo)); memset(ageo, 0, sizeof(*ageo));
ageo->ag_number = agno; ageo->ag_number = pag->pag_agno;
agi = agi_bp->b_addr; agi = agi_bp->b_addr;
ageo->ag_icount = be32_to_cpu(agi->agi_count); ageo->ag_icount = be32_to_cpu(agi->agi_count);
......
...@@ -168,11 +168,10 @@ struct aghdr_init_data { ...@@ -168,11 +168,10 @@ struct aghdr_init_data {
}; };
int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id); int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
int xfs_ag_shrink_space(struct xfs_mount *mp, struct xfs_trans **tpp, int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
xfs_agnumber_t agno, xfs_extlen_t delta); xfs_extlen_t delta);
int xfs_ag_extend_space(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
struct aghdr_init_data *id, xfs_extlen_t len); xfs_extlen_t len);
int xfs_ag_get_geometry(struct xfs_mount *mp, xfs_agnumber_t agno, int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
struct xfs_ag_geometry *ageo);
#endif /* __LIBXFS_AG_H */ #endif /* __LIBXFS_AG_H */
...@@ -41,6 +41,7 @@ xfs_resizefs_init_new_ags( ...@@ -41,6 +41,7 @@ xfs_resizefs_init_new_ags(
xfs_agnumber_t oagcount, xfs_agnumber_t oagcount,
xfs_agnumber_t nagcount, xfs_agnumber_t nagcount,
xfs_rfsblock_t delta, xfs_rfsblock_t delta,
struct xfs_perag *last_pag,
bool *lastag_extended) bool *lastag_extended)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
...@@ -73,7 +74,7 @@ xfs_resizefs_init_new_ags( ...@@ -73,7 +74,7 @@ xfs_resizefs_init_new_ags(
if (delta) { if (delta) {
*lastag_extended = true; *lastag_extended = true;
error = xfs_ag_extend_space(mp, tp, id, delta); error = xfs_ag_extend_space(last_pag, tp, delta);
} }
return error; return error;
} }
...@@ -96,6 +97,7 @@ xfs_growfs_data_private( ...@@ -96,6 +97,7 @@ xfs_growfs_data_private(
xfs_agnumber_t oagcount; xfs_agnumber_t oagcount;
struct xfs_trans *tp; struct xfs_trans *tp;
struct aghdr_init_data id = {}; struct aghdr_init_data id = {};
struct xfs_perag *last_pag;
nb = in->newblocks; nb = in->newblocks;
error = xfs_sb_validate_fsb_count(&mp->m_sb, nb); error = xfs_sb_validate_fsb_count(&mp->m_sb, nb);
...@@ -128,7 +130,6 @@ xfs_growfs_data_private( ...@@ -128,7 +130,6 @@ xfs_growfs_data_private(
return -EINVAL; return -EINVAL;
oagcount = mp->m_sb.sb_agcount; oagcount = mp->m_sb.sb_agcount;
/* allocate the new per-ag structures */ /* allocate the new per-ag structures */
if (nagcount > oagcount) { if (nagcount > oagcount) {
error = xfs_initialize_perag(mp, nagcount, &nagimax); error = xfs_initialize_perag(mp, nagcount, &nagimax);
...@@ -145,15 +146,17 @@ xfs_growfs_data_private( ...@@ -145,15 +146,17 @@ xfs_growfs_data_private(
if (error) if (error)
return error; return error;
last_pag = xfs_perag_get(mp, oagcount - 1);
if (delta > 0) { if (delta > 0) {
error = xfs_resizefs_init_new_ags(tp, &id, oagcount, nagcount, error = xfs_resizefs_init_new_ags(tp, &id, oagcount, nagcount,
delta, &lastag_extended); delta, last_pag, &lastag_extended);
} else { } else {
xfs_warn_mount(mp, XFS_OPSTATE_WARNED_SHRINK, xfs_warn_mount(mp, XFS_OPSTATE_WARNED_SHRINK,
"EXPERIMENTAL online shrink feature in use. Use at your own risk!"); "EXPERIMENTAL online shrink feature in use. Use at your own risk!");
error = xfs_ag_shrink_space(mp, &tp, nagcount - 1, -delta); error = xfs_ag_shrink_space(last_pag, &tp, -delta);
} }
xfs_perag_put(last_pag);
if (error) if (error)
goto out_trans_cancel; goto out_trans_cancel;
......
...@@ -955,6 +955,7 @@ xfs_ioc_ag_geometry( ...@@ -955,6 +955,7 @@ xfs_ioc_ag_geometry(
struct xfs_mount *mp, struct xfs_mount *mp,
void __user *arg) void __user *arg)
{ {
struct xfs_perag *pag;
struct xfs_ag_geometry ageo; struct xfs_ag_geometry ageo;
int error; int error;
...@@ -965,7 +966,12 @@ xfs_ioc_ag_geometry( ...@@ -965,7 +966,12 @@ xfs_ioc_ag_geometry(
if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved))) if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved)))
return -EINVAL; return -EINVAL;
error = xfs_ag_get_geometry(mp, ageo.ag_number, &ageo); pag = xfs_perag_get(mp, ageo.ag_number);
if (!pag)
return -EINVAL;
error = xfs_ag_get_geometry(pag, &ageo);
xfs_perag_put(pag);
if (error) if (error)
return error; return error;
......
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