If a given AG is empty, we can totally wipe it out of the disk via this helper by cleaning up the AG metadata blocks. Signed-off-by: Jie Liu <jeff.liu@xxxxxxxxxx> --- fs/xfs/xfs_fsops.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 149 insertions(+), 0 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 6623d9a..24de23f 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -706,6 +706,155 @@ error0: } /* + * This function is used to remove an empty AG out of the disk + * by cleaning up it's metadata info and free the related perag + * object. + */ +static int +xfs_remove_empty_ag( + xfs_mount_t *mp, + xfs_agnumber_t agno, + xfs_extlen_t *nfree) +{ + xfs_agf_t *agf; + xfs_agi_t *agi; + xfs_buf_t *bp; + xfs_dsb_t *sbp; + xfs_agfl_t *agfl; + xfs_perag_t *pag; + __uint32_t agfl_bno; + __uint32_t bno_btree_blkno; + __uint32_t cnt_btree_blkno; + __uint32_t ino_btree_blkno; + struct xfs_btree_block *block; + int error; + + /* Wipe out superblock in sector size */ + error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0, &bp); + if (error) + goto error0; + sbp = XFS_BUF_TO_SBP(bp); + memset(sbp, 0, mp->m_sb.sb_sectsize); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + + bp = xfs_buf_get(mp->m_ddev_targp, + XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), + XFS_FSS_TO_BB(mp, 1), 0); + if (!bp) { + error = ENOMEM; + goto error0; + } + agf = XFS_BUF_TO_AGF(bp); + if (nfree) { + /* + * Don't use the mp->m_sb.sb_agcount since the end + * AG might has different size to others. + */ + *nfree = be32_to_cpu(agf->agf_length); + } + bno_btree_blkno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]); + cnt_btree_blkno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi]); + memset(agf, 0, mp->m_sb.sb_sectsize); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + + bp = xfs_buf_get(mp->m_ddev_targp, + XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), + XFS_FSS_TO_BB(mp, 1), 0); + if (!bp) { + error = ENOMEM; + goto error0; + } + agi = XFS_BUF_TO_AGI(bp); + ino_btree_blkno = be32_to_cpu(agi->agi_root); + memset(agi, 0, mp->m_sb.sb_sectsize); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + + bp = xfs_buf_get(mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_AGFL_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0); + if (!bp) { + error = XFS_ERROR(ENOMEM); + goto error0; + } + agfl = XFS_BUF_TO_AGFL(bp); + agfl_bno = be32_to_cpu(agfl->agfl_bno[0]); + memset(agfl, 0, mp->m_sb.sb_sectsize); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + + /* BNO btree root block */ + bp = xfs_buf_get(mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, bno_btree_blkno), + BTOBB(mp->m_sb.sb_blocksize), 0); + if (!bp) { + error = XFS_ERROR(ENOMEM); + goto error0; + } + block = XFS_BUF_TO_BLOCK(bp); + memset(block, 0, mp->m_sb.sb_blocksize); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + + /* CNT btree root block */ + bp = xfs_buf_get(mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, cnt_btree_blkno), + BTOBB(mp->m_sb.sb_blocksize), 0); + if (!bp) { + error = XFS_ERROR(ENOMEM); + goto error0; + } + block = XFS_BUF_TO_BLOCK(bp); + memset(block, 0, mp->m_sb.sb_blocksize); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + + /* INO btree root block */ + bp = xfs_buf_get(mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, ino_btree_blkno), + BTOBB(mp->m_sb.sb_blocksize), 0); + if (!bp) { + error = XFS_ERROR(ENOMEM); + goto error0; + } + block = XFS_BUF_TO_BLOCK(bp); + memset(block, 0, mp->m_sb.sb_blocksize); + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + + /* Free perag object from the radix tree */ + spin_lock(&mp->m_perag_lock); + pag = radix_tree_delete(&mp->m_perag_tree, agno); + spin_unlock(&mp->m_perag_lock); + ASSERT(pag); + ASSERT(atomic_read(&pag->pag_ref) == 0); + kmem_free(pag); + + *nfree += xfs_ag_metadata_blocks(mp, agno); + +error0: + return error; +} + +/* * exported through ioctl XFS_IOC_FSCOUNTS */ -- 1.7.4.1 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs