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

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