Blame SOURCES/xfsprogs-5.10.0-xfs-store-inode-btree-block-counts-in-AGI-header.patch

5d5cbe
From 177c81e25b763c90f9815b1f4055d9d5c515a845 Mon Sep 17 00:00:00 2001
5d5cbe
From: "Darrick J. Wong" <darrick.wong@oracle.com>
5d5cbe
Date: Tue, 10 Nov 2020 15:11:09 -0500
5d5cbe
Subject: [PATCH] xfs: store inode btree block counts in AGI header
5d5cbe
5d5cbe
Source kernel commit: 2a39946c984464e4aac82c556ba9915589be7323
5d5cbe
5d5cbe
Add a btree block usage counters for both inode btrees to the AGI header
5d5cbe
so that we don't have to walk the entire finobt at mount time to create
5d5cbe
the per-AG reservations.
5d5cbe
5d5cbe
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
5d5cbe
Reviewed-by: Brian Foster <bfoster@redhat.com>
5d5cbe
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
5d5cbe
---
5d5cbe
5d5cbe
NOTE: kernel routines are not used to initialize AGIs in this
5d5cbe
version, so I added to the open-coded function in xfs_mkfs.c
5d5cbe
5d5cbe
diff --git a/libxfs/xfs_ag.c b/libxfs/xfs_ag.c
5d5cbe
index a7d1a0d..850d6e3 100644
5d5cbe
--- a/libxfs/xfs_ag.c
5d5cbe
+++ b/libxfs/xfs_ag.c
5d5cbe
@@ -258,6 +258,11 @@ xfs_agiblock_init(
5d5cbe
 	}
5d5cbe
 	for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
5d5cbe
 		agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
5d5cbe
+	if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
5d5cbe
+		agi->agi_iblocks = cpu_to_be32(1);
5d5cbe
+		if (xfs_sb_version_hasfinobt(&mp->m_sb))
5d5cbe
+			agi->agi_fblocks = cpu_to_be32(1);
5d5cbe
+	}
5d5cbe
 }
5d5cbe
 
5d5cbe
 typedef void (*aghdr_init_work_f)(struct xfs_mount *mp, struct xfs_buf *bp,
5d5cbe
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
5d5cbe
index 23eca3b..7f7b03a 100644
5d5cbe
--- a/libxfs/xfs_format.h
5d5cbe
+++ b/libxfs/xfs_format.h
5d5cbe
@@ -449,6 +449,7 @@ xfs_sb_has_compat_feature(
5d5cbe
 #define XFS_SB_FEAT_RO_COMPAT_FINOBT   (1 << 0)		/* free inode btree */
5d5cbe
 #define XFS_SB_FEAT_RO_COMPAT_RMAPBT   (1 << 1)		/* reverse map btree */
5d5cbe
 #define XFS_SB_FEAT_RO_COMPAT_REFLINK  (1 << 2)		/* reflinked files */
5d5cbe
+#define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3)		/* inobt block counts */
5d5cbe
 #define XFS_SB_FEAT_RO_COMPAT_ALL \
5d5cbe
 		(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
5d5cbe
 		 XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
5d5cbe
@@ -546,6 +547,17 @@ static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
5d5cbe
 		(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK);
5d5cbe
 }
5d5cbe
 
5d5cbe
+/*
5d5cbe
+ * Inode btree block counter.  We record the number of inobt and finobt blocks
5d5cbe
+ * in the AGI header so that we can skip the finobt walk at mount time when
5d5cbe
+ * setting up per-AG reservations.
5d5cbe
+ */
5d5cbe
+static inline bool xfs_sb_version_hasinobtcounts(struct xfs_sb *sbp)
5d5cbe
+{
5d5cbe
+	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
5d5cbe
+		(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT);
5d5cbe
+}
5d5cbe
+
5d5cbe
 /*
5d5cbe
  * end of superblock version macros
5d5cbe
  */
5d5cbe
@@ -750,6 +762,9 @@ typedef struct xfs_agi {
5d5cbe
 	__be32		agi_free_root; /* root of the free inode btree */
5d5cbe
 	__be32		agi_free_level;/* levels in free inode btree */
5d5cbe
 
5d5cbe
+	__be32		agi_iblocks;	/* inobt blocks used */
5d5cbe
+	__be32		agi_fblocks;	/* finobt blocks used */
5d5cbe
+
5d5cbe
 	/* structure must be padded to 64 bit alignment */
5d5cbe
 } xfs_agi_t;
5d5cbe
 
5d5cbe
@@ -770,7 +785,8 @@ typedef struct xfs_agi {
5d5cbe
 #define	XFS_AGI_ALL_BITS_R1	((1 << XFS_AGI_NUM_BITS_R1) - 1)
5d5cbe
 #define	XFS_AGI_FREE_ROOT	(1 << 11)
5d5cbe
 #define	XFS_AGI_FREE_LEVEL	(1 << 12)
5d5cbe
-#define	XFS_AGI_NUM_BITS_R2	13
5d5cbe
+#define	XFS_AGI_IBLOCKS		(1 << 13) /* both inobt/finobt block counters */
5d5cbe
+#define	XFS_AGI_NUM_BITS_R2	14
5d5cbe
 
5d5cbe
 /* disk block (xfs_daddr_t) in the AG */
5d5cbe
 #define XFS_AGI_DADDR(mp)	((xfs_daddr_t)(2 << (mp)->m_sectbb_log))
5d5cbe
diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
5d5cbe
index a600c03..9d380f9 100644
5d5cbe
--- a/libxfs/xfs_ialloc.c
5d5cbe
+++ b/libxfs/xfs_ialloc.c
5d5cbe
@@ -2451,6 +2451,7 @@ xfs_ialloc_log_agi(
5d5cbe
 		offsetof(xfs_agi_t, agi_unlinked),
5d5cbe
 		offsetof(xfs_agi_t, agi_free_root),
5d5cbe
 		offsetof(xfs_agi_t, agi_free_level),
5d5cbe
+		offsetof(xfs_agi_t, agi_iblocks),
5d5cbe
 		sizeof(xfs_agi_t)
5d5cbe
 	};
5d5cbe
 #ifdef DEBUG
5d5cbe
diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c
5d5cbe
index 716a81f..9db87e9 100644
5d5cbe
--- a/libxfs/xfs_ialloc_btree.c
5d5cbe
+++ b/libxfs/xfs_ialloc_btree.c
5d5cbe
@@ -68,6 +68,25 @@ xfs_finobt_set_root(
5d5cbe
 			   XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL);
5d5cbe
 }
5d5cbe
 
5d5cbe
+/* Update the inode btree block counter for this btree. */
5d5cbe
+static inline void
5d5cbe
+xfs_inobt_mod_blockcount(
5d5cbe
+	struct xfs_btree_cur	*cur,
5d5cbe
+	int			howmuch)
5d5cbe
+{
5d5cbe
+	struct xfs_buf		*agbp = cur->bc_private.a.agbp;
5d5cbe
+	struct xfs_agi		*agi = agbp->b_addr;
5d5cbe
+
5d5cbe
+	if (!xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb))
5d5cbe
+		return;
5d5cbe
+
5d5cbe
+	if (cur->bc_btnum == XFS_BTNUM_FINO)
5d5cbe
+		be32_add_cpu(&agi->agi_fblocks, howmuch);
5d5cbe
+	else if (cur->bc_btnum == XFS_BTNUM_INO)
5d5cbe
+		be32_add_cpu(&agi->agi_iblocks, howmuch);
5d5cbe
+	xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_IBLOCKS);
5d5cbe
+}
5d5cbe
+
5d5cbe
 STATIC int
5d5cbe
 __xfs_inobt_alloc_block(
5d5cbe
 	struct xfs_btree_cur	*cur,
5d5cbe
@@ -103,6 +122,7 @@ __xfs_inobt_alloc_block(
5d5cbe
 
5d5cbe
 	new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno));
5d5cbe
 	*stat = 1;
5d5cbe
+	xfs_inobt_mod_blockcount(cur, 1);
5d5cbe
 	return 0;
5d5cbe
 }
5d5cbe
 
5d5cbe
@@ -135,6 +155,7 @@ __xfs_inobt_free_block(
5d5cbe
 	struct xfs_buf		*bp,
5d5cbe
 	enum xfs_ag_resv_type	resv)
5d5cbe
 {
5d5cbe
+	xfs_inobt_mod_blockcount(cur, -1);
5d5cbe
 	return xfs_free_extent(cur->bc_tp,
5d5cbe
 			XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
5d5cbe
 			&XFS_RMAP_OINFO_INOBT, resv);
5d5cbe
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
5d5cbe
index 16819d8..992224d 100644
5d5cbe
--- a/mkfs/xfs_mkfs.c
5d5cbe
+++ b/mkfs/xfs_mkfs.c
5d5cbe
@@ -3588,6 +3588,11 @@ initialise_ag_headers(
5d5cbe
 		platform_uuid_copy(&agi->agi_uuid, &sbp->sb_uuid);
5d5cbe
 	for (c = 0; c < XFS_AGI_UNLINKED_BUCKETS; c++)
5d5cbe
 		agi->agi_unlinked[c] = cpu_to_be32(NULLAGINO);
5d5cbe
+	if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
5d5cbe
+		agi->agi_iblocks = cpu_to_be32(1);
5d5cbe
+		if (xfs_sb_version_hasfinobt(&mp->m_sb))
5d5cbe
+			agi->agi_fblocks = cpu_to_be32(1);
5d5cbe
+	}
5d5cbe
 	libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
5d5cbe
 
5d5cbe
 	/*