xfs
[Top] [All Lists]

[PATCH 11/15] xfs: Introduce a helper to check if an AG is empty or not

To: xfs@xxxxxxxxxxx
Subject: [PATCH 11/15] xfs: Introduce a helper to check if an AG is empty or not
From: Jeff Liu <jeff.liu@xxxxxxxxxx>
Date: Fri, 16 Nov 2012 14:46:35 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121028 Thunderbird/16.0.2
We need to check if an affected AG is empty or not during FS shrink, this is a 
helper could be used for this purpose.

Maybe it's better to isolate AG related routines to a dedicated file: xfs_ag.c?
 

Signed-off-by: Jie Liu <jeff.liu@xxxxxxxxxx>
---
 fs/xfs/xfs_fsops.c |   92 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 029ab6d..6623d9a 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -614,6 +614,98 @@ xfs_growfs_log(
 }
 
 /*
+ * Get the reserved blocks of metadatas per AG which are includes:
+ *     Superblock (1 sector)
+ *     AG free block info (1 sector)
+ *     AG inode B+tree info (1 sector)
+ *     AG internal free list (1 sector)
+ *     Root of inode B+tree (1 block)
+ *     Root of free space B+tree, key is block number (1 block)
+ *     Root of free space B+tree, key is block count  (1 block)
+ *     Free list (4 blocks)
+ * The reserved block number of the aboves can be fetched via:
+ *     XFS_PREALLOC_BLOCKS(mp).
+ *
+ * The left blocks are used for Primary AG only.
+ * - Inodes (64 inodes)
+ */
+static xfs_extlen_t
+xfs_ag_metadata_blocks(
+       xfs_mount_t     *mp,
+       xfs_agnumber_t  agno)
+{
+       xfs_extlen_t    mdblocks;
+
+       mdblocks = XFS_PREALLOC_BLOCKS(mp);
+       /*
+        * For primary AG, we need to figure out how many blocks are
+        * reserved for those 64 inodes which are used for the root
+        * of inodes B+tree.
+        */
+       if (agno == 0)
+               mdblocks += (64 / mp->m_sb.sb_inopblock);
+
+       return mdblocks;
+}
+
+/*
+ * An empty AG means that there has no data/inodes allocated
+ * at it except those metadata blocks, and the agi_count should
+ * be ZERO.
+ */
+static int
+xfs_ag_is_empty(
+       xfs_mount_t     *mp,
+       xfs_agnumber_t  agno,
+       bool            *empty)
+{
+       xfs_extlen_t    agblocks;
+       xfs_extlen_t    agfblocks;
+       xfs_extlen_t    agmblocks;
+       xfs_extlen_t    agicount;
+       xfs_agf_t       *agf;
+       xfs_agi_t       *agi;
+       xfs_buf_t       *bp;
+       int             error = 0;
+
+       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 = XFS_ERROR(ENOMEM);
+               goto error0;
+       }
+       agf = XFS_BUF_TO_AGF(bp);
+       agmblocks = xfs_ag_metadata_blocks(mp, agno);
+       /*
+        * The latest AG might has different size to others.
+        */
+       if (agno == mp->m_sb.sb_agcount - 1)
+               agblocks = (be32_to_cpu(agf->agf_length) - agmblocks);
+       else
+               agblocks = mp->m_sb.sb_agblocks - agmblocks;
+       agfblocks = be32_to_cpu(agf->agf_freeblks);
+       xfs_buf_relse(bp);
+
+       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 = XFS_ERROR(ENOMEM);
+               goto error0;
+       }
+       agi = XFS_BUF_TO_AGI(bp);
+       agicount = be32_to_cpu(agi->agi_count);
+       xfs_buf_relse(bp);
+
+       *empty = ((agblocks == agfblocks && agicount == 0) ?
+                 true : false);
+
+error0:
+       return error;
+}
+
+/*
  * exported through ioctl XFS_IOC_FSCOUNTS
  */
 
-- 
1.7.4.1

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH 11/15] xfs: Introduce a helper to check if an AG is empty or not, Jeff Liu <=