* [PATCH 12/15] xfs: Introduce a helper to remove an empty
@ 2012-11-16 6:46 Jeff Liu
0 siblings, 0 replies; only message in thread
From: Jeff Liu @ 2012-11-16 6:46 UTC (permalink / raw)
To: xfs
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@oracle.com>
---
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@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2012-11-16 6:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-16 6:46 [PATCH 12/15] xfs: Introduce a helper to remove an empty Jeff Liu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.