[PATCH V4 12/20] xfsprogs: Introduce macros to represent new maximum extent counts for data/attr forks

Chandan Babu R
2021-12-14T08:50:11Z

This commit defines new macros to represent maximum extent counts allowed by
filesystems which have support for large per-inode extent counters.

Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libxfs/xfs_bmap.c | 9 ++++-----
libxfs/xfs_format.h | 8 +++++---
libxfs/xfs_inode_buf.c | 3 ++-
libxfs/xfs_inode_fork.c | 2 +-
libxfs/xfs_inode_fork.h | 19 +++++++++++++++----
repair/dinode.c | 6 ++++--
6 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 37d9d47c..9dd24678 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -55,10 +55,8 @@ xfs_bmap_compute_maxlevels(
int sz; /* root block size */

/*
- * The maximum number of extents in a file, hence the maximum number of
- * leaf entries, is controlled by the size of the on-disk extent count,
- * either a signed 32-bit number for the data fork, or a signed 16-bit
- * number for the attr fork.
+ * The maximum number of extents in a fork, hence the maximum number of
+ * leaf entries, is controlled by the size of the on-disk extent count.
*
* Note that we can no longer assume that if we are in ATTR1 that the
* fork offset of all the inodes will be
@@ -68,7 +66,8 @@ xfs_bmap_compute_maxlevels(
* ATTR2 we have to assume the worst case scenario of a minimum size
* available.
*/
- maxleafents = xfs_iext_max_nextents(whichfork);
+ maxleafents = xfs_iext_max_nextents(xfs_sb_version_hasnrext64(&mp->m_sb),
+ whichfork);
if (whichfork == XFS_DATA_FORK)
sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
else
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 58186f2b..bdd13ec9 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1061,9 +1061,11 @@ enum xfs_dinode_fmt {
/*
* Max values for extlen, extnum, aextnum.
*/
-#define MAXEXTLEN ((xfs_extlen_t)0x001fffff) /* 21 bits */
-#define MAXEXTNUM ((xfs_extnum_t)0x7fffffff) /* signed int */
-#define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */
+#define MAXEXTLEN ((xfs_extlen_t)0x1fffff) /* 21 bits */
+#define XFS_MAX_EXTCNT_DATA_FORK ((xfs_extnum_t)0xffffffffffff) /* Unsigned 48-bits */
+#define XFS_MAX_EXTCNT_ATTR_FORK ((xfs_aextnum_t)0xffffffff) /* Unsigned 32-bits */
+#define XFS_MAX_EXTCNT_DATA_FORK_OLD ((xfs_extnum_t)0x7fffffff) /* Signed 32-bits */
+#define XFS_MAX_EXTCNT_ATTR_FORK_OLD ((xfs_aextnum_t)0x7fff) /* Signed 16-bits */

/*
* Inode minimum and maximum sizes.
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 06b6c09f..9bddf790 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -358,7 +358,8 @@ xfs_dinode_verify_fork(
return __this_address;
break;
case XFS_DINODE_FMT_BTREE:
- max_extents = xfs_iext_max_nextents(whichfork);
+ max_extents = xfs_iext_max_nextents(xfs_dinode_has_nrext64(dip),
+ whichfork);
if (di_nextents > max_extents)
return __this_address;
break;
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index 627eb23b..17265401 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -743,7 +743,7 @@ xfs_iext_count_may_overflow(
if (whichfork == XFS_COW_FORK)
return 0;

- max_exts = xfs_iext_max_nextents(whichfork);
+ max_exts = xfs_iext_max_nextents(xfs_inode_has_nrext64(ip), whichfork);

if (XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
max_exts = 10;
diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h
index b34b5c44..7d5f0015 100644
--- a/libxfs/xfs_inode_fork.h
+++ b/libxfs/xfs_inode_fork.h
@@ -133,12 +133,23 @@ static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
return ifp->if_format;
}

-static inline xfs_extnum_t xfs_iext_max_nextents(int whichfork)
+static inline xfs_extnum_t xfs_iext_max_nextents(bool has_big_extcnt,
+ int whichfork)
{
- if (whichfork == XFS_DATA_FORK || whichfork == XFS_COW_FORK)
- return MAXEXTNUM;
+ switch (whichfork) {
+ case XFS_DATA_FORK:
+ case XFS_COW_FORK:
+ return has_big_extcnt ? XFS_MAX_EXTCNT_DATA_FORK
+ : XFS_MAX_EXTCNT_DATA_FORK_OLD;
+
+ case XFS_ATTR_FORK:
+ return has_big_extcnt ? XFS_MAX_EXTCNT_ATTR_FORK
+ : XFS_MAX_EXTCNT_ATTR_FORK_OLD;

- return MAXAEXTNUM;
+ default:
+ ASSERT(0);
+ return 0;
+ }
}

static inline xfs_extnum_t
diff --git a/repair/dinode.c b/repair/dinode.c
index 8b6cd60d..0df84e48 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -1804,7 +1804,8 @@ _("bad nblocks %llu for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
}
}

- if (nextents > xfs_iext_max_nextents(XFS_DATA_FORK)) {
+ if (nextents > xfs_iext_max_nextents(xfs_dinode_has_nrext64(dino),
+ XFS_DATA_FORK)) {
do_warn(
_("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
nextents, lino);
@@ -1826,7 +1827,8 @@ _("bad nextents %lu for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
}
}

- if (anextents > xfs_iext_max_nextents(XFS_ATTR_FORK)) {
+ if (anextents > xfs_iext_max_nextents(xfs_dinode_has_nrext64(dino),
+ XFS_ATTR_FORK)) {
do_warn(
_("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
anextents, lino);
--
2.30.2