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

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