* [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters
@ 2021-09-16 10:08 Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 01/16] xfsprogs: xfs_repair: allow administrators to add older v5 features Chandan Babu R
` (15 more replies)
0 siblings, 16 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
This patchset implements the changes to userspace programs that are
required to support extending inode's data and attr fork extent
counter fields. The changes allow programs in xfsprogs to be able to
create and work with filesystem instances with 64-bit data fork extent
counter and 32-bit attr fork extent counter fields.
The patchset is based on Darrick's btree-dynamic-depth branch.
These patches can also be obtained from
https://github.com/chandanr/xfsprogs-dev.git at branch
xfs-incompat-extend-extcnt-v3.
Changelog:
V2 -> V3:
1. Introduce the ability to upgrade existing filesystems to use 64-bit
extent counters if it is feasible to do so.
2. Report presence of 64-bit extent counters via xfs_info.
3. Add XFS_SB_FEAT_INCOMPAT_NREXT64 to XFS_SB_FEAT_INCOMPAT_ALL in a
separate patch.
4. Rename mkfs.xfs option from extcnt64bit to nrext64.
V1 -> V2:
1. Rebase patches on top of Darrick's btree-dynamic-depth branch.
2. Add support for using the new bulkstat ioctl version to support
64-bit data fork extent counter field.
Chandan Babu R (15):
xfsprogs: Move extent count limits to xfs_format.h
xfsprogs: Introduce xfs_iext_max_nextents() helper
xfsprogs: Rename MAXEXTNUM, MAXAEXTNUM to XFS_IFORK_EXTCNT_MAXS32,
XFS_IFORK_EXTCNT_MAXS16
xfsprogs: Use xfs_extnum_t instead of basic data types
xfsprogs: Introduce xfs_dfork_nextents() helper
xfsprogs: xfs_dfork_nextents: Return extent count via an out argument
xfsprogs: Rename inode's extent counter fields based on their width
xfsprogs: Promote xfs_extnum_t and xfs_aextnum_t to 64 and 32-bits
respectively
xfsprogs: Enable bulkstat ioctl to support 64-bit extent counters
xfsprogs: Extend per-inode extent counter widths
xfsprogs: xfs_info: Report NREXT64 feature status
xfsprogs: Add XFS_SB_FEAT_INCOMPAT_NREXT64 to XFS_SB_FEAT_INCOMPAT_ALL
xfsprogs: Add nrext64 mkfs option
xfsprogs: Add support for upgrading to NREXT64 feature
xfsprogs: Define max extent length based on on-disk format definition
Darrick J. Wong (1):
xfsprogs: xfs_repair: allow administrators to add older v5 features
db/bmap.c | 21 ++-
db/btdump.c | 11 +-
db/check.c | 44 +++--
db/field.c | 4 -
db/field.h | 2 -
db/frag.c | 11 +-
db/inode.c | 74 +++++++--
db/metadump.c | 14 +-
fsr/xfs_fsr.c | 4 +-
include/libxfs.h | 1 +
include/libxlog.h | 6 +-
include/xfs_inode.h | 5 +
include/xfs_mount.h | 4 +-
io/bulkstat.c | 3 +-
libfrog/bulkstat.c | 55 ++++++-
libfrog/fsgeom.c | 6 +-
libxfs/libxfs_api_defs.h | 3 +
libxfs/xfs_bmap.c | 74 +++++----
libxfs/xfs_format.h | 77 +++++++--
libxfs/xfs_fs.h | 20 ++-
libxfs/xfs_ialloc.c | 2 +
libxfs/xfs_inode_buf.c | 61 +++++--
libxfs/xfs_inode_fork.c | 33 ++--
libxfs/xfs_inode_fork.h | 23 ++-
libxfs/xfs_log_format.h | 7 +-
libxfs/xfs_rtbitmap.c | 4 +-
libxfs/xfs_sb.c | 5 +
libxfs/xfs_swapext.c | 6 +-
libxfs/xfs_trans_inode.c | 5 +
libxfs/xfs_trans_resv.c | 10 +-
libxfs/xfs_types.h | 11 +-
logprint/log_misc.c | 23 ++-
logprint/log_print_all.c | 31 +++-
logprint/log_print_trans.c | 2 +-
man/man8/mkfs.xfs.8 | 7 +
man/man8/xfs_admin.8 | 30 ++++
mkfs/xfs_mkfs.c | 29 +++-
repair/attr_repair.c | 11 +-
repair/bmap_repair.c | 23 ++-
repair/dino_chunks.c | 6 +-
repair/dinode.c | 143 ++++++++++++-----
repair/dinode.h | 4 +-
repair/globals.c | 5 +
repair/globals.h | 5 +
repair/phase2.c | 319 +++++++++++++++++++++++++++++++++++--
repair/phase4.c | 7 +-
repair/prefetch.c | 7 +-
repair/protos.h | 1 +
repair/rmap.c | 4 +-
repair/scan.c | 6 +-
repair/xfs_repair.c | 55 +++++++
51 files changed, 1076 insertions(+), 248 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH V3 01/16] xfsprogs: xfs_repair: allow administrators to add older v5 features
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 02/16] xfsprogs: Move extent count limits to xfs_format.h Chandan Babu R
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Darrick J. Wong, Chandan Babu R
From: "Darrick J. Wong" <djwong@kernel.org>
Add to xfs_db the ability to add certain existing features (finobt,
reflink, and rmapbt) to an existing filesystem if it's eligible.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
include/libxfs.h | 1 +
libxfs/libxfs_api_defs.h | 3 +
man/man8/xfs_admin.8 | 30 +++++
repair/dino_chunks.c | 6 +-
repair/dinode.c | 5 +-
repair/globals.c | 4 +
repair/globals.h | 4 +
repair/phase2.c | 285 +++++++++++++++++++++++++++++++++++++--
repair/phase4.c | 5 +-
repair/protos.h | 1 +
repair/rmap.c | 4 +-
repair/xfs_repair.c | 44 ++++++
12 files changed, 377 insertions(+), 15 deletions(-)
diff --git a/include/libxfs.h b/include/libxfs.h
index 82618a56..7100155f 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -79,6 +79,7 @@ struct iomap;
#include "xfs_refcount.h"
#include "xfs_btree_staging.h"
#include "xfs_imeta.h"
+#include "xfs_ag_resv.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 55dcedeb..d4d0c281 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -21,6 +21,8 @@
#define xfs_ag_init_headers libxfs_ag_init_headers
#define xfs_ag_block_count libxfs_ag_block_count
+#define xfs_ag_resv_free libxfs_ag_resv_free
+#define xfs_ag_resv_init libxfs_ag_resv_init
#define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable
#define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs
@@ -121,6 +123,7 @@
#define xfs_highbit32 libxfs_highbit32
#define xfs_highbit64 libxfs_highbit64
#define xfs_ialloc_calc_rootino libxfs_ialloc_calc_rootino
+#define xfs_ialloc_read_agi libxfs_ialloc_read_agi
#define xfs_icreate libxfs_icreate
#define xfs_icreate_args_rootfile libxfs_icreate_args_rootfile
#define xfs_idata_realloc libxfs_idata_realloc
diff --git a/man/man8/xfs_admin.8 b/man/man8/xfs_admin.8
index ad28e0f6..4f3c882a 100644
--- a/man/man8/xfs_admin.8
+++ b/man/man8/xfs_admin.8
@@ -149,6 +149,36 @@ Upgrade a filesystem to support larger timestamps up to the year 2486.
The filesystem cannot be downgraded after this feature is enabled.
Once enabled, the filesystem will not be mountable by older kernels.
This feature was added to Linux 5.10.
+.TP 0.4i
+.B finobt
+Track free inodes through a separate free inode btree index to speed up inode
+allocation on old filesystems.
+This upgrade can fail if any AG has less than 1% free space remaining.
+The filesystem cannot be downgraded after this feature is enabled.
+This feature was added to Linux 3.16.
+.TP 0.4i
+.B reflink
+Enable sharing of file data blocks.
+This upgrade can fail if any AG has less than 2% free space remaining.
+The filesystem cannot be downgraded after this feature is enabled.
+This feature was added to Linux 4.9.
+.TP 0.4i
+.B rmapbt
+Store an index of the owners of on-disk blocks.
+This enables much stronger cross-referencing of various metadata structures
+and online repairs to space usage metadata.
+The filesystem cannot be downgraded after this feature is enabled.
+This upgrade can fail if any AG has less than 5% free space remaining.
+This feature was added to Linux 4.8.
+.TP 0.4i
+.B metadir
+Create a directory tree of metadata inodes instead of storing them all in the
+superblock.
+This is required for reverse mapping btrees and reflink support on the realtime
+device.
+The filesystem cannot be downgraded after this feature is enabled.
+This upgrade can fail if any AG has less than 5% free space remaining.
+This feature is not upstream yet.
.RE
.TP
.BI \-U " uuid"
diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
index bdefef40..160dd4cc 100644
--- a/repair/dino_chunks.c
+++ b/repair/dino_chunks.c
@@ -963,7 +963,11 @@ next_readbuf:
}
if (status) {
- if (mp->m_sb.sb_rootino == ino) {
+ if (wipe_pre_metadir_file(ino)) {
+ if (!ino_discovery)
+ do_warn(
+ _("wiping pre-metadir metadata inode %"PRIu64".\n"), ino);
+ } else if (mp->m_sb.sb_rootino == ino) {
need_root_inode = 1;
if (!no_modify) {
diff --git a/repair/dinode.c b/repair/dinode.c
index 758b1a15..0ffb3e6e 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -2386,6 +2386,9 @@ process_dinode_int(
ASSERT(uncertain == 0 || verify_mode != 0);
ASSERT(ino_bpp != NULL || verify_mode != 0);
+ if (wipe_pre_metadir_file(lino))
+ goto clear_bad_out;
+
/*
* This is the only valid point to check the CRC; after this we may have
* made changes which invalidate it, and the CRC is only updated again
@@ -2593,7 +2596,7 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
if (flags & XFS_DIFLAG_NEWRTBM) {
/* must be a rt bitmap inode */
if (lino != mp->m_sb.sb_rbmino) {
- if (!uncertain) {
+ if (!uncertain && !add_metadir) {
do_warn(
_("inode %" PRIu64 " not rt bitmap\n"),
lino);
diff --git a/repair/globals.c b/repair/globals.c
index 7f7bafe3..6e52bac9 100644
--- a/repair/globals.c
+++ b/repair/globals.c
@@ -50,6 +50,10 @@ int convert_lazy_count; /* Convert lazy-count mode on/off */
int lazy_count; /* What to set if to if converting */
bool add_inobtcount; /* add inode btree counts to AGI */
bool add_bigtime; /* add support for timestamps up to 2486 */
+bool add_finobt; /* add free inode btrees */
+bool add_reflink; /* add reference count btrees */
+bool add_rmapbt; /* add reverse mapping btrees */
+bool add_metadir; /* add metadata directory tree */
/* misc status variables */
diff --git a/repair/globals.h b/repair/globals.h
index 1964c18c..6c69413f 100644
--- a/repair/globals.h
+++ b/repair/globals.h
@@ -91,6 +91,10 @@ extern int convert_lazy_count; /* Convert lazy-count mode on/off */
extern int lazy_count; /* What to set if to if converting */
extern bool add_inobtcount; /* add inode btree counts to AGI */
extern bool add_bigtime; /* add support for timestamps up to 2486 */
+extern bool add_finobt; /* add free inode btrees */
+extern bool add_reflink; /* add reference count btrees */
+extern bool add_rmapbt; /* add reverse mapping btrees */
+extern bool add_metadir; /* add metadata directory tree */
/* misc status variables */
diff --git a/repair/phase2.c b/repair/phase2.c
index 51234ee9..cca154d3 100644
--- a/repair/phase2.c
+++ b/repair/phase2.c
@@ -133,7 +133,8 @@ zero_log(
static bool
set_inobtcount(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
{
if (!xfs_has_crc(mp)) {
printf(
@@ -153,14 +154,15 @@ set_inobtcount(
}
printf(_("Adding inode btree counts to filesystem.\n"));
- mp->m_sb.sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
- mp->m_sb.sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+ new_sb->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
return true;
}
static bool
set_bigtime(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
{
if (!xfs_has_crc(mp)) {
printf(
@@ -174,8 +176,256 @@ set_bigtime(
}
printf(_("Adding large timestamp support to filesystem.\n"));
- mp->m_sb.sb_features_incompat |= (XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR |
- XFS_SB_FEAT_INCOMPAT_BIGTIME);
+ new_sb->sb_features_incompat |= (XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR |
+ XFS_SB_FEAT_INCOMPAT_BIGTIME);
+ return true;
+}
+
+/* Make sure we can actually upgrade this (v5) filesystem. */
+static void
+check_new_v5_geometry(
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
+{
+ struct xfs_sb old_sb;
+ struct xfs_perag *pag;
+ xfs_agnumber_t agno;
+ xfs_ino_t rootino;
+ int min_logblocks;
+ int error;
+
+ /*
+ * Save the current superblock, then copy in the new one to do log size
+ * and root inode checks.
+ */
+ memcpy(&old_sb, &mp->m_sb, sizeof(struct xfs_sb));
+ memcpy(&mp->m_sb, new_sb, sizeof(struct xfs_sb));
+
+ /* Do we have a big enough log? */
+ min_logblocks = libxfs_log_calc_minimum_size(mp);
+ if (old_sb.sb_logblocks < min_logblocks) {
+ printf(
+ _("Filesystem log too small to upgrade filesystem; need %u blocks, have %u.\n"),
+ min_logblocks, old_sb.sb_logblocks);
+ exit(0);
+ }
+
+ rootino = libxfs_ialloc_calc_rootino(mp, new_sb->sb_unit);
+ if (old_sb.sb_rootino != rootino) {
+ printf(
+ _("Cannot upgrade filesystem, root inode (%llu) cannot be moved to %llu.\n"),
+ (unsigned long long)old_sb.sb_rootino,
+ (unsigned long long)rootino);
+ exit(0);
+ }
+
+ /* Make sure we have enough space for per-AG reservations. */
+ for_each_perag(mp, agno, pag) {
+ struct xfs_trans *tp;
+ struct xfs_agf *agf;
+ struct xfs_buf *agi_bp, *agf_bp;
+ unsigned int avail, agblocks;
+
+ /*
+ * Create a dummy transaction so that we can load the AGI and
+ * AGF buffers in memory with the old fs geometry and pin them
+ * there while we try to make a per-AG reservation with the new
+ * geometry.
+ */
+ error = -libxfs_trans_alloc_empty(mp, &tp);
+ if (error)
+ do_error(
+ _("Cannot reserve resources for upgrade check, err=%d.\n"),
+ error);
+
+ error = -libxfs_ialloc_read_agi(mp, tp, agno, &agi_bp);
+ if (error)
+ do_error(
+ _("Cannot read AGI %u for upgrade check, err=%d.\n"),
+ agno, error);
+
+ error = -libxfs_alloc_read_agf(mp, tp, agno, 0, &agf_bp);
+ if (error)
+ do_error(
+ _("Cannot read AGF %u for upgrade check, err=%d.\n"),
+ agno, error);
+ agf = agf_bp->b_addr;
+ agblocks = be32_to_cpu(agf->agf_length);
+
+ error = -libxfs_ag_resv_init(pag, tp);
+ if (error == ENOSPC) {
+ printf(
+ _("Not enough free space would remain in AG %u for metadata.\n"),
+ agno);
+ exit(0);
+ }
+ if (error)
+ do_error(
+ _("Error %d while checking AG %u space reservation.\n"),
+ error, agno);
+
+ /*
+ * Would we have at least 10% free space in this AG after
+ * making per-AG reservations?
+ */
+ avail = pag->pagf_freeblks + pag->pagf_flcount;
+ avail -= pag->pag_meta_resv.ar_reserved;
+ avail -= pag->pag_rmapbt_resv.ar_asked;
+ if (avail < agblocks / 10)
+ printf(
+ _("AG %u will be low on space after upgrade.\n"),
+ agno);
+
+ libxfs_ag_resv_free(pag);
+
+ /*
+ * Mark the per-AG structure as uninitialized so that we don't
+ * trip over stale cached counters after the upgrade, and
+ * release all the resources.
+ */
+ libxfs_trans_cancel(tp);
+ pag->pagf_init = 0;
+ pag->pagi_init = 0;
+ }
+
+ /*
+ * Put back the old superblock.
+ */
+ memcpy(&mp->m_sb, &old_sb, sizeof(struct xfs_sb));
+}
+
+static bool
+set_finobt(
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
+{
+ if (!xfs_has_crc(mp)) {
+ printf(
+ _("Free inode btree feature only supported on V5 filesystems.\n"));
+ exit(0);
+ }
+
+ if (xfs_has_finobt(mp)) {
+ printf(_("Filesystem already supports free inode btrees.\n"));
+ exit(0);
+ }
+
+ printf(_("Adding free inode btrees to filesystem.\n"));
+ new_sb->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_FINOBT;
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+ return true;
+}
+
+static bool
+set_reflink(
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
+{
+ if (!xfs_has_crc(mp)) {
+ printf(
+ _("Reflink feature only supported on V5 filesystems.\n"));
+ exit(0);
+ }
+
+ if (xfs_has_reflink(mp)) {
+ printf(_("Filesystem already supports reflink.\n"));
+ exit(0);
+ }
+
+ printf(_("Adding reflink support to filesystem.\n"));
+ new_sb->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+ return true;
+}
+
+static bool
+set_rmapbt(
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
+{
+ if (!xfs_has_crc(mp)) {
+ printf(
+ _("Reverse mapping btree feature only supported on V5 filesystems.\n"));
+ exit(0);
+ }
+
+ if (xfs_has_reflink(mp)) {
+ printf(
+ _("Reverse mapping btrees cannot be added when reflink is enabled.\n"));
+ exit(0);
+ }
+
+ if (xfs_has_rmapbt(mp)) {
+ printf(_("Filesystem already supports reverse mapping btrees.\n"));
+ exit(0);
+ }
+
+ printf(_("Adding reverse mapping btrees to filesystem.\n"));
+ new_sb->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT;
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+ return true;
+}
+
+static xfs_ino_t doomed_rbmino = NULLFSINO;
+static xfs_ino_t doomed_rsumino = NULLFSINO;
+static xfs_ino_t doomed_uquotino = NULLFSINO;
+static xfs_ino_t doomed_gquotino = NULLFSINO;
+static xfs_ino_t doomed_pquotino = NULLFSINO;
+
+bool
+wipe_pre_metadir_file(
+ xfs_ino_t ino)
+{
+ if (ino == doomed_rbmino ||
+ ino == doomed_rsumino ||
+ ino == doomed_uquotino ||
+ ino == doomed_gquotino ||
+ ino == doomed_pquotino)
+ return true;
+ return false;
+}
+
+static bool
+set_metadir(
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
+{
+ if (!xfs_has_crc(mp)) {
+ printf(
+ _("Metadata directory trees only supported on V5 filesystems.\n"));
+ exit(0);
+ }
+
+ if (xfs_has_metadir(mp)) {
+ printf(_("Filesystem already supports metadata directory trees.\n"));
+ exit(0);
+ }
+
+ printf(_("Adding metadata directory trees to filesystem.\n"));
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_METADIR;
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+
+ /* Blow out all the old metadata inodes; we'll rebuild in phase6. */
+ new_sb->sb_metadirino = new_sb->sb_rootino + 1;
+ doomed_rbmino = mp->m_sb.sb_rbmino;
+ doomed_rsumino = mp->m_sb.sb_rsumino;
+ doomed_uquotino = mp->m_sb.sb_uquotino;
+ doomed_gquotino = mp->m_sb.sb_gquotino;
+ doomed_pquotino = mp->m_sb.sb_pquotino;
+
+ new_sb->sb_rbmino = NULLFSINO;
+ new_sb->sb_rsumino = NULLFSINO;
+ new_sb->sb_uquotino = NULLFSINO;
+ new_sb->sb_gquotino = NULLFSINO;
+ new_sb->sb_pquotino = NULLFSINO;
+
+ /* Indicate that we need a rebuild. */
+ need_metadir_inode = 1;
+ need_rbmino = 1;
+ need_rsumino = 1;
+ have_uquotino = 0;
+ have_gquotino = 0;
+ have_pquotino = 0;
return true;
}
@@ -184,16 +434,31 @@ static void
upgrade_filesystem(
struct xfs_mount *mp)
{
+ struct xfs_sb new_sb;
struct xfs_buf *bp;
bool dirty = false;
int error;
+ memcpy(&new_sb, &mp->m_sb, sizeof(struct xfs_sb));
+
if (add_inobtcount)
- dirty |= set_inobtcount(mp);
+ dirty |= set_inobtcount(mp, &new_sb);
if (add_bigtime)
- dirty |= set_bigtime(mp);
-
- if (no_modify || !dirty)
+ dirty |= set_bigtime(mp, &new_sb);
+ if (add_finobt)
+ dirty |= set_finobt(mp, &new_sb);
+ if (add_reflink)
+ dirty |= set_reflink(mp, &new_sb);
+ if (add_rmapbt)
+ dirty |= set_rmapbt(mp, &new_sb);
+ if (add_metadir)
+ dirty |= set_metadir(mp, &new_sb);
+ if (!dirty)
+ return;
+
+ check_new_v5_geometry(mp, &new_sb);
+ memcpy(&mp->m_sb, &new_sb, sizeof(struct xfs_sb));
+ if (no_modify)
return;
bp = libxfs_getsb(mp);
diff --git a/repair/phase4.c b/repair/phase4.c
index 7f23d564..b752b07c 100644
--- a/repair/phase4.c
+++ b/repair/phase4.c
@@ -303,7 +303,10 @@ phase4(xfs_mount_t *mp)
if (xfs_has_metadir(mp) &&
(is_inode_free(irec, 1) || !inode_isadir(irec, 1))) {
need_metadir_inode = true;
- if (no_modify)
+ if (add_metadir)
+ do_warn(
+ _("metadata directory root inode needs to be initialized\n"));
+ else if (no_modify)
do_warn(
_("metadata directory root inode would be lost\n"));
else
diff --git a/repair/protos.h b/repair/protos.h
index 83734e85..51432703 100644
--- a/repair/protos.h
+++ b/repair/protos.h
@@ -43,3 +43,4 @@ void phase7(struct xfs_mount *, int);
int verify_set_agheader(struct xfs_mount *, struct xfs_buf *,
struct xfs_sb *, struct xfs_agf *, struct xfs_agi *,
xfs_agnumber_t);
+bool wipe_pre_metadir_file(xfs_ino_t ino);
diff --git a/repair/rmap.c b/repair/rmap.c
index 6a497c30..a72c3b27 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -49,8 +49,8 @@ bool
rmap_needs_work(
struct xfs_mount *mp)
{
- return xfs_has_reflink(mp) ||
- xfs_has_rmapbt(mp);
+ return xfs_has_reflink(mp) || add_reflink ||
+ xfs_has_rmapbt(mp) || add_rmapbt;
}
/*
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 9fc81a83..95360776 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -67,6 +67,10 @@ enum c_opt_nums {
CONVERT_LAZY_COUNT = 0,
CONVERT_INOBTCOUNT,
CONVERT_BIGTIME,
+ CONVERT_FINOBT,
+ CONVERT_REFLINK,
+ CONVERT_RMAPBT,
+ CONVERT_METADIR,
C_MAX_OPTS,
};
@@ -74,6 +78,10 @@ static char *c_opts[] = {
[CONVERT_LAZY_COUNT] = "lazycount",
[CONVERT_INOBTCOUNT] = "inobtcount",
[CONVERT_BIGTIME] = "bigtime",
+ [CONVERT_FINOBT] = "finobt",
+ [CONVERT_REFLINK] = "reflink",
+ [CONVERT_RMAPBT] = "rmapbt",
+ [CONVERT_METADIR] = "metadir",
[C_MAX_OPTS] = NULL,
};
@@ -324,6 +332,42 @@ process_args(int argc, char **argv)
_("-c bigtime only supports upgrades\n"));
add_bigtime = true;
break;
+ case CONVERT_FINOBT:
+ if (!val)
+ do_abort(
+ _("-c finobt requires a parameter\n"));
+ if (strtol(val, NULL, 0) != 1)
+ do_abort(
+ _("-c finobt only supports upgrades\n"));
+ add_finobt = true;
+ break;
+ case CONVERT_REFLINK:
+ if (!val)
+ do_abort(
+ _("-c reflink requires a parameter\n"));
+ if (strtol(val, NULL, 0) != 1)
+ do_abort(
+ _("-c reflink only supports upgrades\n"));
+ add_reflink = true;
+ break;
+ case CONVERT_RMAPBT:
+ if (!val)
+ do_abort(
+ _("-c rmapbt requires a parameter\n"));
+ if (strtol(val, NULL, 0) != 1)
+ do_abort(
+ _("-c rmapbt only supports upgrades\n"));
+ add_rmapbt = true;
+ break;
+ case CONVERT_METADIR:
+ if (!val)
+ do_abort(
+ _("-c metadir requires a parameter\n"));
+ if (strtol(val, NULL, 0) != 1)
+ do_abort(
+ _("-c metadir only supports upgrades\n"));
+ add_metadir = true;
+ break;
default:
unknown('c', val);
break;
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 02/16] xfsprogs: Move extent count limits to xfs_format.h
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 01/16] xfsprogs: xfs_repair: allow administrators to add older v5 features Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 03/16] xfsprogs: Introduce xfs_iext_max_nextents() helper Chandan Babu R
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
Maximum values associated with extent counters i.e. Maximum extent length,
Maximum data extents and Maximum xattr extents are dictated by the on-disk
format. Hence move these definitions over to xfs_format.h.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libxfs/xfs_format.h | 7 +++++++
libxfs/xfs_types.h | 7 -------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 0bc54104..bef1727b 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -872,6 +872,13 @@ enum xfs_dinode_fmt {
{ XFS_DINODE_FMT_BTREE, "btree" }, \
{ XFS_DINODE_FMT_UUID, "uuid" }
+/*
+ * 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 */
+
/*
* Inode minimum and maximum sizes.
*/
diff --git a/libxfs/xfs_types.h b/libxfs/xfs_types.h
index d0afc3d1..dbe5bb56 100644
--- a/libxfs/xfs_types.h
+++ b/libxfs/xfs_types.h
@@ -56,13 +56,6 @@ typedef void * xfs_failaddr_t;
#define NULLFSINO ((xfs_ino_t)-1)
#define NULLAGINO ((xfs_agino_t)-1)
-/*
- * 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 */
-
/*
* Minimum and maximum blocksize and sectorsize.
* The blocksize upper limit is pretty much arbitrary.
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 03/16] xfsprogs: Introduce xfs_iext_max_nextents() helper
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 01/16] xfsprogs: xfs_repair: allow administrators to add older v5 features Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 02/16] xfsprogs: Move extent count limits to xfs_format.h Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 04/16] xfsprogs: Rename MAXEXTNUM, MAXAEXTNUM to XFS_IFORK_EXTCNT_MAXS32, XFS_IFORK_EXTCNT_MAXS16 Chandan Babu R
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
xfs_iext_max_nextents() returns the maximum number of extents possible for one
of data, cow or attribute fork. This helper will be extended further in a
future commit when maximum extent counts associated with data/attribute forks
are increased.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libxfs/xfs_bmap.c | 9 ++++-----
libxfs/xfs_inode_buf.c | 8 +++-----
libxfs/xfs_inode_fork.c | 5 +++--
libxfs/xfs_inode_fork.h | 9 +++++++++
repair/dinode.c | 7 ++++---
5 files changed, 23 insertions(+), 15 deletions(-)
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index c8932f17..cb34c768 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -69,13 +69,12 @@ xfs_bmap_compute_maxlevels(
* ATTR2 we have to assume the worst case scenario of a minimum size
* available.
*/
- if (whichfork == XFS_DATA_FORK) {
- maxleafents = MAXEXTNUM;
+ maxleafents = xfs_iext_max_nextents(mp, whichfork);
+ if (whichfork == XFS_DATA_FORK)
sz = xfs_bmdr_space_calc(MINDBTPTRS);
- } else {
- maxleafents = MAXAEXTNUM;
+ else
sz = xfs_bmdr_space_calc(MINABTPTRS);
- }
+
maxrootrecs = xfs_bmdr_maxrecs(sz, 0);
minleafrecs = mp->m_bmap_dmnr[0];
minnoderecs = mp->m_bmap_dmnr[1];
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 59e9a814..fb271ef1 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -340,6 +340,7 @@ xfs_dinode_verify_fork(
int whichfork)
{
uint32_t di_nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
+ xfs_extnum_t max_extents;
switch (XFS_DFORK_FORMAT(dip, whichfork)) {
case XFS_DINODE_FMT_LOCAL:
@@ -361,12 +362,9 @@ xfs_dinode_verify_fork(
return __this_address;
break;
case XFS_DINODE_FMT_BTREE:
- if (whichfork == XFS_ATTR_FORK) {
- if (di_nextents > MAXAEXTNUM)
- return __this_address;
- } else if (di_nextents > MAXEXTNUM) {
+ max_extents = xfs_iext_max_nextents(mp, whichfork);
+ if (di_nextents > max_extents)
return __this_address;
- }
break;
default:
return __this_address;
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index e3979cee..c943aeb2 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -727,6 +727,7 @@ xfs_iext_count_may_overflow(
int whichfork,
int nr_to_add)
{
+ struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
uint64_t max_exts;
uint64_t nr_exts;
@@ -734,9 +735,9 @@ xfs_iext_count_may_overflow(
if (whichfork == XFS_COW_FORK)
return 0;
- max_exts = (whichfork == XFS_ATTR_FORK) ? MAXAEXTNUM : MAXEXTNUM;
+ max_exts = xfs_iext_max_nextents(mp, whichfork);
- if (XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
+ if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
max_exts = 10;
nr_exts = ifp->if_nextents + nr_to_add;
diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h
index cf82be26..6ba38c15 100644
--- a/libxfs/xfs_inode_fork.h
+++ b/libxfs/xfs_inode_fork.h
@@ -133,6 +133,15 @@ static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
return ifp->if_format;
}
+static inline xfs_extnum_t xfs_iext_max_nextents(struct xfs_mount *mp,
+ int whichfork)
+{
+ if (whichfork == XFS_DATA_FORK || whichfork == XFS_COW_FORK)
+ return MAXEXTNUM;
+
+ return MAXAEXTNUM;
+}
+
struct xfs_ifork *xfs_ifork_alloc(enum xfs_dinode_fmt format,
xfs_extnum_t nextents);
struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
diff --git a/repair/dinode.c b/repair/dinode.c
index 0ffb3e6e..7b472a54 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -1808,6 +1808,7 @@ _("bad attr fork offset %d in inode %" PRIu64 ", max=%zu\n"),
*/
static int
process_inode_blocks_and_extents(
+ struct xfs_mount *mp,
xfs_dinode_t *dino,
xfs_rfsblock_t nblocks,
uint64_t nextents,
@@ -1831,7 +1832,7 @@ _("bad nblocks %llu for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
}
}
- if (nextents > MAXEXTNUM) {
+ if (nextents > xfs_iext_max_nextents(mp, XFS_DATA_FORK)) {
do_warn(
_("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
nextents, lino);
@@ -1854,7 +1855,7 @@ _("bad nextents %d for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
}
}
- if (anextents > MAXAEXTNUM) {
+ if (anextents > xfs_iext_max_nextents(mp, XFS_ATTR_FORK)) {
do_warn(
_("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
anextents, lino);
@@ -2969,7 +2970,7 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "),
/*
* correct space counters if required
*/
- if (process_inode_blocks_and_extents(dino, totblocks + atotblocks,
+ if (process_inode_blocks_and_extents(mp, dino, totblocks + atotblocks,
nextents, anextents, lino, dirty) != 0)
goto clear_bad_out;
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 04/16] xfsprogs: Rename MAXEXTNUM, MAXAEXTNUM to XFS_IFORK_EXTCNT_MAXS32, XFS_IFORK_EXTCNT_MAXS16
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (2 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 03/16] xfsprogs: Introduce xfs_iext_max_nextents() helper Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 05/16] xfsprogs: Use xfs_extnum_t instead of basic data types Chandan Babu R
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
In preparation for introducing larger extent count limits, this commit renames
existing extent count limits based on their signedness and width.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libxfs/xfs_format.h | 8 ++++----
libxfs/xfs_inode_fork.h | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index bef1727b..65ad15fc 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -873,11 +873,11 @@ enum xfs_dinode_fmt {
{ XFS_DINODE_FMT_UUID, "uuid" }
/*
- * Max values for extlen, extnum, aextnum.
+ * Max values for extlen, disk inode's extent counters.
*/
-#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_IFORK_EXTCNT_MAXS32 ((xfs_extnum_t)0x7fffffff) /* Signed 32-bits */
+#define XFS_IFORK_EXTCNT_MAXS16 ((xfs_aextnum_t)0x7fff) /* Signed 16-bits */
/*
* Inode minimum and maximum sizes.
diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h
index 6ba38c15..e8fe5b47 100644
--- a/libxfs/xfs_inode_fork.h
+++ b/libxfs/xfs_inode_fork.h
@@ -137,9 +137,9 @@ static inline xfs_extnum_t xfs_iext_max_nextents(struct xfs_mount *mp,
int whichfork)
{
if (whichfork == XFS_DATA_FORK || whichfork == XFS_COW_FORK)
- return MAXEXTNUM;
+ return XFS_IFORK_EXTCNT_MAXS32;
- return MAXAEXTNUM;
+ return XFS_IFORK_EXTCNT_MAXS16;
}
struct xfs_ifork *xfs_ifork_alloc(enum xfs_dinode_fmt format,
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 05/16] xfsprogs: Use xfs_extnum_t instead of basic data types
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (3 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 04/16] xfsprogs: Rename MAXEXTNUM, MAXAEXTNUM to XFS_IFORK_EXTCNT_MAXS32, XFS_IFORK_EXTCNT_MAXS16 Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 06/16] xfsprogs: Introduce xfs_dfork_nextents() helper Chandan Babu R
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
xfs_extnum_t is the type to use to declare variables which have values
obtained from xfs_dinode->di_[a]nextents. This commit replaces basic
types (e.g. uint32_t) with xfs_extnum_t for such variables.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
db/bmap.c | 2 +-
db/frag.c | 2 +-
libxfs/xfs_bmap.c | 2 +-
libxfs/xfs_inode_buf.c | 2 +-
libxfs/xfs_inode_fork.c | 2 +-
repair/dinode.c | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/db/bmap.c b/db/bmap.c
index 5f81d2b5..50f0474b 100644
--- a/db/bmap.c
+++ b/db/bmap.c
@@ -47,7 +47,7 @@ bmap(
int n;
int nex;
xfs_fsblock_t nextbno;
- int nextents;
+ xfs_extnum_t nextents;
xfs_bmbt_ptr_t *pp;
xfs_bmdr_block_t *rblock;
typnm_t typ;
diff --git a/db/frag.c b/db/frag.c
index 26c3c87e..f324e776 100644
--- a/db/frag.c
+++ b/db/frag.c
@@ -273,7 +273,7 @@ process_fork(
int whichfork)
{
extmap_t *extmap;
- int nex;
+ xfs_extnum_t nex;
nex = XFS_DFORK_NEXTENTS(dip, whichfork);
if (!nex)
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index cb34c768..19db26e6 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -49,7 +49,7 @@ xfs_bmap_compute_maxlevels(
{
int level; /* btree level */
uint maxblocks; /* max blocks at this level */
- uint maxleafents; /* max leaf entries possible */
+ xfs_extnum_t maxleafents; /* max leaf entries possible */
int maxrootrecs; /* max records in root block */
int minleafrecs; /* min records in leaf block */
int minnoderecs; /* min records in node block */
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index fb271ef1..72c1c579 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -339,7 +339,7 @@ xfs_dinode_verify_fork(
struct xfs_mount *mp,
int whichfork)
{
- uint32_t di_nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
+ xfs_extnum_t di_nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
xfs_extnum_t max_extents;
switch (XFS_DFORK_FORMAT(dip, whichfork)) {
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index c943aeb2..61fb0341 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -105,7 +105,7 @@ xfs_iformat_extents(
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
int state = xfs_bmap_fork_to_state(whichfork);
- int nex = XFS_DFORK_NEXTENTS(dip, whichfork);
+ xfs_extnum_t nex = XFS_DFORK_NEXTENTS(dip, whichfork);
int size = nex * sizeof(xfs_bmbt_rec_t);
struct xfs_iext_cursor icur;
struct xfs_bmbt_rec *dp;
diff --git a/repair/dinode.c b/repair/dinode.c
index 7b472a54..94b30ae5 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -967,7 +967,7 @@ process_exinode(
xfs_bmbt_rec_t *rp;
xfs_fileoff_t first_key;
xfs_fileoff_t last_key;
- int32_t numrecs;
+ xfs_extnum_t numrecs;
int ret;
lino = XFS_AGINO_TO_INO(mp, agno, ino);
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 06/16] xfsprogs: Introduce xfs_dfork_nextents() helper
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (4 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 05/16] xfsprogs: Use xfs_extnum_t instead of basic data types Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 07/16] xfsprogs: xfs_dfork_nextents: Return extent count via an out argument Chandan Babu R
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
This commit replaces the macro XFS_DFORK_NEXTENTS() with the helper function
xfs_dfork_nextents(). As of this commit, xfs_dfork_nextents() returns the same
value as XFS_DFORK_NEXTENTS(). A future commit which extends inode's extent
counter fields will add more logic to this helper.
This commit also replaces direct accesses to xfs_dinode->di_[a]nextents
with calls to xfs_dfork_nextents().
No functional changes have been made.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
db/bmap.c | 6 ++--
db/btdump.c | 4 +--
db/check.c | 27 ++++++++++-------
db/frag.c | 6 ++--
db/inode.c | 14 +++++----
db/metadump.c | 4 +--
libxfs/xfs_format.h | 28 ++++++++++++++---
libxfs/xfs_inode_buf.c | 16 ++++++----
libxfs/xfs_inode_fork.c | 9 +++---
repair/attr_repair.c | 2 +-
repair/bmap_repair.c | 4 +--
repair/dinode.c | 66 ++++++++++++++++++++++++-----------------
repair/prefetch.c | 2 +-
13 files changed, 117 insertions(+), 71 deletions(-)
diff --git a/db/bmap.c b/db/bmap.c
index 50f0474b..a33815fe 100644
--- a/db/bmap.c
+++ b/db/bmap.c
@@ -68,7 +68,7 @@ bmap(
ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS ||
fmt == XFS_DINODE_FMT_BTREE);
if (fmt == XFS_DINODE_FMT_EXTENTS) {
- nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
+ nextents = xfs_dfork_nextents(dip, whichfork);
xp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
for (ep = xp; ep < &xp[nextents] && n < nex; ep++) {
if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep))
@@ -158,9 +158,9 @@ bmap_f(
push_cur();
set_cur_inode(iocur_top->ino);
dip = iocur_top->data;
- if (be32_to_cpu(dip->di_nextents))
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK))
dfork = 1;
- if (be16_to_cpu(dip->di_anextents))
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK))
afork = 1;
pop_cur();
}
diff --git a/db/btdump.c b/db/btdump.c
index cb9ca082..d48ce6ca 100644
--- a/db/btdump.c
+++ b/db/btdump.c
@@ -166,13 +166,13 @@ dump_inode(
dip = iocur_top->data;
if (attrfork) {
- if (!dip->di_anextents ||
+ if (!xfs_dfork_nextents(dip, XFS_ATTR_FORK) ||
dip->di_aformat != XFS_DINODE_FMT_BTREE) {
dbprintf(_("attr fork not in btree format\n"));
return 0;
}
} else {
- if (!dip->di_nextents ||
+ if (!xfs_dfork_nextents(dip, XFS_DATA_FORK) ||
dip->di_format != XFS_DINODE_FMT_BTREE) {
dbprintf(_("data fork not in btree format\n"));
return 0;
diff --git a/db/check.c b/db/check.c
index def1db83..eb736ab7 100644
--- a/db/check.c
+++ b/db/check.c
@@ -2720,7 +2720,7 @@ process_exinode(
xfs_bmbt_rec_t *rp;
rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
- *nex = XFS_DFORK_NEXTENTS(dip, whichfork);
+ *nex = xfs_dfork_nextents(dip, whichfork);
if (*nex < 0 || *nex > XFS_DFORK_SIZE(dip, mp, whichfork) /
sizeof(xfs_bmbt_rec_t)) {
if (!sflag || id->ilist)
@@ -2744,12 +2744,14 @@ process_inode(
inodata_t *id = NULL;
xfs_ino_t ino;
xfs_extnum_t nextents = 0;
+ xfs_extnum_t dnextents;
int security;
xfs_rfsblock_t totblocks;
xfs_rfsblock_t totdblocks = 0;
xfs_rfsblock_t totiblocks = 0;
dbm_t type;
xfs_extnum_t anextents = 0;
+ xfs_extnum_t danextents;
xfs_rfsblock_t atotdblocks = 0;
xfs_rfsblock_t atotiblocks = 0;
xfs_qcnt_t bc = 0;
@@ -2878,14 +2880,17 @@ process_inode(
error++;
return;
}
+
+ dnextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
+ danextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+
if (verbose || (id && id->ilist) || CHECK_BLIST(bno))
dbprintf(_("inode %lld mode %#o fmt %s "
"afmt %s "
"nex %d anex %d nblk %lld sz %lld%s%s%s%s%s%s%s\n"),
id->ino, mode, fmtnames[(int)dip->di_format],
fmtnames[(int)dip->di_aformat],
- be32_to_cpu(dip->di_nextents),
- be16_to_cpu(dip->di_anextents),
+ dnextents, danextents,
be64_to_cpu(dip->di_nblocks), be64_to_cpu(dip->di_size),
diflags & XFS_DIFLAG_REALTIME ? " rt" : "",
diflags & XFS_DIFLAG_PREALLOC ? " pre" : "",
@@ -2903,19 +2908,19 @@ process_inode(
if (xfs_has_metadir(mp) &&
id->ino == mp->m_sb.sb_metadirino)
addlink_inode(id);
- blkmap = blkmap_alloc(be32_to_cpu(dip->di_nextents));
+ blkmap = blkmap_alloc(dnextents);
break;
case S_IFREG:
if (diflags & XFS_DIFLAG_REALTIME)
type = DBM_RTDATA;
else if (id->ino == mp->m_sb.sb_rbmino) {
type = DBM_RTBITMAP;
- blkmap = blkmap_alloc(be32_to_cpu(dip->di_nextents));
+ blkmap = blkmap_alloc(dnextents);
if (!xfs_has_metadir(mp))
addlink_inode(id);
} else if (id->ino == mp->m_sb.sb_rsumino) {
type = DBM_RTSUM;
- blkmap = blkmap_alloc(be32_to_cpu(dip->di_nextents));
+ blkmap = blkmap_alloc(dnextents);
if (!xfs_has_metadir(mp))
addlink_inode(id);
}
@@ -2923,7 +2928,7 @@ process_inode(
id->ino == mp->m_sb.sb_gquotino ||
id->ino == mp->m_sb.sb_pquotino) {
type = DBM_QUOTA;
- blkmap = blkmap_alloc(be32_to_cpu(dip->di_nextents));
+ blkmap = blkmap_alloc(dnextents);
if (!xfs_has_metadir(mp))
addlink_inode(id);
}
@@ -3006,17 +3011,17 @@ process_inode(
be64_to_cpu(dip->di_nblocks), id->ino, totblocks);
error++;
}
- if (nextents != be32_to_cpu(dip->di_nextents)) {
+ if (nextents != dnextents) {
if (v)
dbprintf(_("bad nextents %d for inode %lld, counted %d\n"),
- be32_to_cpu(dip->di_nextents), id->ino, nextents);
+ dnextents, id->ino, nextents);
error++;
}
- if (anextents != be16_to_cpu(dip->di_anextents)) {
+ if (anextents != danextents) {
if (v)
dbprintf(_("bad anextents %d for inode %lld, counted "
"%d\n"),
- be16_to_cpu(dip->di_anextents), id->ino, anextents);
+ danextents, id->ino, anextents);
error++;
}
if (type == DBM_DIR)
diff --git a/db/frag.c b/db/frag.c
index f324e776..4105960d 100644
--- a/db/frag.c
+++ b/db/frag.c
@@ -262,9 +262,11 @@ process_exinode(
int whichfork)
{
xfs_bmbt_rec_t *rp;
+ xfs_extnum_t nextents;
rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
- process_bmbt_reclist(rp, XFS_DFORK_NEXTENTS(dip, whichfork), extmapp);
+ nextents = xfs_dfork_nextents(dip, whichfork);
+ process_bmbt_reclist(rp, nextents, extmapp);
}
static void
@@ -275,7 +277,7 @@ process_fork(
extmap_t *extmap;
xfs_extnum_t nex;
- nex = XFS_DFORK_NEXTENTS(dip, whichfork);
+ nex = xfs_dfork_nextents(dip, whichfork);
if (!nex)
return;
extmap = extmap_alloc(nex);
diff --git a/db/inode.c b/db/inode.c
index ee0344d5..b09f9386 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -278,7 +278,7 @@ inode_a_bmx_count(
return 0;
ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff));
return dip->di_aformat == XFS_DINODE_FMT_EXTENTS ?
- be16_to_cpu(dip->di_anextents) : 0;
+ xfs_dfork_nextents(dip, XFS_ATTR_FORK) : 0;
}
static int
@@ -332,6 +332,7 @@ inode_a_size(
{
struct xfs_attr_shortform *asf;
xfs_dinode_t *dip;
+ xfs_extnum_t nextents;
ASSERT(startoff == 0);
ASSERT(idx == 0);
@@ -341,8 +342,8 @@ inode_a_size(
asf = (struct xfs_attr_shortform *)XFS_DFORK_APTR(dip);
return bitize(be16_to_cpu(asf->hdr.totsize));
case XFS_DINODE_FMT_EXTENTS:
- return (int)be16_to_cpu(dip->di_anextents) *
- bitsz(xfs_bmbt_rec_t);
+ nextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ return nextents * bitsz(struct xfs_bmbt_rec);
case XFS_DINODE_FMT_BTREE:
return bitize((int)XFS_DFORK_ASIZE(dip, mp));
default:
@@ -503,7 +504,7 @@ inode_u_bmx_count(
dip = obj;
ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff));
return dip->di_format == XFS_DINODE_FMT_EXTENTS ?
- be32_to_cpu(dip->di_nextents) : 0;
+ xfs_dfork_nextents(dip, XFS_DATA_FORK) : 0;
}
static int
@@ -589,6 +590,7 @@ inode_u_size(
int idx)
{
xfs_dinode_t *dip;
+ xfs_extnum_t nextents;
ASSERT(startoff == 0);
ASSERT(idx == 0);
@@ -599,8 +601,8 @@ inode_u_size(
case XFS_DINODE_FMT_LOCAL:
return bitize((int)be64_to_cpu(dip->di_size));
case XFS_DINODE_FMT_EXTENTS:
- return (int)be32_to_cpu(dip->di_nextents) *
- bitsz(xfs_bmbt_rec_t);
+ nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
+ return nextents * bitsz(struct xfs_bmbt_rec);
case XFS_DINODE_FMT_BTREE:
return bitize((int)XFS_DFORK_DSIZE(dip, mp));
case XFS_DINODE_FMT_UUID:
diff --git a/db/metadump.c b/db/metadump.c
index 1522380f..891de80d 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -2314,7 +2314,7 @@ process_exinode(
whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK;
- nex = XFS_DFORK_NEXTENTS(dip, whichfork);
+ nex = xfs_dfork_nextents(dip, whichfork);
used = nex * sizeof(xfs_bmbt_rec_t);
if (nex < 0 || used > XFS_DFORK_SIZE(dip, mp, whichfork)) {
if (show_warnings)
@@ -2369,7 +2369,7 @@ static int
process_dev_inode(
xfs_dinode_t *dip)
{
- if (XFS_DFORK_NEXTENTS(dip, XFS_DATA_FORK)) {
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK)) {
if (show_warnings)
print_warning("inode %llu has unexpected extents",
(unsigned long long)cur_ino);
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 65ad15fc..e9af506d 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -929,10 +929,30 @@ enum xfs_dinode_fmt {
((w) == XFS_DATA_FORK ? \
(dip)->di_format : \
(dip)->di_aformat)
-#define XFS_DFORK_NEXTENTS(dip,w) \
- ((w) == XFS_DATA_FORK ? \
- be32_to_cpu((dip)->di_nextents) : \
- be16_to_cpu((dip)->di_anextents))
+
+static inline xfs_extnum_t
+xfs_dfork_nextents(
+ struct xfs_dinode *dip,
+ int whichfork)
+{
+ xfs_extnum_t nextents = 0;
+
+ switch (whichfork) {
+ case XFS_DATA_FORK:
+ nextents = be32_to_cpu(dip->di_nextents);
+ break;
+
+ case XFS_ATTR_FORK:
+ nextents = be16_to_cpu(dip->di_anextents);
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ return nextents;
+}
/*
* For block and character special files the 32bit dev_t is stored at the
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 72c1c579..63ec5794 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -339,9 +339,11 @@ xfs_dinode_verify_fork(
struct xfs_mount *mp,
int whichfork)
{
- xfs_extnum_t di_nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
+ xfs_extnum_t di_nextents;
xfs_extnum_t max_extents;
+ di_nextents = xfs_dfork_nextents(dip, whichfork);
+
switch (XFS_DFORK_FORMAT(dip, whichfork)) {
case XFS_DINODE_FMT_LOCAL:
/*
@@ -471,6 +473,8 @@ xfs_dinode_verify(
uint16_t flags;
uint64_t flags2;
uint64_t di_size;
+ xfs_rfsblock_t nblocks;
+ xfs_extnum_t nextents;
if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
return __this_address;
@@ -501,10 +505,12 @@ xfs_dinode_verify(
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
return __this_address;
+ nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
+ nextents += xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ nblocks = be64_to_cpu(dip->di_nblocks);
+
/* Fork checks carried over from xfs_iformat_fork */
- if (mode &&
- be32_to_cpu(dip->di_nextents) + be16_to_cpu(dip->di_anextents) >
- be64_to_cpu(dip->di_nblocks))
+ if (mode && nextents > nblocks)
return __this_address;
if (mode && XFS_DFORK_BOFF(dip) > mp->m_sb.sb_inodesize)
@@ -561,7 +567,7 @@ xfs_dinode_verify(
default:
return __this_address;
}
- if (dip->di_anextents)
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK))
return __this_address;
}
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index 61fb0341..4aa9b7d3 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -105,7 +105,7 @@ xfs_iformat_extents(
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
int state = xfs_bmap_fork_to_state(whichfork);
- xfs_extnum_t nex = XFS_DFORK_NEXTENTS(dip, whichfork);
+ xfs_extnum_t nex = xfs_dfork_nextents(dip, whichfork);
int size = nex * sizeof(xfs_bmbt_rec_t);
struct xfs_iext_cursor icur;
struct xfs_bmbt_rec *dp;
@@ -232,7 +232,7 @@ xfs_iformat_data_fork(
* depend on it.
*/
ip->i_df.if_format = dip->di_format;
- ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents);
+ ip->i_df.if_nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
switch (inode->i_mode & S_IFMT) {
case S_IFIFO:
@@ -299,14 +299,15 @@ xfs_iformat_attr_fork(
struct xfs_inode *ip,
struct xfs_dinode *dip)
{
+ xfs_extnum_t naextents;
int error = 0;
/*
* Initialize the extent count early, as the per-format routines may
* depend on it.
*/
- ip->i_afp = xfs_ifork_alloc(dip->di_aformat,
- be16_to_cpu(dip->di_anextents));
+ naextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ ip->i_afp = xfs_ifork_alloc(dip->di_aformat, naextents);
switch (ip->i_afp->if_format) {
case XFS_DINODE_FMT_LOCAL:
diff --git a/repair/attr_repair.c b/repair/attr_repair.c
index 927dd095..e842db3c 100644
--- a/repair/attr_repair.c
+++ b/repair/attr_repair.c
@@ -1083,7 +1083,7 @@ process_longform_attr(
bno = blkmap_get(blkmap, 0);
if (bno == NULLFSBLOCK) {
if (dip->di_aformat == XFS_DINODE_FMT_EXTENTS &&
- be16_to_cpu(dip->di_anextents) == 0)
+ xfs_dfork_nextents(dip, XFS_ATTR_FORK) == 0)
return(0); /* the kernel can handle this state */
do_warn(
_("block 0 of inode %" PRIu64 " attribute fork is missing\n"),
diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c
index f70194fb..25f02882 100644
--- a/repair/bmap_repair.c
+++ b/repair/bmap_repair.c
@@ -572,7 +572,7 @@ rebuild_bmap(
*/
switch (whichfork) {
case XFS_DATA_FORK:
- if ((*dinop)->di_nextents == 0)
+ if (!xfs_dfork_nextents(*dinop, XFS_DATA_FORK))
return 0;
(*dinop)->di_format = XFS_DINODE_FMT_EXTENTS;
(*dinop)->di_nextents = 0;
@@ -580,7 +580,7 @@ rebuild_bmap(
*dirty = 1;
break;
case XFS_ATTR_FORK:
- if ((*dinop)->di_anextents == 0)
+ if (!xfs_dfork_nextents(*dinop, XFS_ATTR_FORK))
return 0;
(*dinop)->di_aformat = XFS_DINODE_FMT_EXTENTS;
(*dinop)->di_anextents = 0;
diff --git a/repair/dinode.c b/repair/dinode.c
index 94b30ae5..dc6adb4c 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -69,7 +69,7 @@ _("clearing inode %" PRIu64 " attributes\n"), ino_num);
fprintf(stderr,
_("would have cleared inode %" PRIu64 " attributes\n"), ino_num);
- if (be16_to_cpu(dino->di_anextents) != 0) {
+ if (xfs_dfork_nextents(dino, XFS_ATTR_FORK) != 0) {
if (no_modify)
return(1);
dino->di_anextents = cpu_to_be16(0);
@@ -973,7 +973,7 @@ process_exinode(
lino = XFS_AGINO_TO_INO(mp, agno, ino);
rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
*tot = 0;
- numrecs = XFS_DFORK_NEXTENTS(dip, whichfork);
+ numrecs = xfs_dfork_nextents(dip, whichfork);
/*
* We've already decided on the maximum number of extents on the inode,
@@ -1050,7 +1050,7 @@ process_symlink_extlist(xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino)
xfs_fileoff_t expected_offset;
xfs_bmbt_rec_t *rp;
xfs_bmbt_irec_t irec;
- int numrecs;
+ xfs_extnum_t numrecs;
int i;
int max_blocks;
@@ -1072,7 +1072,7 @@ _("mismatch between format (%d) and size (%" PRId64 ") in symlink inode %" PRIu6
}
rp = (xfs_bmbt_rec_t *)XFS_DFORK_DPTR(dino);
- numrecs = be32_to_cpu(dino->di_nextents);
+ numrecs = xfs_dfork_nextents(dino, XFS_DATA_FORK);
/*
* the max # of extents in a symlink inode is equal to the
@@ -1578,6 +1578,8 @@ process_check_sb_inodes(
int *type,
int *dirty)
{
+ xfs_extnum_t nextents;
+
if (lino == mp->m_sb.sb_rootino) {
if (*type != XR_INO_DIR) {
do_warn(_("root inode %" PRIu64 " has bad type 0x%x\n"),
@@ -1632,10 +1634,12 @@ _("realtime summary inode %" PRIu64 " has bad type 0x%x, "),
do_warn(_("would reset to regular file\n"));
}
}
- if (mp->m_sb.sb_rblocks == 0 && dinoc->di_nextents != 0) {
+
+ nextents = xfs_dfork_nextents(dinoc, XFS_DATA_FORK);
+ if (mp->m_sb.sb_rblocks == 0 && nextents != 0) {
do_warn(
-_("bad # of extents (%u) for realtime summary inode %" PRIu64 "\n"),
- be32_to_cpu(dinoc->di_nextents), lino);
+_("bad # of extents (%d) for realtime summary inode %" PRIu64 "\n"),
+ nextents, lino);
return 1;
}
return 0;
@@ -1653,10 +1657,12 @@ _("realtime bitmap inode %" PRIu64 " has bad type 0x%x, "),
do_warn(_("would reset to regular file\n"));
}
}
- if (mp->m_sb.sb_rblocks == 0 && dinoc->di_nextents != 0) {
+
+ nextents = xfs_dfork_nextents(dinoc, XFS_DATA_FORK);
+ if (mp->m_sb.sb_rblocks == 0 && nextents != 0) {
do_warn(
-_("bad # of extents (%u) for realtime bitmap inode %" PRIu64 "\n"),
- be32_to_cpu(dinoc->di_nextents), lino);
+_("bad # of extents (%d) for realtime bitmap inode %" PRIu64 "\n"),
+ nextents, lino);
return 1;
}
return 0;
@@ -1816,6 +1822,8 @@ process_inode_blocks_and_extents(
xfs_ino_t lino,
int *dirty)
{
+ xfs_extnum_t dnextents;
+
if (nblocks != be64_to_cpu(dino->di_nblocks)) {
if (!no_modify) {
do_warn(
@@ -1838,20 +1846,19 @@ _("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
nextents, lino);
return 1;
}
- if (nextents != be32_to_cpu(dino->di_nextents)) {
+
+ dnextents = xfs_dfork_nextents(dino, XFS_DATA_FORK);
+ if (nextents != dnextents) {
if (!no_modify) {
do_warn(
_("correcting nextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"),
- lino,
- be32_to_cpu(dino->di_nextents),
- nextents);
+ lino, dnextents, nextents);
dino->di_nextents = cpu_to_be32(nextents);
*dirty = 1;
} else {
do_warn(
_("bad nextents %d for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
- be32_to_cpu(dino->di_nextents),
- lino, nextents);
+ dnextents, lino, nextents);
}
}
@@ -1861,19 +1868,19 @@ _("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
anextents, lino);
return 1;
}
- if (anextents != be16_to_cpu(dino->di_anextents)) {
+
+ dnextents = xfs_dfork_nextents(dino, XFS_ATTR_FORK);
+ if (anextents != dnextents) {
if (!no_modify) {
do_warn(
_("correcting anextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"),
- lino,
- be16_to_cpu(dino->di_anextents), anextents);
+ lino, dnextents, anextents);
dino->di_anextents = cpu_to_be16(anextents);
*dirty = 1;
} else {
do_warn(
_("bad anextents %d for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
- be16_to_cpu(dino->di_anextents),
- lino, anextents);
+ dnextents, lino, anextents);
}
}
@@ -1910,8 +1917,8 @@ process_inode_data_fork(
{
struct xfs_dinode *dino = *dinop;
xfs_ino_t lino = XFS_AGINO_TO_INO(mp, agno, ino);
+ xfs_extnum_t nex;
int err = 0;
- int nex;
int try_rebuild = -1; /* don't know yet */
retry:
@@ -1920,7 +1927,7 @@ retry:
* uses negative values in memory. hence if we see negative numbers
* here, trash it!
*/
- nex = be32_to_cpu(dino->di_nextents);
+ nex = xfs_dfork_nextents(dino, XFS_DATA_FORK);
if (nex < 0)
*nextents = 1;
else
@@ -1970,8 +1977,7 @@ _("rebuilding inode %"PRIu64" data fork\n"),
lino);
try_rebuild = 0;
err = rebuild_bmap(mp, lino, XFS_DATA_FORK,
- be32_to_cpu(dino->di_nextents),
- ino_bpp, dinop, dirty);
+ nex, ino_bpp, dinop, dirty);
dino = *dinop;
if (!err)
goto retry;
@@ -2070,7 +2076,7 @@ retry:
return 0;
}
- *anextents = be16_to_cpu(dino->di_anextents);
+ *anextents = xfs_dfork_nextents(dino, XFS_ATTR_FORK);
if (*anextents > be64_to_cpu(dino->di_nblocks))
*anextents = 1;
@@ -2118,13 +2124,17 @@ retry:
if (!no_modify) {
if (try_rebuild == 1) {
+ xfs_extnum_t danextents;
+
+ danextents = xfs_dfork_nextents(dino,
+ XFS_ATTR_FORK);
do_warn(
_("rebuilding inode %"PRIu64" attr fork\n"),
lino);
try_rebuild = 0;
err = rebuild_bmap(mp, lino, XFS_ATTR_FORK,
- be16_to_cpu(dino->di_anextents),
- ino_bpp, dinop, dirty);
+ danextents, ino_bpp, dinop,
+ dirty);
dino = *dinop;
if (!err)
goto retry;
diff --git a/repair/prefetch.c b/repair/prefetch.c
index ad06addf..19eaf16c 100644
--- a/repair/prefetch.c
+++ b/repair/prefetch.c
@@ -393,7 +393,7 @@ pf_read_exinode(
xfs_dinode_t *dino)
{
pf_read_bmbt_reclist(args, (xfs_bmbt_rec_t *)XFS_DFORK_DPTR(dino),
- be32_to_cpu(dino->di_nextents));
+ xfs_dfork_nextents(dino, XFS_DATA_FORK));
}
static void
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 07/16] xfsprogs: xfs_dfork_nextents: Return extent count via an out argument
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (5 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 06/16] xfsprogs: Introduce xfs_dfork_nextents() helper Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 08/16] xfsprogs: Rename inode's extent counter fields based on their width Chandan Babu R
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
This commit changes xfs_dfork_nextents() to return an error code. The extent
count itself is now returned through an out argument. This facility will be
used by a future commit to indicate an inconsistent ondisk extent count.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
db/bmap.c | 19 ++++++++------
db/btdump.c | 11 +++++---
db/check.c | 23 ++++++++++++++---
db/frag.c | 7 +++---
db/inode.c | 26 +++++++++++++------
db/metadump.c | 12 +++++++--
libxfs/xfs_format.h | 14 ++++++-----
libxfs/xfs_inode_buf.c | 16 +++++++++---
libxfs/xfs_inode_fork.c | 23 +++++++++++++----
repair/attr_repair.c | 11 +++++---
repair/bmap_repair.c | 11 ++++++--
repair/dinode.c | 56 ++++++++++++++++++++++++++++++++---------
repair/prefetch.c | 7 ++++--
13 files changed, 175 insertions(+), 61 deletions(-)
diff --git a/db/bmap.c b/db/bmap.c
index a33815fe..fca01f3c 100644
--- a/db/bmap.c
+++ b/db/bmap.c
@@ -68,11 +68,13 @@ bmap(
ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS ||
fmt == XFS_DINODE_FMT_BTREE);
if (fmt == XFS_DINODE_FMT_EXTENTS) {
- nextents = xfs_dfork_nextents(dip, whichfork);
- xp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
- for (ep = xp; ep < &xp[nextents] && n < nex; ep++) {
- if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep))
- break;
+ if (!xfs_dfork_nextents(dip, whichfork, &nextents)) {
+ xp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
+ for (ep = xp; ep < &xp[nextents] && n < nex; ep++) {
+ if (!bmap_one_extent(ep, &curoffset, eoffset,
+ &n, bep))
+ break;
+ }
}
} else if (fmt == XFS_DINODE_FMT_BTREE) {
push_cur();
@@ -155,12 +157,15 @@ bmap_f(
}
}
if (afork + dfork == 0) {
+ xfs_extnum_t nextents;
push_cur();
set_cur_inode(iocur_top->ino);
dip = iocur_top->data;
- if (xfs_dfork_nextents(dip, XFS_DATA_FORK))
+ if (!xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents) &&
+ nextents)
dfork = 1;
- if (xfs_dfork_nextents(dip, XFS_ATTR_FORK))
+ if (!xfs_dfork_nextents(dip, XFS_ATTR_FORK, &nextents) &&
+ nextents)
afork = 1;
pop_cur();
}
diff --git a/db/btdump.c b/db/btdump.c
index d48ce6ca..b2ab7e28 100644
--- a/db/btdump.c
+++ b/db/btdump.c
@@ -153,6 +153,7 @@ dump_inode(
bool dump_node_blocks,
bool attrfork)
{
+ xfs_extnum_t nextents;
char *prefix;
struct xfs_dinode *dip;
int ret = 0;
@@ -166,14 +167,16 @@ dump_inode(
dip = iocur_top->data;
if (attrfork) {
- if (!xfs_dfork_nextents(dip, XFS_ATTR_FORK) ||
- dip->di_aformat != XFS_DINODE_FMT_BTREE) {
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK, &nextents))
+ return -1;
+ if (!nextents || dip->di_aformat != XFS_DINODE_FMT_BTREE) {
dbprintf(_("attr fork not in btree format\n"));
return 0;
}
} else {
- if (!xfs_dfork_nextents(dip, XFS_DATA_FORK) ||
- dip->di_format != XFS_DINODE_FMT_BTREE) {
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents))
+ return -1;
+ if (!nextents || dip->di_format != XFS_DINODE_FMT_BTREE) {
dbprintf(_("data fork not in btree format\n"));
return 0;
}
diff --git a/db/check.c b/db/check.c
index eb736ab7..79e7978e 100644
--- a/db/check.c
+++ b/db/check.c
@@ -2718,10 +2718,17 @@ process_exinode(
int whichfork)
{
xfs_bmbt_rec_t *rp;
+ int ret;
rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
- *nex = xfs_dfork_nextents(dip, whichfork);
- if (*nex < 0 || *nex > XFS_DFORK_SIZE(dip, mp, whichfork) /
+ ret = xfs_dfork_nextents(dip, whichfork, nex);
+ if (ret) {
+ if (!sflag || id->ilist)
+ dbprintf(_("Corrupt extent count for inode %lld\n"),
+ id->ino);
+ error++;
+ return;
+ } else if (*nex < 0 || *nex > XFS_DFORK_SIZE(dip, mp, whichfork) /
sizeof(xfs_bmbt_rec_t)) {
if (!sflag || id->ilist)
dbprintf(_("bad number of extents %d for inode %lld\n"),
@@ -2881,8 +2888,16 @@ process_inode(
return;
}
- dnextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
- danextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK, &dnextents)) {
+ if (v)
+ dbprintf(_("Corrupt extent count for inode %lld\n"),
+ id->ino);
+ error++;
+ return;
+ }
+
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK, &danextents))
+ ASSERT(0);
if (verbose || (id && id->ilist) || CHECK_BLIST(bno))
dbprintf(_("inode %lld mode %#o fmt %s "
diff --git a/db/frag.c b/db/frag.c
index 4105960d..f60d2ec4 100644
--- a/db/frag.c
+++ b/db/frag.c
@@ -263,9 +263,11 @@ process_exinode(
{
xfs_bmbt_rec_t *rp;
xfs_extnum_t nextents;
+ int error;
rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
- nextents = xfs_dfork_nextents(dip, whichfork);
+ error = xfs_dfork_nextents(dip, whichfork, &nextents);
+ ASSERT(error == 0);
process_bmbt_reclist(rp, nextents, extmapp);
}
@@ -277,8 +279,7 @@ process_fork(
extmap_t *extmap;
xfs_extnum_t nex;
- nex = xfs_dfork_nextents(dip, whichfork);
- if (!nex)
+ if (xfs_dfork_nextents(dip, whichfork, &nex) || !nex)
return;
extmap = extmap_alloc(nex);
switch (XFS_DFORK_FORMAT(dip, whichfork)) {
diff --git a/db/inode.c b/db/inode.c
index b09f9386..c45ec1f7 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -269,6 +269,7 @@ inode_a_bmx_count(
void *obj,
int startoff)
{
+ xfs_extnum_t nextents;
xfs_dinode_t *dip;
ASSERT(bitoffs(startoff) == 0);
@@ -277,8 +278,12 @@ inode_a_bmx_count(
if (!dip->di_forkoff)
return 0;
ASSERT((char *)XFS_DFORK_APTR(dip) - (char *)dip == byteize(startoff));
- return dip->di_aformat == XFS_DINODE_FMT_EXTENTS ?
- xfs_dfork_nextents(dip, XFS_ATTR_FORK) : 0;
+ if (dip->di_aformat != XFS_DINODE_FMT_EXTENTS ||
+ xfs_dfork_nextents(dip, XFS_ATTR_FORK, &nextents)) {
+ nextents = 0;
+ }
+
+ return nextents;
}
static int
@@ -342,7 +347,8 @@ inode_a_size(
asf = (struct xfs_attr_shortform *)XFS_DFORK_APTR(dip);
return bitize(be16_to_cpu(asf->hdr.totsize));
case XFS_DINODE_FMT_EXTENTS:
- nextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK, &nextents))
+ nextents = 0;
return nextents * bitsz(struct xfs_bmbt_rec);
case XFS_DINODE_FMT_BTREE:
return bitize((int)XFS_DFORK_ASIZE(dip, mp));
@@ -497,14 +503,19 @@ inode_u_bmx_count(
void *obj,
int startoff)
{
+ xfs_extnum_t nextents;
xfs_dinode_t *dip;
ASSERT(bitoffs(startoff) == 0);
ASSERT(obj == iocur_top->data);
dip = obj;
ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff));
- return dip->di_format == XFS_DINODE_FMT_EXTENTS ?
- xfs_dfork_nextents(dip, XFS_DATA_FORK) : 0;
+ if (dip->di_format != XFS_DINODE_FMT_EXTENTS ||
+ xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents)) {
+ nextents = 0;
+ }
+
+ return nextents;
}
static int
@@ -590,7 +601,7 @@ inode_u_size(
int idx)
{
xfs_dinode_t *dip;
- xfs_extnum_t nextents;
+ xfs_extnum_t nextents = 0;
ASSERT(startoff == 0);
ASSERT(idx == 0);
@@ -601,7 +612,8 @@ inode_u_size(
case XFS_DINODE_FMT_LOCAL:
return bitize((int)be64_to_cpu(dip->di_size));
case XFS_DINODE_FMT_EXTENTS:
- nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents))
+ nextents = 0;
return nextents * bitsz(struct xfs_bmbt_rec);
case XFS_DINODE_FMT_BTREE:
return bitize((int)XFS_DFORK_DSIZE(dip, mp));
diff --git a/db/metadump.c b/db/metadump.c
index 891de80d..3e3e05c7 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -2314,7 +2314,13 @@ process_exinode(
whichfork = (itype == TYP_ATTR) ? XFS_ATTR_FORK : XFS_DATA_FORK;
- nex = xfs_dfork_nextents(dip, whichfork);
+ if (xfs_dfork_nextents(dip, whichfork, &nex)) {
+ if (show_warnings)
+ print_warning("Corrupt extent count for inode %lld\n",
+ (long long)cur_ino);
+ return 1;
+ }
+
used = nex * sizeof(xfs_bmbt_rec_t);
if (nex < 0 || used > XFS_DFORK_SIZE(dip, mp, whichfork)) {
if (show_warnings)
@@ -2369,7 +2375,9 @@ static int
process_dev_inode(
xfs_dinode_t *dip)
{
- if (xfs_dfork_nextents(dip, XFS_DATA_FORK)) {
+ xfs_extnum_t nextents;
+
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents) || nextents) {
if (show_warnings)
print_warning("inode %llu has unexpected extents",
(unsigned long long)cur_ino);
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index e9af506d..49e627ad 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -930,28 +930,30 @@ enum xfs_dinode_fmt {
(dip)->di_format : \
(dip)->di_aformat)
-static inline xfs_extnum_t
+static inline int
xfs_dfork_nextents(
struct xfs_dinode *dip,
- int whichfork)
+ int whichfork,
+ xfs_extnum_t *nextents)
{
- xfs_extnum_t nextents = 0;
+ int error = 0;
switch (whichfork) {
case XFS_DATA_FORK:
- nextents = be32_to_cpu(dip->di_nextents);
+ *nextents = be32_to_cpu(dip->di_nextents);
break;
case XFS_ATTR_FORK:
- nextents = be16_to_cpu(dip->di_anextents);
+ *nextents = be16_to_cpu(dip->di_anextents);
break;
default:
ASSERT(0);
+ error = -EFSCORRUPTED;
break;
}
- return nextents;
+ return error;
}
/*
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 63ec5794..5ed923ae 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -342,7 +342,8 @@ xfs_dinode_verify_fork(
xfs_extnum_t di_nextents;
xfs_extnum_t max_extents;
- di_nextents = xfs_dfork_nextents(dip, whichfork);
+ if (xfs_dfork_nextents(dip, whichfork, &di_nextents))
+ return __this_address;
switch (XFS_DFORK_FORMAT(dip, whichfork)) {
case XFS_DINODE_FMT_LOCAL:
@@ -475,6 +476,7 @@ xfs_dinode_verify(
uint64_t di_size;
xfs_rfsblock_t nblocks;
xfs_extnum_t nextents;
+ xfs_extnum_t naextents;
if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
return __this_address;
@@ -505,8 +507,13 @@ xfs_dinode_verify(
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
return __this_address;
- nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
- nextents += xfs_dfork_nextents(dip, XFS_ATTR_FORK);
+ if (xfs_dfork_nextents(dip, XFS_DATA_FORK, &nextents))
+ return __this_address;
+
+ if (xfs_dfork_nextents(dip, XFS_ATTR_FORK, &naextents))
+ return __this_address;
+
+ nextents += naextents;
nblocks = be64_to_cpu(dip->di_nblocks);
/* Fork checks carried over from xfs_iformat_fork */
@@ -567,7 +574,8 @@ xfs_dinode_verify(
default:
return __this_address;
}
- if (xfs_dfork_nextents(dip, XFS_ATTR_FORK))
+
+ if (naextents)
return __this_address;
}
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index 4aa9b7d3..6b69d34e 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -105,12 +105,19 @@ xfs_iformat_extents(
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
int state = xfs_bmap_fork_to_state(whichfork);
- xfs_extnum_t nex = xfs_dfork_nextents(dip, whichfork);
- int size = nex * sizeof(xfs_bmbt_rec_t);
+ xfs_extnum_t nex;
+ int size;
struct xfs_iext_cursor icur;
struct xfs_bmbt_rec *dp;
struct xfs_bmbt_irec new;
int i;
+ int error;
+
+ error = xfs_dfork_nextents(dip, whichfork, &nex);
+ if (error)
+ return error;
+
+ size = nex * sizeof(struct xfs_bmbt_rec);
/*
* If the number of extents is unreasonable, then something is wrong and
@@ -232,7 +239,10 @@ xfs_iformat_data_fork(
* depend on it.
*/
ip->i_df.if_format = dip->di_format;
- ip->i_df.if_nextents = xfs_dfork_nextents(dip, XFS_DATA_FORK);
+ error = xfs_dfork_nextents(dip, XFS_DATA_FORK,
+ &ip->i_df.if_nextents);
+ if (error)
+ return error;
switch (inode->i_mode & S_IFMT) {
case S_IFIFO:
@@ -300,13 +310,16 @@ xfs_iformat_attr_fork(
struct xfs_dinode *dip)
{
xfs_extnum_t naextents;
- int error = 0;
+ int error;
+
+ error = xfs_dfork_nextents(dip, XFS_ATTR_FORK, &naextents);
+ if (error)
+ return error;
/*
* Initialize the extent count early, as the per-format routines may
* depend on it.
*/
- naextents = xfs_dfork_nextents(dip, XFS_ATTR_FORK);
ip->i_afp = xfs_ifork_alloc(dip->di_aformat, naextents);
switch (ip->i_afp->if_format) {
diff --git a/repair/attr_repair.c b/repair/attr_repair.c
index e842db3c..c026b4fc 100644
--- a/repair/attr_repair.c
+++ b/repair/attr_repair.c
@@ -1073,6 +1073,7 @@ process_longform_attr(
struct blkmap *blkmap,
int *repair) /* out - 1 if something was fixed */
{
+ xfs_extnum_t anextents;
xfs_fsblock_t bno;
struct xfs_buf *bp;
struct xfs_da_blkinfo *info;
@@ -1082,9 +1083,13 @@ process_longform_attr(
bno = blkmap_get(blkmap, 0);
if (bno == NULLFSBLOCK) {
- if (dip->di_aformat == XFS_DINODE_FMT_EXTENTS &&
- xfs_dfork_nextents(dip, XFS_ATTR_FORK) == 0)
- return(0); /* the kernel can handle this state */
+ if (dip->di_aformat == XFS_DINODE_FMT_EXTENTS) {
+ error = xfs_dfork_nextents(dip, XFS_ATTR_FORK,
+ &anextents);
+ ASSERT(error == 0);
+ if (anextents == 0)
+ return(0); /* the kernel can handle this state */
+ }
do_warn(
_("block 0 of inode %" PRIu64 " attribute fork is missing\n"),
ino);
diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c
index 25f02882..adb798f7 100644
--- a/repair/bmap_repair.c
+++ b/repair/bmap_repair.c
@@ -560,6 +560,7 @@ rebuild_bmap(
struct xfs_buf *bp;
unsigned long long resblks;
xfs_daddr_t bp_bn;
+ xfs_extnum_t nextents;
int bp_length;
int error;
@@ -572,7 +573,10 @@ rebuild_bmap(
*/
switch (whichfork) {
case XFS_DATA_FORK:
- if (!xfs_dfork_nextents(*dinop, XFS_DATA_FORK))
+ error = xfs_dfork_nextents(*dinop, whichfork, &nextents);
+ if (error)
+ return error;
+ if (nextents == 0)
return 0;
(*dinop)->di_format = XFS_DINODE_FMT_EXTENTS;
(*dinop)->di_nextents = 0;
@@ -580,7 +584,10 @@ rebuild_bmap(
*dirty = 1;
break;
case XFS_ATTR_FORK:
- if (!xfs_dfork_nextents(*dinop, XFS_ATTR_FORK))
+ error = xfs_dfork_nextents(*dinop, whichfork, &nextents);
+ if (error)
+ return error;
+ if (nextents == 0)
return 0;
(*dinop)->di_aformat = XFS_DINODE_FMT_EXTENTS;
(*dinop)->di_anextents = 0;
diff --git a/repair/dinode.c b/repair/dinode.c
index dc6adb4c..46f82f64 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -60,6 +60,9 @@ get_forkname(int whichfork)
static int
clear_dinode_attr(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num)
{
+ xfs_extnum_t anextents;
+ int err;
+
ASSERT(dino->di_forkoff != 0);
if (!no_modify)
@@ -69,7 +72,10 @@ _("clearing inode %" PRIu64 " attributes\n"), ino_num);
fprintf(stderr,
_("would have cleared inode %" PRIu64 " attributes\n"), ino_num);
- if (xfs_dfork_nextents(dino, XFS_ATTR_FORK) != 0) {
+ err = xfs_dfork_nextents(dino, XFS_ATTR_FORK, &anextents);
+ ASSERT(err == 0);
+
+ if (anextents != 0) {
if (no_modify)
return(1);
dino->di_anextents = cpu_to_be16(0);
@@ -973,7 +979,9 @@ process_exinode(
lino = XFS_AGINO_TO_INO(mp, agno, ino);
rp = (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, whichfork);
*tot = 0;
- numrecs = xfs_dfork_nextents(dip, whichfork);
+
+ ret = xfs_dfork_nextents(dip, whichfork, &numrecs);
+ ASSERT(ret == 0);
/*
* We've already decided on the maximum number of extents on the inode,
@@ -1053,6 +1061,7 @@ process_symlink_extlist(xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino)
xfs_extnum_t numrecs;
int i;
int max_blocks;
+ int ret;
if (be64_to_cpu(dino->di_size) <= XFS_DFORK_DSIZE(dino, mp)) {
if (dino->di_format == XFS_DINODE_FMT_LOCAL)
@@ -1072,7 +1081,9 @@ _("mismatch between format (%d) and size (%" PRId64 ") in symlink inode %" PRIu6
}
rp = (xfs_bmbt_rec_t *)XFS_DFORK_DPTR(dino);
- numrecs = xfs_dfork_nextents(dino, XFS_DATA_FORK);
+
+ ret = xfs_dfork_nextents(dino, XFS_DATA_FORK, &numrecs);
+ ASSERT(ret == 0);
/*
* the max # of extents in a symlink inode is equal to the
@@ -1579,6 +1590,7 @@ process_check_sb_inodes(
int *dirty)
{
xfs_extnum_t nextents;
+ int ret;
if (lino == mp->m_sb.sb_rootino) {
if (*type != XR_INO_DIR) {
@@ -1635,7 +1647,9 @@ _("realtime summary inode %" PRIu64 " has bad type 0x%x, "),
}
}
- nextents = xfs_dfork_nextents(dinoc, XFS_DATA_FORK);
+ ret = xfs_dfork_nextents(dinoc, XFS_DATA_FORK, &nextents);
+ ASSERT(ret == 0);
+
if (mp->m_sb.sb_rblocks == 0 && nextents != 0) {
do_warn(
_("bad # of extents (%d) for realtime summary inode %" PRIu64 "\n"),
@@ -1658,8 +1672,10 @@ _("realtime bitmap inode %" PRIu64 " has bad type 0x%x, "),
}
}
- nextents = xfs_dfork_nextents(dinoc, XFS_DATA_FORK);
- if (mp->m_sb.sb_rblocks == 0 && nextents != 0) {
+ ret = xfs_dfork_nextents(dinoc, XFS_DATA_FORK, &nextents);
+ ASSERT(ret == 0);
+
+ if (mp->m_sb.sb_rblocks == 0 && nextents != 0) {
do_warn(
_("bad # of extents (%d) for realtime bitmap inode %" PRIu64 "\n"),
nextents, lino);
@@ -1823,6 +1839,7 @@ process_inode_blocks_and_extents(
int *dirty)
{
xfs_extnum_t dnextents;
+ int ret;
if (nblocks != be64_to_cpu(dino->di_nblocks)) {
if (!no_modify) {
@@ -1847,7 +1864,9 @@ _("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
return 1;
}
- dnextents = xfs_dfork_nextents(dino, XFS_DATA_FORK);
+ ret = xfs_dfork_nextents(dino, XFS_DATA_FORK, &dnextents);
+ ASSERT(ret == 0);
+
if (nextents != dnextents) {
if (!no_modify) {
do_warn(
@@ -1869,7 +1888,9 @@ _("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
return 1;
}
- dnextents = xfs_dfork_nextents(dino, XFS_ATTR_FORK);
+ ret = xfs_dfork_nextents(dino, XFS_ATTR_FORK, &dnextents);
+ ASSERT(ret == 0);
+
if (anextents != dnextents) {
if (!no_modify) {
do_warn(
@@ -1920,6 +1941,7 @@ process_inode_data_fork(
xfs_extnum_t nex;
int err = 0;
int try_rebuild = -1; /* don't know yet */
+ int ret;
retry:
/*
@@ -1927,7 +1949,9 @@ retry:
* uses negative values in memory. hence if we see negative numbers
* here, trash it!
*/
- nex = xfs_dfork_nextents(dino, XFS_DATA_FORK);
+ ret = xfs_dfork_nextents(dino, XFS_DATA_FORK, &nex);
+ ASSERT(ret == 0);
+
if (nex < 0)
*nextents = 1;
else
@@ -2076,7 +2100,10 @@ retry:
return 0;
}
- *anextents = xfs_dfork_nextents(dino, XFS_ATTR_FORK);
+ err = xfs_dfork_nextents(dino, XFS_ATTR_FORK,
+ (xfs_extnum_t *)anextents);
+ ASSERT(err == 0);
+
if (*anextents > be64_to_cpu(dino->di_nblocks))
*anextents = 1;
@@ -2126,8 +2153,10 @@ retry:
if (try_rebuild == 1) {
xfs_extnum_t danextents;
- danextents = xfs_dfork_nextents(dino,
- XFS_ATTR_FORK);
+ err = xfs_dfork_nextents(dino, XFS_ATTR_FORK,
+ &danextents);
+ ASSERT(err == 0);
+
do_warn(
_("rebuilding inode %"PRIu64" attr fork\n"),
lino);
@@ -2859,6 +2888,9 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
goto clear_bad_out;
}
+ if (xfs_dfork_nextents(dino, XFS_DATA_FORK, (xfs_extnum_t *)&nextents))
+ goto clear_bad_out;
+
/*
* type checks for superblock inodes
*/
diff --git a/repair/prefetch.c b/repair/prefetch.c
index 19eaf16c..247438d1 100644
--- a/repair/prefetch.c
+++ b/repair/prefetch.c
@@ -392,8 +392,11 @@ pf_read_exinode(
prefetch_args_t *args,
xfs_dinode_t *dino)
{
- pf_read_bmbt_reclist(args, (xfs_bmbt_rec_t *)XFS_DFORK_DPTR(dino),
- xfs_dfork_nextents(dino, XFS_DATA_FORK));
+ xfs_extnum_t nextents;
+
+ if (!xfs_dfork_nextents(dino, XFS_DATA_FORK, &nextents))
+ pf_read_bmbt_reclist(args,
+ (xfs_bmbt_rec_t *)XFS_DFORK_DPTR(dino), nextents);
}
static void
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 08/16] xfsprogs: Rename inode's extent counter fields based on their width
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (6 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 07/16] xfsprogs: xfs_dfork_nextents: Return extent count via an out argument Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 09/16] xfsprogs: Promote xfs_extnum_t and xfs_aextnum_t to 64 and 32-bits respectively Chandan Babu R
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
This commit renames extent counter fields in "struct xfs_dinode" and "struct
xfs_log_dinode" based on the width of the fields. As of this commit, the
32-bit field will be used to count data fork extents and the 16-bit field will
be used to count attr fork extents.
This change is done to enable a future commit to introduce a new 64-bit extent
counter field.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
db/inode.c | 4 ++--
libxfs/xfs_format.h | 8 ++++----
libxfs/xfs_inode_buf.c | 4 ++--
libxfs/xfs_log_format.h | 4 ++--
logprint/log_misc.c | 4 ++--
logprint/log_print_all.c | 2 +-
repair/bmap_repair.c | 4 ++--
repair/dinode.c | 6 +++---
8 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/db/inode.c b/db/inode.c
index c45ec1f7..33dfffd0 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -100,8 +100,8 @@ const field_t inode_core_flds[] = {
{ "size", FLDT_FSIZE, OI(COFF(size)), C1, 0, TYP_NONE },
{ "nblocks", FLDT_DRFSBNO, OI(COFF(nblocks)), C1, 0, TYP_NONE },
{ "extsize", FLDT_EXTLEN, OI(COFF(extsize)), C1, 0, TYP_NONE },
- { "nextents", FLDT_EXTNUM, OI(COFF(nextents)), C1, 0, TYP_NONE },
- { "naextents", FLDT_AEXTNUM, OI(COFF(anextents)), C1, 0, TYP_NONE },
+ { "nextents32", FLDT_EXTNUM, OI(COFF(nextents32)), C1, 0, TYP_NONE },
+ { "nextents16", FLDT_AEXTNUM, OI(COFF(nextents16)), C1, 0, TYP_NONE },
{ "forkoff", FLDT_UINT8D, OI(COFF(forkoff)), C1, 0, TYP_NONE },
{ "aformat", FLDT_DINODE_FMT, OI(COFF(aformat)), C1, 0, TYP_NONE },
{ "dmevmask", FLDT_UINT32X, OI(COFF(dmevmask)), C1, 0, TYP_NONE },
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 49e627ad..36c382e7 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -802,8 +802,8 @@ typedef struct xfs_dinode {
__be64 di_size; /* number of bytes in file */
__be64 di_nblocks; /* # of direct & btree blocks used */
__be32 di_extsize; /* basic/minimum extent size for file */
- __be32 di_nextents; /* number of extents in data fork */
- __be16 di_anextents; /* number of extents in attribute fork*/
+ __be32 di_nextents32; /* 32-bit extent counter */
+ __be16 di_nextents16; /* 16-bit extent counter */
__u8 di_forkoff; /* attr fork offs, <<3 for 64b align */
__s8 di_aformat; /* format of attr fork's data */
__be32 di_dmevmask; /* DMIG event mask */
@@ -940,11 +940,11 @@ xfs_dfork_nextents(
switch (whichfork) {
case XFS_DATA_FORK:
- *nextents = be32_to_cpu(dip->di_nextents);
+ *nextents = be32_to_cpu(dip->di_nextents32);
break;
case XFS_ATTR_FORK:
- *nextents = be16_to_cpu(dip->di_anextents);
+ *nextents = be16_to_cpu(dip->di_nextents16);
break;
default:
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 5ed923ae..5909bc26 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -310,8 +310,8 @@ xfs_inode_to_disk(
to->di_size = cpu_to_be64(ip->i_disk_size);
to->di_nblocks = cpu_to_be64(ip->i_nblocks);
to->di_extsize = cpu_to_be32(ip->i_extsize);
- to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
- to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
+ to->di_nextents32 = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
+ to->di_nextents16 = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
to->di_forkoff = ip->i_forkoff;
to->di_aformat = xfs_ifork_format(ip->i_afp);
to->di_flags = cpu_to_be16(ip->i_diflags);
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index bd711d24..9f352ff4 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -402,8 +402,8 @@ struct xfs_log_dinode {
xfs_fsize_t di_size; /* number of bytes in file */
xfs_rfsblock_t di_nblocks; /* # of direct & btree blocks used */
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
- xfs_extnum_t di_nextents; /* number of extents in data fork */
- xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
+ uint32_t di_nextents32; /* number of extents in data fork */
+ uint16_t di_nextents16; /* number of extents in attribute fork*/
uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
int8_t di_aformat; /* format of attr fork's data */
uint32_t di_dmevmask; /* DMIG event mask */
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index c06fd233..4e8760c4 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -452,9 +452,9 @@ xlog_print_trans_inode_core(
xlog_extract_dinode_ts(ip->di_ctime));
printf(_("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n"),
(unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks,
- ip->di_extsize, ip->di_nextents);
+ ip->di_extsize, ip->di_nextents32);
printf(_("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n"),
- ip->di_anextents, (int)ip->di_forkoff, ip->di_dmevmask,
+ ip->di_nextents16, (int)ip->di_forkoff, ip->di_dmevmask,
ip->di_dmstate);
printf(_("flags 0x%x gen 0x%x\n"),
ip->di_flags, ip->di_gen);
diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c
index 37669372..403c5637 100644
--- a/logprint/log_print_all.c
+++ b/logprint/log_print_all.c
@@ -257,7 +257,7 @@ xlog_recover_print_inode_core(
printf(_(" size:0x%llx nblks:0x%llx exsize:%d "
"nextents:%d anextents:%d\n"), (unsigned long long)
di->di_size, (unsigned long long)di->di_nblocks,
- di->di_extsize, di->di_nextents, (int)di->di_anextents);
+ di->di_extsize, di->di_nextents32, (int)di->di_nextents16);
printf(_(" forkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x "
"gen:%u\n"),
(int)di->di_forkoff, di->di_dmevmask, (int)di->di_dmstate,
diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c
index adb798f7..847538b1 100644
--- a/repair/bmap_repair.c
+++ b/repair/bmap_repair.c
@@ -579,7 +579,7 @@ rebuild_bmap(
if (nextents == 0)
return 0;
(*dinop)->di_format = XFS_DINODE_FMT_EXTENTS;
- (*dinop)->di_nextents = 0;
+ (*dinop)->di_nextents32 = 0;
libxfs_dinode_calc_crc(mp, *dinop);
*dirty = 1;
break;
@@ -590,7 +590,7 @@ rebuild_bmap(
if (nextents == 0)
return 0;
(*dinop)->di_aformat = XFS_DINODE_FMT_EXTENTS;
- (*dinop)->di_anextents = 0;
+ (*dinop)->di_nextents16 = 0;
libxfs_dinode_calc_crc(mp, *dinop);
*dirty = 1;
break;
diff --git a/repair/dinode.c b/repair/dinode.c
index 46f82f64..4e95766e 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -78,7 +78,7 @@ _("would have cleared inode %" PRIu64 " attributes\n"), ino_num);
if (anextents != 0) {
if (no_modify)
return(1);
- dino->di_anextents = cpu_to_be16(0);
+ dino->di_nextents16 = cpu_to_be16(0);
}
if (dino->di_aformat != XFS_DINODE_FMT_EXTENTS) {
@@ -1872,7 +1872,7 @@ _("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
do_warn(
_("correcting nextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"),
lino, dnextents, nextents);
- dino->di_nextents = cpu_to_be32(nextents);
+ dino->di_nextents32 = cpu_to_be32(nextents);
*dirty = 1;
} else {
do_warn(
@@ -1896,7 +1896,7 @@ _("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
do_warn(
_("correcting anextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"),
lino, dnextents, anextents);
- dino->di_anextents = cpu_to_be16(anextents);
+ dino->di_nextents16 = cpu_to_be16(anextents);
*dirty = 1;
} else {
do_warn(
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 09/16] xfsprogs: Promote xfs_extnum_t and xfs_aextnum_t to 64 and 32-bits respectively
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (7 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 08/16] xfsprogs: Rename inode's extent counter fields based on their width Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 10/16] xfsprogs: Enable bulkstat ioctl to support 64-bit extent counters Chandan Babu R
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
A future commit will introduce a 64-bit on-disk data extent counter and a
32-bit on-disk attr extent counter. This commit promotes xfs_extnum_t and
xfs_aextnum_t to 64 and 32-bits in order to correctly handle in-core versions
of these quantities.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libxfs/xfs_bmap.c | 4 ++--
libxfs/xfs_inode_fork.c | 2 +-
libxfs/xfs_inode_fork.h | 2 +-
libxfs/xfs_types.h | 4 ++--
repair/dinode.c | 20 ++++++++++----------
repair/dinode.h | 4 ++--
repair/scan.c | 6 +++---
7 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 19db26e6..3c23ea30 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -47,9 +47,9 @@ xfs_bmap_compute_maxlevels(
xfs_mount_t *mp, /* file system mount structure */
int whichfork) /* data or attr fork */
{
+ xfs_extnum_t maxleafents; /* max leaf entries possible */
int level; /* btree level */
uint maxblocks; /* max blocks at this level */
- xfs_extnum_t maxleafents; /* max leaf entries possible */
int maxrootrecs; /* max records in root block */
int minleafrecs; /* min records in leaf block */
int minnoderecs; /* min records in node block */
@@ -466,7 +466,7 @@ error0:
if (bp_release)
xfs_trans_brelse(NULL, bp);
error_norelse:
- xfs_warn(mp, "%s: BAD after btree leaves for %d extents",
+ xfs_warn(mp, "%s: BAD after btree leaves for %llu extents",
__func__, i);
xfs_err(mp, "%s: CORRUPTED BTREE OR SOMETHING", __func__);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index 6b69d34e..9b25f3be 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -124,7 +124,7 @@ xfs_iformat_extents(
* we just bail out rather than crash in kmem_alloc() or memcpy() below.
*/
if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
- xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",
+ xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %llu).",
(unsigned long long) ip->i_ino, nex);
xfs_inode_verifier_error(ip, -EFSCORRUPTED,
"xfs_iformat_extents(1)", dip, sizeof(*dip),
diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h
index e8fe5b47..4b9df10e 100644
--- a/libxfs/xfs_inode_fork.h
+++ b/libxfs/xfs_inode_fork.h
@@ -21,9 +21,9 @@ struct xfs_ifork {
void *if_root; /* extent tree root */
char *if_data; /* inline file data */
} if_u1;
+ xfs_extnum_t if_nextents; /* # of extents in this fork */
short if_broot_bytes; /* bytes allocated for root */
int8_t if_format; /* format of this fork */
- xfs_extnum_t if_nextents; /* # of extents in this fork */
};
/*
diff --git a/libxfs/xfs_types.h b/libxfs/xfs_types.h
index dbe5bb56..a3af29b7 100644
--- a/libxfs/xfs_types.h
+++ b/libxfs/xfs_types.h
@@ -12,8 +12,8 @@ typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */
typedef uint32_t xfs_agino_t; /* inode # within allocation grp */
typedef uint32_t xfs_extlen_t; /* extent length in blocks */
typedef uint32_t xfs_agnumber_t; /* allocation group number */
-typedef int32_t xfs_extnum_t; /* # of extents in a file */
-typedef int16_t xfs_aextnum_t; /* # extents in an attribute fork */
+typedef uint64_t xfs_extnum_t; /* # of extents in a file */
+typedef uint32_t xfs_aextnum_t; /* # extents in an attribute fork */
typedef int64_t xfs_fsize_t; /* bytes in a file */
typedef uint64_t xfs_ufsize_t; /* unsigned bytes in a file */
diff --git a/repair/dinode.c b/repair/dinode.c
index 4e95766e..c995a524 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -357,7 +357,7 @@ static int
process_bmbt_reclist_int(
xfs_mount_t *mp,
xfs_bmbt_rec_t *rp,
- int *numrecs,
+ xfs_extnum_t *numrecs,
int type,
xfs_ino_t ino,
xfs_rfsblock_t *tot,
@@ -680,7 +680,7 @@ int
process_bmbt_reclist(
xfs_mount_t *mp,
xfs_bmbt_rec_t *rp,
- int *numrecs,
+ xfs_extnum_t *numrecs,
int type,
xfs_ino_t ino,
xfs_rfsblock_t *tot,
@@ -703,7 +703,7 @@ int
scan_bmbt_reclist(
xfs_mount_t *mp,
xfs_bmbt_rec_t *rp,
- int *numrecs,
+ xfs_extnum_t *numrecs,
int type,
xfs_ino_t ino,
xfs_rfsblock_t *tot,
@@ -1091,7 +1091,7 @@ _("mismatch between format (%d) and size (%" PRId64 ") in symlink inode %" PRIu6
*/
if (numrecs > max_symlink_blocks) {
do_warn(
-_("bad number of extents (%d) in symlink %" PRIu64 " data fork\n"),
+_("bad number of extents (%lu) in symlink %" PRIu64 " data fork\n"),
numrecs, lino);
return(1);
}
@@ -1652,7 +1652,7 @@ _("realtime summary inode %" PRIu64 " has bad type 0x%x, "),
if (mp->m_sb.sb_rblocks == 0 && nextents != 0) {
do_warn(
-_("bad # of extents (%d) for realtime summary inode %" PRIu64 "\n"),
+_("bad # of extents (%lu) for realtime summary inode %" PRIu64 "\n"),
nextents, lino);
return 1;
}
@@ -1677,7 +1677,7 @@ _("realtime bitmap inode %" PRIu64 " has bad type 0x%x, "),
if (mp->m_sb.sb_rblocks == 0 && nextents != 0) {
do_warn(
-_("bad # of extents (%d) for realtime bitmap inode %" PRIu64 "\n"),
+_("bad # of extents (%lu) for realtime bitmap inode %" PRIu64 "\n"),
nextents, lino);
return 1;
}
@@ -1870,13 +1870,13 @@ _("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
if (nextents != dnextents) {
if (!no_modify) {
do_warn(
-_("correcting nextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"),
+_("correcting nextents for inode %" PRIu64 ", was %lu - counted %" PRIu64 "\n"),
lino, dnextents, nextents);
dino->di_nextents32 = cpu_to_be32(nextents);
*dirty = 1;
} else {
do_warn(
-_("bad nextents %d for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
+_("bad nextents %lu for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
dnextents, lino, nextents);
}
}
@@ -1894,13 +1894,13 @@ _("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
if (anextents != dnextents) {
if (!no_modify) {
do_warn(
-_("correcting anextents for inode %" PRIu64 ", was %d - counted %" PRIu64 "\n"),
+_("correcting anextents for inode %" PRIu64 ", was %lu - counted %" PRIu64 "\n"),
lino, dnextents, anextents);
dino->di_nextents16 = cpu_to_be16(anextents);
*dirty = 1;
} else {
do_warn(
-_("bad anextents %d for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
+_("bad anextents %lu for inode %" PRIu64 ", would reset to %" PRIu64 "\n"),
dnextents, lino, anextents);
}
}
diff --git a/repair/dinode.h b/repair/dinode.h
index e190b743..09129e7b 100644
--- a/repair/dinode.h
+++ b/repair/dinode.h
@@ -20,7 +20,7 @@ convert_extent(
int
process_bmbt_reclist(xfs_mount_t *mp,
xfs_bmbt_rec_t *rp,
- int *numrecs,
+ xfs_extnum_t *numrecs,
int type,
xfs_ino_t ino,
xfs_rfsblock_t *tot,
@@ -34,7 +34,7 @@ int
scan_bmbt_reclist(
xfs_mount_t *mp,
xfs_bmbt_rec_t *rp,
- int *numrecs,
+ xfs_extnum_t *numrecs,
int type,
xfs_ino_t ino,
xfs_rfsblock_t *tot,
diff --git a/repair/scan.c b/repair/scan.c
index 698befd3..bcf523da 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -223,7 +223,7 @@ scan_bmapbt(
xfs_fileoff_t first_key;
xfs_fileoff_t last_key;
char *forkname = get_forkname(whichfork);
- int numrecs;
+ xfs_extnum_t numrecs;
xfs_agnumber_t agno;
xfs_agblock_t agbno;
int state;
@@ -443,7 +443,7 @@ _("couldn't add inode %"PRIu64" bmbt block %"PRIu64" reverse-mapping data."),
if (numrecs > mp->m_bmap_dmxr[0] || (isroot == 0 && numrecs <
mp->m_bmap_dmnr[0])) {
do_warn(
-_("inode %" PRIu64 " bad # of bmap records (%u, min - %u, max - %u)\n"),
+_("inode %" PRIu64 " bad # of bmap records (%lu, min - %u, max - %u)\n"),
ino, numrecs, mp->m_bmap_dmnr[0],
mp->m_bmap_dmxr[0]);
return(1);
@@ -495,7 +495,7 @@ _("out-of-order bmap key (file offset) in inode %" PRIu64 ", %s fork, fsbno %" P
if (numrecs > mp->m_bmap_dmxr[1] || (isroot == 0 && numrecs <
mp->m_bmap_dmnr[1])) {
do_warn(
-_("inode %" PRIu64 " bad # of bmap records (%u, min - %u, max - %u)\n"),
+_("inode %" PRIu64 " bad # of bmap records (%lu, min - %u, max - %u)\n"),
ino, numrecs, mp->m_bmap_dmnr[1], mp->m_bmap_dmxr[1]);
return(1);
}
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 10/16] xfsprogs: Enable bulkstat ioctl to support 64-bit extent counters
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (8 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 09/16] xfsprogs: Promote xfs_extnum_t and xfs_aextnum_t to 64 and 32-bits respectively Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 11/16] xfsprogs: Extend per-inode extent counter widths Chandan Babu R
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
This commit adds support to libfrog to enable reporting 64-bit extent counters
to its users. In order to do so bulkstat ioctl is now invoked with the newly
introduced XFS_BULK_IREQ_BULKSTAT_NREXT64 flag. If the ioctl call fails with
-EINVAL error, the commit falls back to invoking the bulkstat ioctl without
passing XFS_BULK_IREQ_BULKSTAT_NREXT64 flag.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
fsr/xfs_fsr.c | 4 ++--
io/bulkstat.c | 3 ++-
libfrog/bulkstat.c | 55 ++++++++++++++++++++++++++++++++++++++++++----
libxfs/xfs_fs.h | 19 +++++++++++-----
4 files changed, 69 insertions(+), 12 deletions(-)
diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index bb5d4a2c..1fb2e5e7 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -606,7 +606,7 @@ cmp(const void *s1, const void *s2)
(bs1->bs_version == XFS_BULKSTAT_VERSION_V5 &&
bs2->bs_version == XFS_BULKSTAT_VERSION_V5));
- return (bs2->bs_extents - bs1->bs_extents);
+ return (bs2->bs_extents64 - bs1->bs_extents64);
}
/*
@@ -670,7 +670,7 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
for (p = buf, endp = (buf + buflenout); p < endp ; p++) {
/* Do some obvious checks now */
if (((p->bs_mode & S_IFMT) != S_IFREG) ||
- (p->bs_extents < 2))
+ (p->bs_extents64 < 2))
continue;
ret = open_handle(&file_fd, fshandlep, p,
diff --git a/io/bulkstat.c b/io/bulkstat.c
index 4ae27586..8a9cf902 100644
--- a/io/bulkstat.c
+++ b/io/bulkstat.c
@@ -49,7 +49,7 @@ dump_bulkstat(
printf("\tbs_extsize_blks = %"PRIu32"\n", bstat->bs_extsize_blks);
printf("\tbs_nlink = %"PRIu32"\n", bstat->bs_nlink);
- printf("\tbs_extents = %"PRIu32"\n", bstat->bs_extents);
+ printf("\tbs_extents32 = %"PRIu32"\n", bstat->bs_extents32);
printf("\tbs_aextents = %"PRIu32"\n", bstat->bs_aextents);
printf("\tbs_version = %"PRIu16"\n", bstat->bs_version);
printf("\tbs_forkoff = %"PRIu16"\n", bstat->bs_forkoff);
@@ -57,6 +57,7 @@ dump_bulkstat(
printf("\tbs_sick = 0x%"PRIx16"\n", bstat->bs_sick);
printf("\tbs_checked = 0x%"PRIx16"\n", bstat->bs_checked);
printf("\tbs_mode = 0%"PRIo16"\n", bstat->bs_mode);
+ printf("\tbs_extents64 = %"PRIu64"\n", bstat->bs_extents64);
};
static void
diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
index 195f6ea0..9de614d3 100644
--- a/libfrog/bulkstat.c
+++ b/libfrog/bulkstat.c
@@ -48,12 +48,13 @@ xfrog_bulkstat_single5(
struct xfs_fd *xfd,
uint64_t ino,
unsigned int flags,
+ uint64_t bulkstat_flags,
struct xfs_bulkstat *bulkstat)
{
struct xfs_bulkstat_req *req;
int ret;
- if (flags & ~(XFS_BULK_IREQ_SPECIAL))
+ if (flags & ~(XFS_BULK_IREQ_SPECIAL | XFS_BULK_IREQ_BULKSTAT))
return -EINVAL;
ret = xfrog_bulkstat_alloc_req(1, ino, &req);
@@ -61,6 +62,7 @@ xfrog_bulkstat_single5(
return ret;
req->hdr.flags = flags;
+ req->hdr.bulkstat_flags = bulkstat_flags;
ret = ioctl(xfd->fd, XFS_IOC_BULKSTAT, req);
if (ret) {
ret = -errno;
@@ -73,6 +75,13 @@ xfrog_bulkstat_single5(
}
memcpy(bulkstat, req->bulkstat, sizeof(struct xfs_bulkstat));
+
+ if (!(flags & XFS_BULK_IREQ_BULKSTAT) ||
+ !(bulkstat_flags & XFS_BULK_IREQ_BULKSTAT_NREXT64)) {
+ bulkstat->bs_extents64 = bulkstat->bs_extents32;
+ bulkstat->bs_extents32 = 0;
+ }
+
free:
free(req);
return ret;
@@ -121,7 +130,18 @@ xfrog_bulkstat_single(
if (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V1)
goto try_v1;
- error = xfrog_bulkstat_single5(xfd, ino, flags, bulkstat);
+ error = xfrog_bulkstat_single5(xfd, ino, flags | XFS_BULK_IREQ_BULKSTAT,
+ XFS_BULK_IREQ_BULKSTAT_NREXT64, bulkstat);
+ if (error == -EINVAL) {
+ /*
+ * Older versions of XFS kernel driver return -EINVAL because
+ * they don't recognize XFS_BULK_IREQ_BULKSTAT as a valid
+ * flag. Try once again without passing XFS_BULK_IREQ_BULKSTAT
+ * flag.
+ */
+ error = xfrog_bulkstat_single5(xfd, ino, flags, 0, bulkstat);
+ }
+
if (error == 0 || (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V5))
return error;
@@ -259,10 +279,21 @@ xfrog_bulkstat5(
struct xfs_bulkstat_req *req)
{
int ret;
+ int i;
ret = ioctl(xfd->fd, XFS_IOC_BULKSTAT, req);
if (ret)
return -errno;
+
+ if (!(req->hdr.flags & XFS_BULK_IREQ_BULKSTAT) ||
+ !(req->hdr.bulkstat_flags & XFS_BULK_IREQ_BULKSTAT_NREXT64)) {
+ for (i = 0; i < req->hdr.ocount; i++) {
+ req->bulkstat[i].bs_extents64 =
+ req->bulkstat[i].bs_extents32;
+ req->bulkstat[i].bs_extents32 = 0;
+ }
+ }
+
return 0;
}
@@ -308,7 +339,22 @@ xfrog_bulkstat(
if (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V1)
goto try_v1;
+ req->hdr.flags |= XFS_BULK_IREQ_BULKSTAT;
+ req->hdr.bulkstat_flags |= XFS_BULK_IREQ_BULKSTAT_NREXT64;
+
error = xfrog_bulkstat5(xfd, req);
+ if (error == -EINVAL) {
+ /*
+ * Older versions of XFS kernel driver return -EINVAL because
+ * they don't recognize XFS_BULK_IREQ_BULKSTAT as a valid
+ * flag. Try once again without passing XFS_BULK_IREQ_BULKSTAT
+ * flag.
+ */
+ req->hdr.flags &= ~XFS_BULK_IREQ_BULKSTAT;
+ req->hdr.bulkstat_flags &= ~XFS_BULK_IREQ_BULKSTAT_NREXT64;
+ error = xfrog_bulkstat5(xfd, req);
+ }
+
if (error == 0 || (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V5))
return error;
@@ -342,6 +388,7 @@ xfrog_bulkstat_v5_to_v1(
const struct xfs_bulkstat *bs5)
{
if (bs5->bs_aextents > UINT16_MAX ||
+ bs5->bs_extents64 > INT32_MAX ||
cvt_off_fsb_to_b(xfd, bs5->bs_extsize_blks) > UINT32_MAX ||
cvt_off_fsb_to_b(xfd, bs5->bs_cowextsize_blks) > UINT32_MAX ||
time_too_big(bs5->bs_atime) ||
@@ -366,7 +413,7 @@ xfrog_bulkstat_v5_to_v1(
bs1->bs_blocks = bs5->bs_blocks;
bs1->bs_xflags = bs5->bs_xflags;
bs1->bs_extsize = cvt_off_fsb_to_b(xfd, bs5->bs_extsize_blks);
- bs1->bs_extents = bs5->bs_extents;
+ bs1->bs_extents = bs5->bs_extents64;
bs1->bs_gen = bs5->bs_gen;
bs1->bs_projid_lo = bs5->bs_projectid & 0xFFFF;
bs1->bs_forkoff = bs5->bs_forkoff;
@@ -407,7 +454,6 @@ xfrog_bulkstat_v1_to_v5(
bs5->bs_blocks = bs1->bs_blocks;
bs5->bs_xflags = bs1->bs_xflags;
bs5->bs_extsize_blks = cvt_b_to_off_fsbt(xfd, bs1->bs_extsize);
- bs5->bs_extents = bs1->bs_extents;
bs5->bs_gen = bs1->bs_gen;
bs5->bs_projectid = bstat_get_projid(bs1);
bs5->bs_forkoff = bs1->bs_forkoff;
@@ -415,6 +461,7 @@ xfrog_bulkstat_v1_to_v5(
bs5->bs_checked = bs1->bs_checked;
bs5->bs_cowextsize_blks = cvt_b_to_off_fsbt(xfd, bs1->bs_cowextsize);
bs5->bs_aextents = bs1->bs_aextents;
+ bs5->bs_extents64 = bs1->bs_extents;
}
/* Allocate a bulkstat request. Returns zero or a negative error code. */
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 2594fb64..b7690691 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -394,7 +394,7 @@ struct xfs_bulkstat {
uint32_t bs_extsize_blks; /* extent size hint, blocks */
uint32_t bs_nlink; /* number of links */
- uint32_t bs_extents; /* number of extents */
+ uint32_t bs_extents32; /* 32-bit data fork extent counter */
uint32_t bs_aextents; /* attribute number of extents */
uint16_t bs_version; /* structure version */
uint16_t bs_forkoff; /* inode fork offset in bytes */
@@ -403,8 +403,9 @@ struct xfs_bulkstat {
uint16_t bs_checked; /* checked inode metadata */
uint16_t bs_mode; /* type and mode */
uint16_t bs_pad2; /* zeroed */
+ uint64_t bs_extents64; /* 64-bit data fork extent counter */
- uint64_t bs_pad[7]; /* zeroed */
+ uint64_t bs_pad[6]; /* zeroed */
};
#define XFS_BULKSTAT_VERSION_V1 (1)
@@ -469,7 +470,8 @@ struct xfs_bulk_ireq {
uint32_t icount; /* I: count of entries in buffer */
uint32_t ocount; /* O: count of entries filled out */
uint32_t agno; /* I: see comment for IREQ_AGNO */
- uint64_t reserved[5]; /* must be zero */
+ uint64_t bulkstat_flags; /* I: Bulkstat operation flags */
+ uint64_t reserved[4]; /* must be zero */
};
/*
@@ -492,9 +494,16 @@ struct xfs_bulk_ireq {
*/
#define XFS_BULK_IREQ_METADIR (1 << 2)
-#define XFS_BULK_IREQ_FLAGS_ALL (XFS_BULK_IREQ_AGNO | \
+#define XFS_BULK_IREQ_BULKSTAT (1 << 3)
+
+#define XFS_BULK_IREQ_FLAGS_ALL (XFS_BULK_IREQ_AGNO | \
XFS_BULK_IREQ_SPECIAL | \
- XFS_BULK_IREQ_METADIR)
+ XFS_BULK_IREQ_METADIR | \
+ XFS_BULK_IREQ_BULKSTAT)
+
+#define XFS_BULK_IREQ_BULKSTAT_NREXT64 (1 << 0)
+
+#define XFS_BULK_IREQ_BULKSTAT_FLAGS_ALL (XFS_BULK_IREQ_BULKSTAT_NREXT64)
/* Operate on the root directory inode. */
#define XFS_BULK_IREQ_SPECIAL_ROOT (1)
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 11/16] xfsprogs: Extend per-inode extent counter widths
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (9 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 10/16] xfsprogs: Enable bulkstat ioctl to support 64-bit extent counters Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 12/16] xfsprogs: xfs_info: Report NREXT64 feature status Chandan Babu R
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
This commit adds a new 64-bit per-inode data extent counter. However the
maximum number of extents that a data fork can hold is limited to 2^48
extents. This feature is available only when
XFS_SB_FEAT_INCOMPAT_EXTCOUNT_64BIT feature bit is enabled on the
filesystem. Also, enabling this feature bit causes attr fork extent counter to
use the 32-bit extent counter that was previously used to hold the data fork
extent counter. This implies that the attr fork can now occupy a maximum of
2^32 extents.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
db/field.c | 4 --
db/field.h | 2 -
db/inode.c | 44 +++++++++++++++++--
include/libxlog.h | 6 ++-
include/xfs_inode.h | 5 +++
include/xfs_mount.h | 4 +-
libxfs/xfs_bmap.c | 8 ++--
libxfs/xfs_format.h | 87 ++++++++++++++++++++++++++------------
libxfs/xfs_fs.h | 1 +
libxfs/xfs_ialloc.c | 2 +
libxfs/xfs_inode_buf.c | 25 ++++++++++-
libxfs/xfs_inode_fork.h | 18 ++++++--
libxfs/xfs_log_format.h | 3 +-
libxfs/xfs_sb.c | 3 ++
libxfs/xfs_trans_inode.c | 5 +++
logprint/log_misc.c | 23 +++++++---
logprint/log_print_all.c | 31 +++++++++++---
logprint/log_print_trans.c | 2 +-
repair/bmap_repair.c | 10 ++++-
repair/dinode.c | 15 +++++--
20 files changed, 229 insertions(+), 69 deletions(-)
diff --git a/db/field.c b/db/field.c
index 51268938..1e274ffc 100644
--- a/db/field.c
+++ b/db/field.c
@@ -25,8 +25,6 @@
#include "symlink.h"
const ftattr_t ftattrtab[] = {
- { FLDT_AEXTNUM, "aextnum", fp_num, "%d", SI(bitsz(xfs_aextnum_t)),
- FTARG_SIGNED, NULL, NULL },
{ FLDT_AGBLOCK, "agblock", fp_num, "%u", SI(bitsz(xfs_agblock_t)),
FTARG_DONULL, fa_agblock, NULL },
{ FLDT_AGBLOCKNZ, "agblocknz", fp_num, "%u", SI(bitsz(xfs_agblock_t)),
@@ -300,8 +298,6 @@ const ftattr_t ftattrtab[] = {
FTARG_DONULL, fa_drtbno, NULL },
{ FLDT_EXTLEN, "extlen", fp_num, "%u", SI(bitsz(xfs_extlen_t)), 0, NULL,
NULL },
- { FLDT_EXTNUM, "extnum", fp_num, "%d", SI(bitsz(xfs_extnum_t)),
- FTARG_SIGNED, NULL, NULL },
{ FLDT_FSIZE, "fsize", fp_num, "%lld", SI(bitsz(xfs_fsize_t)),
FTARG_SIGNED, NULL, NULL },
{ FLDT_INO, "ino", fp_num, "%llu", SI(bitsz(xfs_ino_t)), FTARG_DONULL,
diff --git a/db/field.h b/db/field.h
index 387c189e..614fd0ab 100644
--- a/db/field.h
+++ b/db/field.h
@@ -5,7 +5,6 @@
*/
typedef enum fldt {
- FLDT_AEXTNUM,
FLDT_AGBLOCK,
FLDT_AGBLOCKNZ,
FLDT_AGF,
@@ -143,7 +142,6 @@ typedef enum fldt {
FLDT_DRFSBNO,
FLDT_DRTBNO,
FLDT_EXTLEN,
- FLDT_EXTNUM,
FLDT_FSIZE,
FLDT_INO,
FLDT_INOBT,
diff --git a/db/inode.c b/db/inode.c
index 33dfffd0..ab825fc3 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -37,6 +37,8 @@ static int inode_u_muuid_count(void *obj, int startoff);
static int inode_u_sfdir2_count(void *obj, int startoff);
static int inode_u_sfdir3_count(void *obj, int startoff);
static int inode_u_symlink_count(void *obj, int startoff);
+static int inode_v3_64bitext_count(void *obj, int startoff);
+static int inode_v3_pad2_count(void *obj, int startoff);
static const cmdinfo_t inode_cmd =
{ "inode", NULL, inode_f, 0, 1, 1, "[inode#]",
@@ -100,8 +102,8 @@ const field_t inode_core_flds[] = {
{ "size", FLDT_FSIZE, OI(COFF(size)), C1, 0, TYP_NONE },
{ "nblocks", FLDT_DRFSBNO, OI(COFF(nblocks)), C1, 0, TYP_NONE },
{ "extsize", FLDT_EXTLEN, OI(COFF(extsize)), C1, 0, TYP_NONE },
- { "nextents32", FLDT_EXTNUM, OI(COFF(nextents32)), C1, 0, TYP_NONE },
- { "nextents16", FLDT_AEXTNUM, OI(COFF(nextents16)), C1, 0, TYP_NONE },
+ { "nextents32", FLDT_UINT32D, OI(COFF(nextents32)), C1, 0, TYP_NONE },
+ { "nextents16", FLDT_UINT16D, OI(COFF(nextents16)), C1, 0, TYP_NONE },
{ "forkoff", FLDT_UINT8D, OI(COFF(forkoff)), C1, 0, TYP_NONE },
{ "aformat", FLDT_DINODE_FMT, OI(COFF(aformat)), C1, 0, TYP_NONE },
{ "dmevmask", FLDT_UINT32X, OI(COFF(dmevmask)), C1, 0, TYP_NONE },
@@ -162,7 +164,10 @@ const field_t inode_v3_flds[] = {
{ "lsn", FLDT_UINT64X, OI(COFF(lsn)), C1, 0, TYP_NONE },
{ "flags2", FLDT_UINT64X, OI(COFF(flags2)), C1, 0, TYP_NONE },
{ "cowextsize", FLDT_EXTLEN, OI(COFF(cowextsize)), C1, 0, TYP_NONE },
- { "pad2", FLDT_UINT8X, OI(OFF(pad2)), CI(12), FLD_ARRAY|FLD_SKIPALL, TYP_NONE },
+ { "nextents64", FLDT_UINT64D, OI(COFF(nextents64)),
+ inode_v3_64bitext_count, FLD_COUNT, TYP_NONE },
+ { "pad2", FLDT_UINT8X, OI(OFF(pad2)), inode_v3_pad2_count,
+ FLD_ARRAY|FLD_COUNT|FLD_SKIPALL, TYP_NONE },
{ "crtime", FLDT_TIMESTAMP, OI(COFF(crtime)), C1, 0, TYP_NONE },
{ "inumber", FLDT_INO, OI(COFF(ino)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(COFF(uuid)), C1, 0, TYP_NONE },
@@ -181,6 +186,9 @@ const field_t inode_v3_flds[] = {
{ "metadata", FLDT_UINT1,
OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_METADATA_BIT-1), C1,
0, TYP_NONE },
+ { "nrext64", FLDT_UINT1,
+ OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_NREXT64_BIT-1), C1,
+ 0, TYP_NONE },
{ NULL }
};
@@ -409,6 +417,36 @@ inode_core_projid_count(
return dic->di_version >= 2;
}
+static int
+inode_v3_64bitext_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+ return !!(be64_to_cpu(dic->di_flags2) & XFS_DIFLAG2_NREXT64);
+}
+
+static int
+inode_v3_pad2_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (be64_to_cpu(dic->di_flags2) & XFS_DIFLAG2_NREXT64)
+ return 4;
+ else
+ return 12;
+}
+
static int
inode_f(
int argc,
diff --git a/include/libxlog.h b/include/libxlog.h
index adaa9963..fe30481c 100644
--- a/include/libxlog.h
+++ b/include/libxlog.h
@@ -89,13 +89,15 @@ extern int xlog_find_tail(struct xlog *log, xfs_daddr_t *head_blk,
extern int xlog_recover(struct xlog *log, int readonly);
extern void xlog_recover_print_data(char *p, int len);
-extern void xlog_recover_print_logitem(struct xlog_recover_item *item);
+extern void xlog_recover_print_logitem(struct xlog *log,
+ struct xlog_recover_item *item);
extern void xlog_recover_print_trans_head(struct xlog_recover *tr);
extern int xlog_print_find_oldest(struct xlog *log, xfs_daddr_t *last_blk);
/* for transactional view */
extern void xlog_recover_print_trans_head(struct xlog_recover *tr);
-extern void xlog_recover_print_trans(struct xlog_recover *trans,
+extern void xlog_recover_print_trans(struct xlog *log,
+ struct xlog_recover *trans,
struct list_head *itemq, int print);
extern int xlog_do_recovery_pass(struct xlog *log, xfs_daddr_t head_blk,
xfs_daddr_t tail_blk, int pass);
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
index bf8e68e1..450ea8ff 100644
--- a/include/xfs_inode.h
+++ b/include/xfs_inode.h
@@ -211,6 +211,11 @@ static inline bool xfs_inode_has_bigrtextents(struct xfs_inode *ip)
return XFS_IS_REALTIME_INODE(ip) && ip->i_mount->m_sb.sb_rextsize > 1;
}
+static inline bool xfs_inode_has_nrext64(struct xfs_inode *ip)
+{
+ return ip->i_diflags2 & XFS_DIFLAG2_NREXT64;
+}
+
static inline bool xfs_is_always_cow_inode(struct xfs_inode *ip)
{
return false;
diff --git a/include/xfs_mount.h b/include/xfs_mount.h
index 2ee93e37..c8385d16 100644
--- a/include/xfs_mount.h
+++ b/include/xfs_mount.h
@@ -153,8 +153,9 @@ typedef struct xfs_mount {
#define XFS_FEAT_NEEDSREPAIR (1ULL << 25) /* needs xfs_repair */
#define XFS_FEAT_ATOMIC_SWAP (1ULL << 26) /* extent swap log items */
#define XFS_FEAT_METADIR (1ULL << 27) /* metadata directory tree */
+#define XFS_FEAT_NREXT64 (1ULL << 28) /* 64-bit inode extent counters */
-#define __XFS_HAS_FEAT(name, NAME) \
+#define __XFS_HAS_FEAT(name, NAME) \
static inline bool xfs_has_ ## name (struct xfs_mount *mp) \
{ \
return mp->m_features & XFS_FEAT_ ## NAME; \
@@ -198,6 +199,7 @@ __XFS_HAS_FEAT(bigtime, BIGTIME)
__XFS_HAS_FEAT(needsrepair, NEEDSREPAIR)
__XFS_HAS_FEAT(atomicswap, ATOMIC_SWAP)
__XFS_HAS_FEAT(metadir, METADIR)
+__XFS_HAS_FEAT(nrext64, NREXT64)
/*
* Decide if this filesystem can use log-assisted ("atomic") extent swapping.
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 3c23ea30..8a1b94bb 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -48,18 +48,16 @@ xfs_bmap_compute_maxlevels(
int whichfork) /* data or attr fork */
{
xfs_extnum_t maxleafents; /* max leaf entries possible */
+ xfs_rfsblock_t maxblocks; /* max blocks at this level */
int level; /* btree level */
- uint maxblocks; /* max blocks at this level */
int maxrootrecs; /* max records in root block */
int minleafrecs; /* min records in leaf block */
int minnoderecs; /* min records in node block */
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
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 36c382e7..9971300a 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -388,6 +388,7 @@ xfs_sb_has_ro_compat_feature(
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */
#define XFS_SB_FEAT_INCOMPAT_METADIR (1 << 5) /* metadata dir tree */
+#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 6) /* 64-bit data fork extent counter */
#define XFS_SB_FEAT_INCOMPAT_ALL \
(XFS_SB_FEAT_INCOMPAT_FTYPE| \
XFS_SB_FEAT_INCOMPAT_SPINODES| \
@@ -802,6 +803,15 @@ typedef struct xfs_dinode {
__be64 di_size; /* number of bytes in file */
__be64 di_nblocks; /* # of direct & btree blocks used */
__be32 di_extsize; /* basic/minimum extent size for file */
+ /*
+ * On a extcnt64bit filesystem, di_nextents64 holds the data fork
+ * extent count, di_nextents32 holds the attr fork extent count,
+ * and di_nextents16 must be zero.
+ *
+ * Otherwise, di_nextents32 holds the data fork extent count,
+ * di_nextents16 holds the attr fork extent count, and di_nextents64
+ * must be zero.
+ */
__be32 di_nextents32; /* 32-bit extent counter */
__be16 di_nextents16; /* 16-bit extent counter */
__u8 di_forkoff; /* attr fork offs, <<3 for 64b align */
@@ -820,7 +830,8 @@ typedef struct xfs_dinode {
__be64 di_lsn; /* flush sequence */
__be64 di_flags2; /* more random flags */
__be32 di_cowextsize; /* basic cow extent size for file */
- __u8 di_pad2[12]; /* more padding for future expansion */
+ __u8 di_pad2[4]; /* more padding for future expansion */
+ __be64 di_nextents64; /* 64-bit extent counter */
/* fields only written to during inode creation */
xfs_timestamp_t di_crtime; /* time created */
@@ -875,10 +886,14 @@ enum xfs_dinode_fmt {
/*
* Max values for extlen, disk inode's extent counters.
*/
+
#define MAXEXTLEN ((xfs_extlen_t)0x1fffff) /* 21 bits */
+#define XFS_IFORK_EXTCNT_MAXU48 ((xfs_extnum_t)0xffffffffffff) /* Unsigned 48-bits */
+#define XFS_IFORK_EXTCNT_MAXU32 ((xfs_aextnum_t)0xffffffff) /* Unsigned 32-bits */
#define XFS_IFORK_EXTCNT_MAXS32 ((xfs_extnum_t)0x7fffffff) /* Signed 32-bits */
#define XFS_IFORK_EXTCNT_MAXS16 ((xfs_aextnum_t)0x7fff) /* Signed 16-bits */
+
/*
* Inode minimum and maximum sizes.
*/
@@ -930,32 +945,6 @@ enum xfs_dinode_fmt {
(dip)->di_format : \
(dip)->di_aformat)
-static inline int
-xfs_dfork_nextents(
- struct xfs_dinode *dip,
- int whichfork,
- xfs_extnum_t *nextents)
-{
- int error = 0;
-
- switch (whichfork) {
- case XFS_DATA_FORK:
- *nextents = be32_to_cpu(dip->di_nextents32);
- break;
-
- case XFS_ATTR_FORK:
- *nextents = be16_to_cpu(dip->di_nextents16);
- break;
-
- default:
- ASSERT(0);
- error = -EFSCORRUPTED;
- break;
- }
-
- return error;
-}
-
/*
* For block and character special files the 32bit dev_t is stored at the
* beginning of the data fork.
@@ -1022,6 +1011,7 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */
#define XFS_DIFLAG2_BIGTIME_BIT 3 /* big timestamps */
#define XFS_DIFLAG2_METADATA_BIT 4 /* filesystem metadata */
+#define XFS_DIFLAG2_NREXT64_BIT 5 /* 64-bit extent counter enabled */
#define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT)
#define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT)
@@ -1052,10 +1042,11 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
* - Metadata directory entries must have correct ftype.
*/
#define XFS_DIFLAG2_METADATA (1 << XFS_DIFLAG2_METADATA_BIT)
+#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT)
#define XFS_DIFLAG2_ANY \
(XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \
- XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_METADATA)
+ XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_METADATA | XFS_DIFLAG2_NREXT64)
static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
{
@@ -1063,6 +1054,46 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_BIGTIME));
}
+static inline bool xfs_dinode_has_nrext64(const struct xfs_dinode *dip)
+{
+ return dip->di_version >= 3 &&
+ (dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_NREXT64));
+}
+
+static inline int
+xfs_dfork_nextents(
+ struct xfs_dinode *dip,
+ int whichfork,
+ xfs_extnum_t *nextents)
+{
+ int error = 0;
+ bool inode_has_nrext64;
+
+ inode_has_nrext64 = xfs_dinode_has_nrext64(dip);
+
+ if (inode_has_nrext64 && dip->di_nextents16 != 0)
+ return -EFSCORRUPTED;
+
+ switch (whichfork) {
+ case XFS_DATA_FORK:
+ *nextents = inode_has_nrext64 ? be64_to_cpu(dip->di_nextents64) :
+ be32_to_cpu(dip->di_nextents32);
+ break;
+
+ case XFS_ATTR_FORK:
+ *nextents = inode_has_nrext64 ? be32_to_cpu(dip->di_nextents32) :
+ be16_to_cpu(dip->di_nextents16);
+ break;
+
+ default:
+ ASSERT(0);
+ error = -EFSCORRUPTED;
+ break;
+ }
+
+ return error;
+}
+
/*
* Inode number format:
* low inopblog bits - offset in block
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index b7690691..3d0b679d 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -254,6 +254,7 @@ typedef struct xfs_fsop_resblks {
#define XFS_FSOP_GEOM_FLAGS_INOBTCNT (1 << 22) /* inobt btree counter */
#define XFS_FSOP_GEOM_FLAGS_ATOMIC_SWAP (1 << 23) /* atomic swapext */
#define XFS_FSOP_GEOM_FLAGS_METADIR (1 << 24) /* metadata directories */
+#define XFS_FSOP_GEOM_FLAGS_NREXT64 (1 << 25) /* 64-bit extent counter */
/*
* Minimum and maximum sizes need for growth checks.
diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
index 67dd9060..7fac2c34 100644
--- a/libxfs/xfs_ialloc.c
+++ b/libxfs/xfs_ialloc.c
@@ -2831,6 +2831,8 @@ xfs_ialloc_setup_geometry(
igeo->new_diflags2 = 0;
if (xfs_has_bigtime(mp))
igeo->new_diflags2 |= XFS_DIFLAG2_BIGTIME;
+ if (xfs_has_nrext64(mp))
+ igeo->new_diflags2 |= XFS_DIFLAG2_NREXT64;
/* Compute inode btree geometry. */
igeo->agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 5909bc26..15690f7f 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -282,6 +282,27 @@ xfs_inode_to_disk_ts(
return ts;
}
+static inline void
+xfs_inode_to_disk_iext_counters(
+ struct xfs_inode *ip,
+ struct xfs_dinode *to)
+{
+ if (xfs_inode_has_nrext64(ip)) {
+ to->di_nextents64 = cpu_to_be64(xfs_ifork_nextents(&ip->i_df));
+ to->di_nextents32 = cpu_to_be32(xfs_ifork_nextents(ip->i_afp));
+ /*
+ * We might be upgrading the inode to use wider extent counters
+ * than was previously used. Hence zero the unused field.
+ */
+ to->di_nextents16 = cpu_to_be16(0);
+ } else {
+ if (xfs_has_v3inodes(ip->i_mount))
+ to->di_nextents64 = 0;
+ to->di_nextents32 = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
+ to->di_nextents16 = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
+ }
+}
+
void
xfs_inode_to_disk(
struct xfs_inode *ip,
@@ -310,8 +331,6 @@ xfs_inode_to_disk(
to->di_size = cpu_to_be64(ip->i_disk_size);
to->di_nblocks = cpu_to_be64(ip->i_nblocks);
to->di_extsize = cpu_to_be32(ip->i_extsize);
- to->di_nextents32 = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
- to->di_nextents16 = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
to->di_forkoff = ip->i_forkoff;
to->di_aformat = xfs_ifork_format(ip->i_afp);
to->di_flags = cpu_to_be16(ip->i_diflags);
@@ -331,6 +350,8 @@ xfs_inode_to_disk(
to->di_version = 2;
to->di_flushiter = cpu_to_be16(ip->i_flushiter);
}
+
+ xfs_inode_to_disk_iext_counters(ip, to);
}
static xfs_failaddr_t
diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h
index 4b9df10e..f8a85ba6 100644
--- a/libxfs/xfs_inode_fork.h
+++ b/libxfs/xfs_inode_fork.h
@@ -136,10 +136,22 @@ static inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
static inline xfs_extnum_t xfs_iext_max_nextents(struct xfs_mount *mp,
int whichfork)
{
- if (whichfork == XFS_DATA_FORK || whichfork == XFS_COW_FORK)
- return XFS_IFORK_EXTCNT_MAXS32;
+ bool has_64bit_extcnt = xfs_has_nrext64(mp);
- return XFS_IFORK_EXTCNT_MAXS16;
+ switch (whichfork) {
+ case XFS_DATA_FORK:
+ case XFS_COW_FORK:
+ return has_64bit_extcnt ? XFS_IFORK_EXTCNT_MAXU48
+ : XFS_IFORK_EXTCNT_MAXS32;
+
+ case XFS_ATTR_FORK:
+ return has_64bit_extcnt ? XFS_IFORK_EXTCNT_MAXU32
+ : XFS_IFORK_EXTCNT_MAXS16;
+
+ default:
+ ASSERT(0);
+ return 0;
+ }
}
struct xfs_ifork *xfs_ifork_alloc(enum xfs_dinode_fmt format,
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index 9f352ff4..de4bcb94 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -429,7 +429,8 @@ struct xfs_log_dinode {
uint64_t di_flags2; /* more random flags */
uint32_t di_cowextsize; /* basic cow extent size for file */
- uint8_t di_pad2[12]; /* more padding for future expansion */
+ uint8_t di_pad2[4]; /* more padding for future expansion */
+ uint64_t di_nextents64; /* higher part of data fork extent count */
/* fields only written to during inode creation */
xfs_log_timestamp_t di_crtime; /* time created */
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index ae336f0a..2489f619 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -1173,6 +1173,9 @@ xfs_fs_geometry(
geo->flags |= XFS_FSOP_GEOM_FLAGS_ATOMIC_SWAP;
if (xfs_has_metadir(mp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_METADIR;
+ if (xfs_has_nrext64(mp))
+ geo->flags |= XFS_FSOP_GEOM_FLAGS_NREXT64;
+
geo->rtsectsize = sbp->sb_blocksize;
geo->dirblocksize = xfs_dir2_dirblock_bytes(sbp);
diff --git a/libxfs/xfs_trans_inode.c b/libxfs/xfs_trans_inode.c
index 6fc7a65d..fb069c02 100644
--- a/libxfs/xfs_trans_inode.c
+++ b/libxfs/xfs_trans_inode.c
@@ -141,6 +141,11 @@ xfs_trans_log_inode(
flags |= XFS_ILOG_CORE;
}
+ if ((flags & XFS_ILOG_CORE) &&
+ xfs_has_nrext64(ip->i_mount) &&
+ !xfs_inode_has_nrext64(ip))
+ ip->i_diflags2 |= XFS_DIFLAG2_NREXT64;
+
/*
* Inode verifiers do not check that the extent size hint is an integer
* multiple of the rt extent size on a directory with both rtinherit
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index 4e8760c4..56b373f9 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -438,8 +438,11 @@ xlog_print_trans_qoff(char **ptr, uint len)
static void
xlog_print_trans_inode_core(
+ struct xfs_mount *mp,
struct xfs_log_dinode *ip)
{
+ xfs_extnum_t nextents;
+
printf(_("INODE CORE\n"));
printf(_("magic 0x%hx mode 0%ho version %d format %d\n"),
ip->di_magic, ip->di_mode, (int)ip->di_version,
@@ -450,11 +453,21 @@ xlog_print_trans_inode_core(
xlog_extract_dinode_ts(ip->di_atime),
xlog_extract_dinode_ts(ip->di_mtime),
xlog_extract_dinode_ts(ip->di_ctime));
- printf(_("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n"),
+
+ if (ip->di_flags2 & XFS_DIFLAG2_NREXT64)
+ nextents = ip->di_nextents64;
+ else
+ nextents = ip->di_nextents32;
+ printf(_("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%lx\n"),
(unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks,
- ip->di_extsize, ip->di_nextents32);
- printf(_("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n"),
- ip->di_nextents16, (int)ip->di_forkoff, ip->di_dmevmask,
+ ip->di_extsize, nextents);
+
+ if (ip->di_flags2 & XFS_DIFLAG2_NREXT64)
+ nextents = ip->di_nextents32;
+ else
+ nextents = ip->di_nextents16;
+ printf(_("naextents 0x%lx forkoff %d dmevmask 0x%x dmstate 0x%hx\n"),
+ nextents, (int)ip->di_forkoff, ip->di_dmevmask,
ip->di_dmstate);
printf(_("flags 0x%x gen 0x%x\n"),
ip->di_flags, ip->di_gen);
@@ -564,7 +577,7 @@ xlog_print_trans_inode(
memmove(&dino, *ptr, sizeof(dino));
mode = dino.di_mode & S_IFMT;
size = (int)dino.di_size;
- xlog_print_trans_inode_core(&dino);
+ xlog_print_trans_inode_core(log->l_mp, &dino);
*ptr += xfs_log_dinode_size(log->l_mp);
skip_count--;
diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c
index 403c5637..adc7c79c 100644
--- a/logprint/log_print_all.c
+++ b/logprint/log_print_all.c
@@ -238,9 +238,13 @@ xlog_recover_print_dquot(
STATIC void
xlog_recover_print_inode_core(
+ struct xlog *log,
struct xfs_log_dinode *di)
{
- printf(_(" CORE inode:\n"));
+ xfs_extnum_t nextents;
+ xfs_aextnum_t anextents;
+
+ printf(_(" CORE inode:\n"));
if (!print_inode)
return;
printf(_(" magic:%c%c mode:0x%x ver:%d format:%d\n"),
@@ -254,10 +258,19 @@ xlog_recover_print_inode_core(
xlog_extract_dinode_ts(di->di_mtime),
xlog_extract_dinode_ts(di->di_ctime));
printf(_(" flushiter:%d\n"), di->di_flushiter);
+
+ if (di->di_flags2 & XFS_DIFLAG2_NREXT64) {
+ nextents = di->di_nextents64;
+ anextents = di->di_nextents32;
+ } else {
+ nextents = di->di_nextents32;
+ anextents = di->di_nextents16;
+ }
+
printf(_(" size:0x%llx nblks:0x%llx exsize:%d "
- "nextents:%d anextents:%d\n"), (unsigned long long)
+ "nextents:%lu anextents:%u\n"), (unsigned long long)
di->di_size, (unsigned long long)di->di_nblocks,
- di->di_extsize, di->di_nextents32, (int)di->di_nextents16);
+ di->di_extsize, nextents, anextents);
printf(_(" forkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x "
"gen:%u\n"),
(int)di->di_forkoff, di->di_dmevmask, (int)di->di_dmstate,
@@ -270,6 +283,7 @@ xlog_recover_print_inode_core(
STATIC void
xlog_recover_print_inode(
+ struct xlog *log,
struct xlog_recover_item *item)
{
struct xfs_inode_log_format f_buf;
@@ -291,7 +305,7 @@ xlog_recover_print_inode(
ASSERT(item->ri_buf[1].i_len ==
offsetof(struct xfs_log_dinode, di_next_unlinked) ||
item->ri_buf[1].i_len == sizeof(struct xfs_log_dinode));
- xlog_recover_print_inode_core((struct xfs_log_dinode *)
+ xlog_recover_print_inode_core(log, (struct xfs_log_dinode *)
item->ri_buf[1].i_addr);
hasdata = (f->ilf_fields & XFS_ILOG_DFORK) != 0;
@@ -386,6 +400,7 @@ xlog_recover_print_icreate(
void
xlog_recover_print_logitem(
+ struct xlog *log,
struct xlog_recover_item *item)
{
switch (ITEM_TYPE(item)) {
@@ -396,7 +411,7 @@ xlog_recover_print_logitem(
xlog_recover_print_icreate(item);
break;
case XFS_LI_INODE:
- xlog_recover_print_inode(item);
+ xlog_recover_print_inode(log, item);
break;
case XFS_LI_EFD:
xlog_recover_print_efd(item);
@@ -442,6 +457,7 @@ xlog_recover_print_logitem(
static void
xlog_recover_print_item(
+ struct xlog *log,
struct xlog_recover_item *item)
{
int i;
@@ -507,11 +523,12 @@ xlog_recover_print_item(
(long)item->ri_buf[i].i_addr, item->ri_buf[i].i_len);
}
printf("\n");
- xlog_recover_print_logitem(item);
+ xlog_recover_print_logitem(log, item);
}
void
xlog_recover_print_trans(
+ struct xlog *log,
struct xlog_recover *trans,
struct list_head *itemq,
int print)
@@ -524,5 +541,5 @@ xlog_recover_print_trans(
print_xlog_record_line();
xlog_recover_print_trans_head(trans);
list_for_each_entry(item, itemq, ri_list)
- xlog_recover_print_item(item);
+ xlog_recover_print_item(log, item);
}
diff --git a/logprint/log_print_trans.c b/logprint/log_print_trans.c
index 2004b5a0..c6386fb0 100644
--- a/logprint/log_print_trans.c
+++ b/logprint/log_print_trans.c
@@ -24,7 +24,7 @@ xlog_recover_do_trans(
struct xlog_recover *trans,
int pass)
{
- xlog_recover_print_trans(trans, &trans->r_itemq, 3);
+ xlog_recover_print_trans(log, trans, &trans->r_itemq, 3);
return 0;
}
diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c
index 847538b1..7d3bb330 100644
--- a/repair/bmap_repair.c
+++ b/repair/bmap_repair.c
@@ -579,7 +579,10 @@ rebuild_bmap(
if (nextents == 0)
return 0;
(*dinop)->di_format = XFS_DINODE_FMT_EXTENTS;
- (*dinop)->di_nextents32 = 0;
+ if (be64_to_cpu((*dinop)->di_flags2) & XFS_DIFLAG2_NREXT64)
+ (*dinop)->di_nextents64 = 0;
+ else
+ (*dinop)->di_nextents32 = 0;
libxfs_dinode_calc_crc(mp, *dinop);
*dirty = 1;
break;
@@ -590,7 +593,10 @@ rebuild_bmap(
if (nextents == 0)
return 0;
(*dinop)->di_aformat = XFS_DINODE_FMT_EXTENTS;
- (*dinop)->di_nextents16 = 0;
+ if (be64_to_cpu((*dinop)->di_flags2) & XFS_DIFLAG2_NREXT64)
+ (*dinop)->di_nextents32 = 0;
+ else
+ (*dinop)->di_nextents16 = 0;
libxfs_dinode_calc_crc(mp, *dinop);
*dirty = 1;
break;
diff --git a/repair/dinode.c b/repair/dinode.c
index c995a524..01674443 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -78,7 +78,10 @@ _("would have cleared inode %" PRIu64 " attributes\n"), ino_num);
if (anextents != 0) {
if (no_modify)
return(1);
- dino->di_nextents16 = cpu_to_be16(0);
+ if (xfs_dinode_has_nrext64(dino))
+ dino->di_nextents32 = 0;
+ else
+ dino->di_nextents16 = 0;
}
if (dino->di_aformat != XFS_DINODE_FMT_EXTENTS) {
@@ -1872,7 +1875,10 @@ _("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
do_warn(
_("correcting nextents for inode %" PRIu64 ", was %lu - counted %" PRIu64 "\n"),
lino, dnextents, nextents);
- dino->di_nextents32 = cpu_to_be32(nextents);
+ if (xfs_dinode_has_nrext64(dino))
+ dino->di_nextents64 = cpu_to_be64(nextents);
+ else
+ dino->di_nextents32 = cpu_to_be32(nextents);
*dirty = 1;
} else {
do_warn(
@@ -1896,7 +1902,10 @@ _("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
do_warn(
_("correcting anextents for inode %" PRIu64 ", was %lu - counted %" PRIu64 "\n"),
lino, dnextents, anextents);
- dino->di_nextents16 = cpu_to_be16(anextents);
+ if (xfs_dinode_has_nrext64(dino))
+ dino->di_nextents32 = cpu_to_be32(anextents);
+ else
+ dino->di_nextents16 = cpu_to_be16(anextents);
*dirty = 1;
} else {
do_warn(
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 12/16] xfsprogs: xfs_info: Report NREXT64 feature status
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (10 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 11/16] xfsprogs: Extend per-inode extent counter widths Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 13/16] xfsprogs: Add XFS_SB_FEAT_INCOMPAT_NREXT64 to XFS_SB_FEAT_INCOMPAT_ALL Chandan Babu R
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
This commit adds support to libfrog to obtain information about the
availability of NREXT64 feature in the underlying filesystem.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libfrog/fsgeom.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index c499ef2a..33645503 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -31,6 +31,7 @@ xfs_report_geom(
int bigtime_enabled;
int inobtcount;
int metadir;
+ int nrext64;
isint = geo->logstart > 0;
lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0;
@@ -49,12 +50,13 @@ xfs_report_geom(
bigtime_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_BIGTIME ? 1 : 0;
inobtcount = geo->flags & XFS_FSOP_GEOM_FLAGS_INOBTCNT ? 1 : 0;
metadir = geo->flags & XFS_FSOP_GEOM_FLAGS_METADIR ? 1 : 0;
+ nrext64 = geo->flags & XFS_FSOP_GEOM_FLAGS_NREXT64 ? 1 : 0;
printf(_(
"meta-data=%-22s isize=%-6d agcount=%u, agsize=%u blks\n"
" =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
" =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n"
-" =%-22s reflink=%-4u bigtime=%u inobtcount=%u\n"
+" =%-22s reflink=%-4u bigtime=%u inobtcount=%u nrext64=%u\n"
" =%-22s metadir=%-4u\n"
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
" =%-22s sunit=%-6u swidth=%u blks\n"
@@ -65,7 +67,7 @@ xfs_report_geom(
mntpoint, geo->inodesize, geo->agcount, geo->agblocks,
"", geo->sectsize, attrversion, projid32bit,
"", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled,
- "", reflink_enabled, bigtime_enabled, inobtcount,
+ "", reflink_enabled, bigtime_enabled, inobtcount, nrext64,
"", metadir,
"", geo->blocksize, (unsigned long long)geo->datablocks,
geo->imaxpct,
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 13/16] xfsprogs: Add XFS_SB_FEAT_INCOMPAT_NREXT64 to XFS_SB_FEAT_INCOMPAT_ALL
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (11 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 12/16] xfsprogs: xfs_info: Report NREXT64 feature status Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 14/16] xfsprogs: Add nrext64 mkfs option Chandan Babu R
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libxfs/xfs_format.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 9971300a..a97abc4a 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -395,7 +395,8 @@ xfs_sb_has_ro_compat_feature(
XFS_SB_FEAT_INCOMPAT_META_UUID| \
XFS_SB_FEAT_INCOMPAT_BIGTIME| \
XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR| \
- XFS_SB_FEAT_INCOMPAT_METADIR)
+ XFS_SB_FEAT_INCOMPAT_METADIR| \
+ XFS_SB_FEAT_INCOMPAT_NREXT64)
#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL
static inline bool
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 14/16] xfsprogs: Add nrext64 mkfs option
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (12 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 13/16] xfsprogs: Add XFS_SB_FEAT_INCOMPAT_NREXT64 to XFS_SB_FEAT_INCOMPAT_ALL Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 15/16] xfsprogs: Add support for upgrading to NREXT64 feature Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 16/16] xfsprogs: Define max extent length based on on-disk format definition Chandan Babu R
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
Enabling nrext64 option on mkfs.xfs command line extends the maximum values of
inode data and attr fork extent counters to 2^48 - 1 and 2^32 - 1
respectively. This also sets the XFS_SB_FEAT_INCOMPAT_NREXT64 incompat flag
on the superblock preventing older kernels from mounting such a filesystem.
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
libxfs/xfs_sb.c | 2 ++
man/man8/mkfs.xfs.8 | 7 +++++++
mkfs/xfs_mkfs.c | 23 +++++++++++++++++++++++
3 files changed, 32 insertions(+)
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index 2489f619..8d066c1c 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -124,6 +124,8 @@ xfs_sb_version_to_features(
features |= XFS_FEAT_NEEDSREPAIR;
if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)
features |= XFS_FEAT_METADIR;
+ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NREXT64)
+ features |= XFS_FEAT_NREXT64;
if (sbp->sb_features_log_incompat & XFS_SB_FEAT_INCOMPAT_LOG_ATOMIC_SWAP)
features |= XFS_FEAT_ATOMIC_SWAP;
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 0e06e5be..8e24b8bc 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -650,6 +650,13 @@ space over time such that no free extents are large enough to
accommodate a chunk of 64 inodes. Without this feature enabled, inode
allocations can fail with out of space errors under severe fragmented
free space conditions.
+.TP
+.BI nrext64[= value]
+Extend maximum values of inode data and attr fork extent counters from 2^31 -
+1 and 2^15 - 1 to 2^48 - 1 and 2^32 - 1 respectively. If the value is
+omitted, 1 is assumed. This feature is disabled by default. This feature is
+only available for filesystems formatted with -m crc=1.
+.TP
.RE
.PP
.PD 0
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 899da545..37c22277 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -78,6 +78,7 @@ enum {
I_ATTR,
I_PROJID32BIT,
I_SPINODES,
+ I_NREXT64,
I_MAX_OPTS,
};
@@ -433,6 +434,7 @@ static struct opt_params iopts = {
[I_ATTR] = "attr",
[I_PROJID32BIT] = "projid32bit",
[I_SPINODES] = "sparse",
+ [I_NREXT64] = "nrext64",
},
.subopt_params = {
{ .index = I_ALIGN,
@@ -481,6 +483,12 @@ static struct opt_params iopts = {
.maxval = 1,
.defaultval = 1,
},
+ { .index = I_NREXT64,
+ .conflicts = { { NULL, LAST_CONFLICT } },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ }
},
};
@@ -813,6 +821,7 @@ struct sb_feat_args {
bool metadir; /* XFS_SB_FEAT_INCOMPAT_METADIR */
bool nodalign;
bool nortalign;
+ bool nrext64;
};
struct cli_params {
@@ -1594,6 +1603,9 @@ inode_opts_parser(
case I_SPINODES:
cli->sb_feat.spinodes = getnum(value, opts, subopt);
break;
+ case I_NREXT64:
+ cli->sb_feat.nrext64 = getnum(value, opts, subopt);
+ break;
default:
return -EINVAL;
}
@@ -2181,6 +2193,14 @@ _("metadata directory not supported without CRC support\n"));
usage();
}
cli->sb_feat.metadir = false;
+
+ if (cli->sb_feat.nrext64 &&
+ cli_opt_set(&iopts, I_NREXT64)) {
+ fprintf(stderr,
+_("64 bit extent count not supported without CRC support\n"));
+ usage();
+ }
+ cli->sb_feat.nrext64 = false;
}
if (!cli->sb_feat.finobt) {
@@ -3175,6 +3195,8 @@ sb_set_features(
sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
}
+ if (fp->nrext64)
+ sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NREXT64;
}
/*
@@ -3887,6 +3909,7 @@ main(
.nodalign = false,
.nortalign = false,
.bigtime = false,
+ .nrext64 = false,
},
};
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 15/16] xfsprogs: Add support for upgrading to NREXT64 feature
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (13 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 14/16] xfsprogs: Add nrext64 mkfs option Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 16/16] xfsprogs: Define max extent length based on on-disk format definition Chandan Babu R
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
repair/globals.c | 1 +
repair/globals.h | 1 +
repair/phase2.c | 34 ++++++++++++++++++++++++++++++++++
repair/xfs_repair.c | 11 +++++++++++
4 files changed, 47 insertions(+)
diff --git a/repair/globals.c b/repair/globals.c
index 6e52bac9..ec9d109d 100644
--- a/repair/globals.c
+++ b/repair/globals.c
@@ -54,6 +54,7 @@ bool add_finobt; /* add free inode btrees */
bool add_reflink; /* add reference count btrees */
bool add_rmapbt; /* add reverse mapping btrees */
bool add_metadir; /* add metadata directory tree */
+bool add_nrext64;
/* misc status variables */
diff --git a/repair/globals.h b/repair/globals.h
index 6c69413f..12157c52 100644
--- a/repair/globals.h
+++ b/repair/globals.h
@@ -95,6 +95,7 @@ extern bool add_finobt; /* add free inode btrees */
extern bool add_reflink; /* add reference count btrees */
extern bool add_rmapbt; /* add reverse mapping btrees */
extern bool add_metadir; /* add metadata directory tree */
+extern bool add_nrext64;
/* misc status variables */
diff --git a/repair/phase2.c b/repair/phase2.c
index cca154d3..d6dd7fcc 100644
--- a/repair/phase2.c
+++ b/repair/phase2.c
@@ -191,6 +191,7 @@ check_new_v5_geometry(
struct xfs_perag *pag;
xfs_agnumber_t agno;
xfs_ino_t rootino;
+ uint old_bm_maxlevels[2];
int min_logblocks;
int error;
@@ -201,6 +202,12 @@ check_new_v5_geometry(
memcpy(&old_sb, &mp->m_sb, sizeof(struct xfs_sb));
memcpy(&mp->m_sb, new_sb, sizeof(struct xfs_sb));
+ old_bm_maxlevels[0] = mp->m_bm_maxlevels[0];
+ old_bm_maxlevels[1] = mp->m_bm_maxlevels[1];
+
+ xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
+ xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
+
/* Do we have a big enough log? */
min_logblocks = libxfs_log_calc_minimum_size(mp);
if (old_sb.sb_logblocks < min_logblocks) {
@@ -288,6 +295,9 @@ check_new_v5_geometry(
pag->pagi_init = 0;
}
+ mp->m_bm_maxlevels[0] = old_bm_maxlevels[0];
+ mp->m_bm_maxlevels[1] = old_bm_maxlevels[1];
+
/*
* Put back the old superblock.
*/
@@ -429,6 +439,28 @@ set_metadir(
return true;
}
+static bool
+set_nrext64(
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
+{
+ if (!xfs_has_crc(mp)) {
+ printf(
+ _("Nrext64 only supported on V5 filesystems.\n"));
+ exit(0);
+ }
+
+ if (xfs_has_nrext64(mp)) {
+ printf(_("Filesystem already supports nrext64.\n"));
+ exit(0);
+ }
+
+ printf(_("Adding nrext64 to filesystem.\n"));
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NREXT64;
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+ return true;
+}
+
/* Perform the user's requested upgrades on filesystem. */
static void
upgrade_filesystem(
@@ -453,6 +485,8 @@ upgrade_filesystem(
dirty |= set_rmapbt(mp, &new_sb);
if (add_metadir)
dirty |= set_metadir(mp, &new_sb);
+ if (add_nrext64)
+ dirty |= set_nrext64(mp, &new_sb);
if (!dirty)
return;
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 95360776..0e6cbd96 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -71,6 +71,7 @@ enum c_opt_nums {
CONVERT_REFLINK,
CONVERT_RMAPBT,
CONVERT_METADIR,
+ CONVERT_NREXT64,
C_MAX_OPTS,
};
@@ -82,6 +83,7 @@ static char *c_opts[] = {
[CONVERT_REFLINK] = "reflink",
[CONVERT_RMAPBT] = "rmapbt",
[CONVERT_METADIR] = "metadir",
+ [CONVERT_NREXT64] = "nrext64",
[C_MAX_OPTS] = NULL,
};
@@ -368,6 +370,15 @@ process_args(int argc, char **argv)
_("-c metadir only supports upgrades\n"));
add_metadir = true;
break;
+ case CONVERT_NREXT64:
+ if (!val)
+ do_abort(
+ _("-c nrext64 requires a parameter\n"));
+ if (strtol(val, NULL, 0) != 1)
+ do_abort(
+ _("-c nrext64 only supports upgrades\n"));
+ add_nrext64 = true;
+ break;
default:
unknown('c', val);
break;
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH V3 16/16] xfsprogs: Define max extent length based on on-disk format definition
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
` (14 preceding siblings ...)
2021-09-16 10:08 ` [PATCH V3 15/16] xfsprogs: Add support for upgrading to NREXT64 feature Chandan Babu R
@ 2021-09-16 10:08 ` Chandan Babu R
15 siblings, 0 replies; 17+ messages in thread
From: Chandan Babu R @ 2021-09-16 10:08 UTC (permalink / raw)
To: linux-xfs; +Cc: Chandan Babu R, djwong
The maximum extent length depends on maximum block count that can be stored in
a BMBT record. Hence this commit defines MAXEXTLEN based on
BMBT_BLOCKCOUNT_BITLEN.
While at it, the commit also renames MAXEXTLEN to XFS_MAX_EXTLEN.
Suggested-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
db/metadump.c | 2 +-
libxfs/xfs_bmap.c | 53 +++++++++++++++++++++--------------------
libxfs/xfs_format.h | 20 +++++++---------
libxfs/xfs_inode_buf.c | 4 ++--
libxfs/xfs_rtbitmap.c | 4 ++--
libxfs/xfs_swapext.c | 6 ++---
libxfs/xfs_trans_resv.c | 10 ++++----
mkfs/xfs_mkfs.c | 6 ++---
repair/bmap_repair.c | 2 +-
repair/phase4.c | 2 +-
10 files changed, 54 insertions(+), 55 deletions(-)
diff --git a/db/metadump.c b/db/metadump.c
index 3e3e05c7..77a27707 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -20,7 +20,7 @@
#include "field.h"
#include "dir2.h"
-#define DEFAULT_MAX_EXT_SIZE MAXEXTLEN
+#define DEFAULT_MAX_EXT_SIZE XFS_MAX_EXTLEN
/* copy all metadata structures to/from a file */
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 8a1b94bb..fa7b4a2a 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -541,7 +541,7 @@ __xfs_bmap_add_free(
ASSERT(bno != NULLFSBLOCK);
ASSERT(len > 0);
- ASSERT(len <= MAXEXTLEN);
+ ASSERT(len <= XFS_MAX_EXTLEN);
ASSERT(!isnullstartblock(bno));
agno = XFS_FSB_TO_AGNO(mp, bno);
agbno = XFS_FSB_TO_AGBNO(mp, bno);
@@ -1497,7 +1497,7 @@ xfs_bmap_add_extent_delay_real(
LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
LEFT.br_state == new->br_state &&
- LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+ LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_EXTLEN)
state |= BMAP_LEFT_CONTIG;
/*
@@ -1515,13 +1515,13 @@ xfs_bmap_add_extent_delay_real(
new_endoff == RIGHT.br_startoff &&
new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
new->br_state == RIGHT.br_state &&
- new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
+ new->br_blockcount + RIGHT.br_blockcount <= XFS_MAX_EXTLEN &&
((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
BMAP_RIGHT_FILLING)) !=
(BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
BMAP_RIGHT_FILLING) ||
LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
- <= MAXEXTLEN))
+ <= XFS_MAX_EXTLEN))
state |= BMAP_RIGHT_CONTIG;
error = 0;
@@ -2060,7 +2060,7 @@ xfs_bmap_add_extent_unwritten_real(
LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
LEFT.br_state == new->br_state &&
- LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+ LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_EXTLEN)
state |= BMAP_LEFT_CONTIG;
/*
@@ -2078,13 +2078,13 @@ xfs_bmap_add_extent_unwritten_real(
new_endoff == RIGHT.br_startoff &&
new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
new->br_state == RIGHT.br_state &&
- new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
+ new->br_blockcount + RIGHT.br_blockcount <= XFS_MAX_EXTLEN &&
((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
BMAP_RIGHT_FILLING)) !=
(BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
BMAP_RIGHT_FILLING) ||
LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
- <= MAXEXTLEN))
+ <= XFS_MAX_EXTLEN))
state |= BMAP_RIGHT_CONTIG;
/*
@@ -2593,15 +2593,15 @@ xfs_bmap_add_extent_hole_delay(
*/
if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&
left.br_startoff + left.br_blockcount == new->br_startoff &&
- left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+ left.br_blockcount + new->br_blockcount <= XFS_MAX_EXTLEN)
state |= BMAP_LEFT_CONTIG;
if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&
new->br_startoff + new->br_blockcount == right.br_startoff &&
- new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
+ new->br_blockcount + right.br_blockcount <= XFS_MAX_EXTLEN &&
(!(state & BMAP_LEFT_CONTIG) ||
(left.br_blockcount + new->br_blockcount +
- right.br_blockcount <= MAXEXTLEN)))
+ right.br_blockcount <= XFS_MAX_EXTLEN)))
state |= BMAP_RIGHT_CONTIG;
/*
@@ -2744,17 +2744,17 @@ xfs_bmap_add_extent_hole_real(
left.br_startoff + left.br_blockcount == new->br_startoff &&
left.br_startblock + left.br_blockcount == new->br_startblock &&
left.br_state == new->br_state &&
- left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+ left.br_blockcount + new->br_blockcount <= XFS_MAX_EXTLEN)
state |= BMAP_LEFT_CONTIG;
if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
new->br_startoff + new->br_blockcount == right.br_startoff &&
new->br_startblock + new->br_blockcount == right.br_startblock &&
new->br_state == right.br_state &&
- new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
+ new->br_blockcount + right.br_blockcount <= XFS_MAX_EXTLEN &&
(!(state & BMAP_LEFT_CONTIG) ||
left.br_blockcount + new->br_blockcount +
- right.br_blockcount <= MAXEXTLEN))
+ right.br_blockcount <= XFS_MAX_EXTLEN))
state |= BMAP_RIGHT_CONTIG;
error = 0;
@@ -2996,15 +2996,15 @@ xfs_bmap_extsize_align(
/*
* For large extent hint sizes, the aligned extent might be larger than
- * MAXEXTLEN. In that case, reduce the size by an extsz so that it pulls
- * the length back under MAXEXTLEN. The outer allocation loops handle
+ * XFS_MAX_EXTLEN. In that case, reduce the size by an extsz so that it pulls
+ * the length back under XFS_MAX_EXTLEN. The outer allocation loops handle
* short allocation just fine, so it is safe to do this. We only want to
* do it when we are forced to, though, because it means more allocation
* operations are required.
*/
- while (align_alen > MAXEXTLEN)
+ while (align_alen > XFS_MAX_EXTLEN)
align_alen -= extsz;
- ASSERT(align_alen <= MAXEXTLEN);
+ ASSERT(align_alen <= XFS_MAX_EXTLEN);
/*
* If the previous block overlaps with this proposed allocation
@@ -3094,9 +3094,9 @@ xfs_bmap_extsize_align(
return -EINVAL;
} else {
ASSERT(orig_off >= align_off);
- /* see MAXEXTLEN handling above */
+ /* see XFS_MAX_EXTLEN handling above */
ASSERT(orig_end <= align_off + align_alen ||
- align_alen + extsz > MAXEXTLEN);
+ align_alen + extsz > XFS_MAX_EXTLEN);
}
#ifdef DEBUG
@@ -4063,7 +4063,7 @@ xfs_bmapi_reserve_delalloc(
* Cap the alloc length. Keep track of prealloc so we know whether to
* tag the inode before we return.
*/
- alen = XFS_FILBLKS_MIN(len + prealloc, MAXEXTLEN);
+ alen = XFS_FILBLKS_MIN(len + prealloc, XFS_MAX_EXTLEN);
if (!eof)
alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
if (prealloc && alen >= len)
@@ -4196,7 +4196,7 @@ xfs_bmapi_allocate(
if (!xfs_iext_peek_prev_extent(ifp, &bma->icur, &bma->prev))
bma->prev.br_startoff = NULLFILEOFF;
} else {
- bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN);
+ bma->length = XFS_FILBLKS_MIN(bma->length, XFS_MAX_EXTLEN);
if (!bma->eof)
bma->length = XFS_FILBLKS_MIN(bma->length,
bma->got.br_startoff - bma->offset);
@@ -4517,8 +4517,8 @@ xfs_bmapi_write(
* xfs_extlen_t and therefore 32 bits. Hence we have to
* check for 32-bit overflows and handle them here.
*/
- if (len > (xfs_filblks_t)MAXEXTLEN)
- bma.length = MAXEXTLEN;
+ if (len > (xfs_filblks_t)XFS_MAX_EXTLEN)
+ bma.length = XFS_MAX_EXTLEN;
else
bma.length = len;
@@ -4653,7 +4653,8 @@ xfs_bmapi_convert_delalloc(
bma.ip = ip;
bma.wasdel = true;
bma.offset = bma.got.br_startoff;
- bma.length = max_t(xfs_filblks_t, bma.got.br_blockcount, MAXEXTLEN);
+ bma.length = max_t(xfs_filblks_t, bma.got.br_blockcount,
+ XFS_MAX_EXTLEN);
bma.minleft = xfs_bmapi_minleft(tp, ip, whichfork);
/*
@@ -4736,7 +4737,7 @@ xfs_bmapi_remap(
ifp = XFS_IFORK_PTR(ip, whichfork);
ASSERT(len > 0);
- ASSERT(len <= (xfs_filblks_t)MAXEXTLEN);
+ ASSERT(len <= (xfs_filblks_t)XFS_MAX_EXTLEN);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC |
XFS_BMAPI_NORMAP)));
@@ -5709,7 +5710,7 @@ xfs_bmse_can_merge(
if ((left->br_startoff + left->br_blockcount != startoff) ||
(left->br_startblock + left->br_blockcount != got->br_startblock) ||
(left->br_state != got->br_state) ||
- (left->br_blockcount + got->br_blockcount > MAXEXTLEN))
+ (left->br_blockcount + got->br_blockcount > XFS_MAX_EXTLEN))
return false;
return true;
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index a97abc4a..c9af8c04 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -884,17 +884,6 @@ enum xfs_dinode_fmt {
{ XFS_DINODE_FMT_BTREE, "btree" }, \
{ XFS_DINODE_FMT_UUID, "uuid" }
-/*
- * Max values for extlen, disk inode's extent counters.
- */
-
-#define MAXEXTLEN ((xfs_extlen_t)0x1fffff) /* 21 bits */
-#define XFS_IFORK_EXTCNT_MAXU48 ((xfs_extnum_t)0xffffffffffff) /* Unsigned 48-bits */
-#define XFS_IFORK_EXTCNT_MAXU32 ((xfs_aextnum_t)0xffffffff) /* Unsigned 32-bits */
-#define XFS_IFORK_EXTCNT_MAXS32 ((xfs_extnum_t)0x7fffffff) /* Signed 32-bits */
-#define XFS_IFORK_EXTCNT_MAXS16 ((xfs_aextnum_t)0x7fff) /* Signed 16-bits */
-
-
/*
* Inode minimum and maximum sizes.
*/
@@ -1700,6 +1689,15 @@ typedef struct xfs_bmbt_rec {
typedef uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
typedef xfs_bmbt_rec_t xfs_bmdr_rec_t;
+/*
+ * Max values for extlen, disk inode's extent counters.
+ */
+#define XFS_MAX_EXTLEN ((xfs_extlen_t)(1 << BMBT_BLOCKCOUNT_BITLEN) - 1)
+#define XFS_IFORK_EXTCNT_MAXU48 ((xfs_extnum_t)0xffffffffffff) /* Unsigned 48-bits */
+#define XFS_IFORK_EXTCNT_MAXU32 ((xfs_aextnum_t)0xffffffff) /* Unsigned 32-bits */
+#define XFS_IFORK_EXTCNT_MAXS32 ((xfs_extnum_t)0x7fffffff) /* Signed 32-bits */
+#define XFS_IFORK_EXTCNT_MAXS16 ((xfs_aextnum_t)0x7fff) /* Signed 16-bits */
+
/*
* Values and macros for delayed-allocation startblock fields.
*/
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 15690f7f..77288b82 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -744,7 +744,7 @@ xfs_inode_validate_extsize(
if (extsize_bytes % blocksize_bytes)
return __this_address;
- if (extsize > MAXEXTLEN)
+ if (extsize > XFS_MAX_EXTLEN)
return __this_address;
if (!rt_flag && extsize > mp->m_sb.sb_agblocks / 2)
@@ -801,7 +801,7 @@ xfs_inode_validate_cowextsize(
if (cowextsize_bytes % mp->m_sb.sb_blocksize)
return __this_address;
- if (cowextsize > MAXEXTLEN)
+ if (cowextsize > XFS_MAX_EXTLEN)
return __this_address;
if (cowextsize > mp->m_sb.sb_agblocks / 2)
diff --git a/libxfs/xfs_rtbitmap.c b/libxfs/xfs_rtbitmap.c
index a8a71adc..c87c9d0b 100644
--- a/libxfs/xfs_rtbitmap.c
+++ b/libxfs/xfs_rtbitmap.c
@@ -1013,7 +1013,7 @@ xfs_rtfree_extent(
/*
* Free some blocks in the realtime subvolume. rtbno and rtlen are in units of
* rt blocks, not rt extents; must be aligned to the rt extent size; and rtlen
- * cannot exceed MAXEXTLEN.
+ * cannot exceed XFS_MAX_EXTLEN.
*/
int
xfs_rtfree_blocks(
@@ -1026,7 +1026,7 @@ xfs_rtfree_blocks(
xfs_filblks_t len;
xfs_extlen_t mod;
- ASSERT(rtlen <= MAXEXTLEN);
+ ASSERT(rtlen <= XFS_MAX_EXTLEN);
len = div_u64_rem(rtlen, mp->m_sb.sb_rextsize, &mod);
if (mod) {
diff --git a/libxfs/xfs_swapext.c b/libxfs/xfs_swapext.c
index 2fb0ac76..f8facf1d 100644
--- a/libxfs/xfs_swapext.c
+++ b/libxfs/xfs_swapext.c
@@ -755,7 +755,7 @@ can_merge(
if (b1->br_startoff + b1->br_blockcount == b2->br_startoff &&
b1->br_startblock + b1->br_blockcount == b2->br_startblock &&
b1->br_state == b2->br_state &&
- b1->br_blockcount + b2->br_blockcount <= MAXEXTLEN)
+ b1->br_blockcount + b2->br_blockcount <= XFS_MAX_EXTLEN)
return true;
return false;
@@ -797,7 +797,7 @@ delta_nextents_step(
state |= CRIGHT_CONTIG;
if ((state & CBOTH_CONTIG) == CBOTH_CONTIG &&
left->br_startblock + curr->br_startblock +
- right->br_startblock > MAXEXTLEN)
+ right->br_startblock > XFS_MAX_EXTLEN)
state &= ~CRIGHT_CONTIG;
if (nhole)
@@ -808,7 +808,7 @@ delta_nextents_step(
state |= NRIGHT_CONTIG;
if ((state & NBOTH_CONTIG) == NBOTH_CONTIG &&
left->br_startblock + new->br_startblock +
- right->br_startblock > MAXEXTLEN)
+ right->br_startblock > XFS_MAX_EXTLEN)
state &= ~NRIGHT_CONTIG;
switch (state & (CLEFT_CONTIG | CRIGHT_CONTIG | CHOLE)) {
diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c
index f153e021..6566012d 100644
--- a/libxfs/xfs_trans_resv.c
+++ b/libxfs/xfs_trans_resv.c
@@ -208,8 +208,8 @@ xfs_calc_inode_chunk_res(
/*
* Per-extent log reservation for the btree changes involved in freeing or
* allocating a realtime extent. We have to be able to log as many rtbitmap
- * blocks as needed to mark inuse MAXEXTLEN blocks' worth of realtime extents,
- * as well as the realtime summary block.
+ * blocks as needed to mark inuse XFS_MAX_EXTLEN blocks' worth of realtime
+ * extents, as well as the realtime summary block.
*/
static unsigned int
xfs_rtalloc_log_count(
@@ -219,7 +219,7 @@ xfs_rtalloc_log_count(
unsigned int blksz = XFS_FSB_TO_B(mp, 1);
unsigned int rtbmp_bytes;
- rtbmp_bytes = (MAXEXTLEN / mp->m_sb.sb_rextsize) / NBBY;
+ rtbmp_bytes = (XFS_MAX_EXTLEN / mp->m_sb.sb_rextsize) / NBBY;
return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
}
@@ -278,7 +278,7 @@ xfs_refcount_log_reservation(
* the inode's bmap btree: max depth * block size
* the agfs of the ags from which the extents are allocated: 2 * sector
* the superblock free block counter: sector size
- * the realtime bitmap: ((MAXEXTLEN / rtextsize) / NBBY) bytes
+ * the realtime bitmap: ((XFS_MAX_EXTLEN / rtextsize) / NBBY) bytes
* the realtime summary: 1 block
* the allocation btrees: 2 trees * (2 * max depth - 1) * block size
* And the bmap_finish transaction can free bmap blocks in a join (t3):
@@ -333,7 +333,7 @@ xfs_calc_write_reservation(
* the agf for each of the ags: 2 * sector size
* the agfl for each of the ags: 2 * sector size
* the super block to reflect the freed blocks: sector size
- * the realtime bitmap: 2 exts * ((MAXEXTLEN / rtextsize) / NBBY) bytes
+ * the realtime bitmap: 2 exts * ((XFS_MAX_EXTLEN / rtextsize) / NBBY) bytes
* the realtime summary: 2 exts * 1 block
* worst case split in allocation btrees per extent assuming 2 extents:
* 2 exts * 2 trees * (2 * max depth - 1) * block size
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 37c22277..49a450e0 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2427,7 +2427,7 @@ validate_extsize_hint(
fprintf(stderr,
_("illegal extent size hint %lld, must be less than %u.\n"),
(long long)cli->fsx.fsx_extsize,
- min(MAXEXTLEN, mp->m_sb.sb_agblocks / 2));
+ min(XFS_MAX_EXTLEN, mp->m_sb.sb_agblocks / 2));
usage();
}
@@ -2450,7 +2450,7 @@ _("illegal extent size hint %lld, must be less than %u.\n"),
fprintf(stderr,
_("illegal extent size hint %lld, must be less than %u and a multiple of %u.\n"),
(long long)cli->fsx.fsx_extsize,
- min(MAXEXTLEN, mp->m_sb.sb_agblocks / 2),
+ min(XFS_MAX_EXTLEN, mp->m_sb.sb_agblocks / 2),
mp->m_sb.sb_rextsize);
usage();
}
@@ -2479,7 +2479,7 @@ validate_cowextsize_hint(
fprintf(stderr,
_("illegal CoW extent size hint %lld, must be less than %u.\n"),
(long long)cli->fsx.fsx_cowextsize,
- min(MAXEXTLEN, mp->m_sb.sb_agblocks / 2));
+ min(XFS_MAX_EXTLEN, mp->m_sb.sb_agblocks / 2));
usage();
}
}
diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c
index 7d3bb330..811b16dc 100644
--- a/repair/bmap_repair.c
+++ b/repair/bmap_repair.c
@@ -64,7 +64,7 @@ xrep_bmap_from_rmap(
do {
irec.br_blockcount = min_t(xfs_filblks_t, blockcount,
- MAXEXTLEN);
+ XFS_MAX_EXTLEN);
libxfs_bmbt_disk_set_all(&rbe, &irec);
error = slab_add(rb->bmap_records, &rbe);
diff --git a/repair/phase4.c b/repair/phase4.c
index b752b07c..880cd313 100644
--- a/repair/phase4.c
+++ b/repair/phase4.c
@@ -393,7 +393,7 @@ phase4(xfs_mount_t *mp)
if (rt_start == 0) {
rt_start = bno;
rt_len = 1;
- } else if (rt_len == MAXEXTLEN) {
+ } else if (rt_len == XFS_MAX_EXTLEN) {
/*
* large extent case
*/
--
2.30.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2021-09-16 10:09 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-16 10:08 [PATCH V3 00/16] xfsprogs: Extend per-inode extent counters Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 01/16] xfsprogs: xfs_repair: allow administrators to add older v5 features Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 02/16] xfsprogs: Move extent count limits to xfs_format.h Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 03/16] xfsprogs: Introduce xfs_iext_max_nextents() helper Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 04/16] xfsprogs: Rename MAXEXTNUM, MAXAEXTNUM to XFS_IFORK_EXTCNT_MAXS32, XFS_IFORK_EXTCNT_MAXS16 Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 05/16] xfsprogs: Use xfs_extnum_t instead of basic data types Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 06/16] xfsprogs: Introduce xfs_dfork_nextents() helper Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 07/16] xfsprogs: xfs_dfork_nextents: Return extent count via an out argument Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 08/16] xfsprogs: Rename inode's extent counter fields based on their width Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 09/16] xfsprogs: Promote xfs_extnum_t and xfs_aextnum_t to 64 and 32-bits respectively Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 10/16] xfsprogs: Enable bulkstat ioctl to support 64-bit extent counters Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 11/16] xfsprogs: Extend per-inode extent counter widths Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 12/16] xfsprogs: xfs_info: Report NREXT64 feature status Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 13/16] xfsprogs: Add XFS_SB_FEAT_INCOMPAT_NREXT64 to XFS_SB_FEAT_INCOMPAT_ALL Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 14/16] xfsprogs: Add nrext64 mkfs option Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 15/16] xfsprogs: Add support for upgrading to NREXT64 feature Chandan Babu R
2021-09-16 10:08 ` [PATCH V3 16/16] xfsprogs: Define max extent length based on on-disk format definition Chandan Babu R
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).