diff options
author | Dave Chinner <dchinner@redhat.com> | 2018-05-14 09:10:08 +0300 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-05-16 04:12:51 +0300 |
commit | 49dd56f26ea7d18d4ca71f43a082dbb92798ebd3 (patch) | |
tree | 484e098777d3af29c538c0c684af7ae31c59c1a8 /fs/xfs/libxfs | |
parent | b16817b66b6c97d2a812d663d26faed40079892a (diff) | |
download | linux-49dd56f26ea7d18d4ca71f43a082dbb92798ebd3.tar.xz |
xfs: factor the ag length extension code into libxfs
Growfs currently manually codes the extension of the last AG in a
filesytem during the growfs process. Factor that out of the growfs
code and move it into libxfs along with teh rest of the AG header
modification code.
Signed-Off-By: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_ag.c | 60 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_ag.h | 7 |
2 files changed, 66 insertions, 1 deletions
diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c index 5baa22c07095..9345802c99f7 100644 --- a/fs/xfs/libxfs/xfs_ag.c +++ b/fs/xfs/libxfs/xfs_ag.c @@ -16,6 +16,7 @@ #include "xfs_alloc_btree.h" #include "xfs_rmap_btree.h" #include "xfs_alloc.h" +#include "xfs_ialloc.h" #include "xfs_rmap.h" #include "xfs_ag.h" @@ -402,3 +403,62 @@ xfs_ag_init_headers( } return error; } + +/* + * Extent the AG indicated by the @id by the length passed in + */ +int +xfs_ag_extend_space( + struct xfs_mount *mp, + struct xfs_trans *tp, + struct aghdr_init_data *id, + xfs_extlen_t len) +{ + struct xfs_owner_info oinfo; + struct xfs_buf *bp; + struct xfs_agi *agi; + struct xfs_agf *agf; + int error; + + /* + * Change the agi length. + */ + error = xfs_ialloc_read_agi(mp, tp, id->agno, &bp); + if (error) + return error; + + agi = XFS_BUF_TO_AGI(bp); + 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); + + /* + * Change agf length. + */ + error = xfs_alloc_read_agf(mp, tp, id->agno, 0, &bp); + if (error) + return error; + + agf = XFS_BUF_TO_AGF(bp); + be32_add_cpu(&agf->agf_length, len); + ASSERT(agf->agf_length == agi->agi_length); + xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH); + + /* + * Free the new space. + * + * XFS_RMAP_OWN_NULL is used here to tell the rmap btree that + * this doesn't actually exist in the rmap btree. + */ + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_NULL); + error = xfs_rmap_free(tp, bp, id->agno, + be32_to_cpu(agf->agf_length) - len, + len, &oinfo); + if (error) + return error; + + return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno, + be32_to_cpu(agf->agf_length) - len), + len, &oinfo, XFS_AG_RESV_NONE); +} diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h index 69f2fd4be0ea..412702e23f61 100644 --- a/fs/xfs/libxfs/xfs_ag.h +++ b/fs/xfs/libxfs/xfs_ag.h @@ -7,6 +7,9 @@ #ifndef __LIBXFS_AG_H #define __LIBXFS_AG_H 1 +struct xfs_mount; +struct xfs_trans; + struct aghdr_init_data { /* per ag data */ xfs_agblock_t agno; /* ag to init */ @@ -20,6 +23,8 @@ struct aghdr_init_data { xfs_btnum_t type; /* type of btree root block */ }; -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_extend_space(struct xfs_mount *mp, struct xfs_trans *tp, + struct aghdr_init_data *id, xfs_extlen_t len); #endif /* __LIBXFS_AG_H */ |