aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandan Babu R <chandan.babu@oracle.com>2022-06-22 14:28:52 -0500
committerEric Sandeen <sandeen@sandeen.net>2022-06-22 14:28:52 -0500
commit8be26c6a172f5738539b931db06fb911ecf7be4e (patch)
tree89b663358aa92f1688a40275058b9a2861dafdd0
parent5a8b4d6a60dffd4f09e4e30e488c8289d1813388 (diff)
downloadxfsprogs-dev-8be26c6a172f5738539b931db06fb911ecf7be4e.tar.gz
xfs: Introduce per-inode 64-bit extent counters
Source kernel commit: 52a4a14842ef940e5bab1c949e5adc8f027327dc This commit introduces new fields in the on-disk inode format to support 64-bit data fork extent counters and 32-bit attribute fork extent counters. The new fields will be used only when an inode has XFS_DIFLAG2_NREXT64 flag set. Otherwise we continue to use the regular 32-bit data fork extent counters and 16-bit attribute fork extent counters. Reviewed-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Chandan Babu R <chandan.babu@oracle.com> Suggested-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--db/field.c4
-rw-r--r--db/field.h2
-rw-r--r--db/inode.c217
-rw-r--r--libxfs/xfs_format.h33
-rw-r--r--libxfs/xfs_inode_buf.c49
-rw-r--r--libxfs/xfs_inode_fork.h6
-rw-r--r--libxfs/xfs_log_format.h33
-rw-r--r--logprint/log_misc.c21
-rw-r--r--logprint/log_print_all.c16
-rw-r--r--repair/dinode.c16
10 files changed, 361 insertions, 36 deletions
diff --git a/db/field.c b/db/field.c
index 1d873d518a..6a25b87246 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 387c189ec8..614fd0ab41 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 3fbf1db060..c9b506b905 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -27,6 +27,16 @@ static int inode_core_nlinkv2_count(void *obj, int startoff);
static int inode_core_onlink_count(void *obj, int startoff);
static int inode_core_projid_count(void *obj, int startoff);
static int inode_core_nlinkv1_count(void *obj, int startoff);
+static int inode_core_v3_pad_count(void *obj, int startoff);
+static int inode_core_v2_pad_count(void *obj, int startoff);
+static int inode_core_flushiter_count(void *obj, int startoff);
+static int inode_core_nrext64_pad_count(void *obj, int startoff);
+static int inode_core_nextents_offset(void *obj, int startoff, int idx);
+static int inode_core_nextents32_count(void *obj, int startoff);
+static int inode_core_nextents64_count(void *obj, int startoff);
+static int inode_core_anextents_offset(void *obj, int startoff, int idx);
+static int inode_core_anextents16_count(void *obj, int startoff);
+static int inode_core_anextents32_count(void *obj, int startoff);
static int inode_f(int argc, char **argv);
static int inode_u_offset(void *obj, int startoff, int idx);
static int inode_u_bmbt_count(void *obj, int startoff);
@@ -82,26 +92,42 @@ const field_t inode_core_flds[] = {
{ "format", FLDT_DINODE_FMT, OI(COFF(format)), C1, 0, TYP_NONE },
{ "nlinkv1", FLDT_UINT16D, OI(COFF(onlink)), inode_core_nlinkv1_count,
FLD_COUNT, TYP_NONE },
- { "nlinkv2", FLDT_UINT32D, OI(COFF(nlink)), inode_core_nlinkv2_count,
- FLD_COUNT, TYP_NONE },
{ "onlink", FLDT_UINT16D, OI(COFF(onlink)), inode_core_onlink_count,
FLD_COUNT, TYP_NONE },
+ { "uid", FLDT_UINT32D, OI(COFF(uid)), C1, 0, TYP_NONE },
+ { "gid", FLDT_UINT32D, OI(COFF(gid)), C1, 0, TYP_NONE },
+ { "nlinkv2", FLDT_UINT32D, OI(COFF(nlink)), inode_core_nlinkv2_count,
+ FLD_COUNT, TYP_NONE },
{ "projid_lo", FLDT_UINT16D, OI(COFF(projid_lo)),
inode_core_projid_count, FLD_COUNT, TYP_NONE },
{ "projid_hi", FLDT_UINT16D, OI(COFF(projid_hi)),
inode_core_projid_count, FLD_COUNT, TYP_NONE },
- { "pad", FLDT_UINT8X, OI(OFF(pad)), CI(6), FLD_ARRAY|FLD_SKIPALL, TYP_NONE },
- { "uid", FLDT_UINT32D, OI(COFF(uid)), C1, 0, TYP_NONE },
- { "gid", FLDT_UINT32D, OI(COFF(gid)), C1, 0, TYP_NONE },
- { "flushiter", FLDT_UINT16D, OI(COFF(flushiter)), C1, 0, TYP_NONE },
+ /* union 1 */
+ { "nextents", FLDT_UINT64D, inode_core_nextents_offset,
+ inode_core_nextents64_count, FLD_OFFSET|FLD_COUNT, TYP_NONE },
+ { "v3_pad", FLDT_UINT64D, OI(OFF(v3_pad)),
+ inode_core_v3_pad_count, FLD_COUNT|FLD_SKIPALL, TYP_NONE },
+ { "v2_pad", FLDT_UINT8X, OI(OFF(v2_pad)),
+ inode_core_v2_pad_count, FLD_ARRAY|FLD_COUNT|FLD_SKIPALL, TYP_NONE },
+ { "flushiter", FLDT_UINT16D, OI(COFF(flushiter)),
+ inode_core_flushiter_count, FLD_COUNT, TYP_NONE },
+ /* -- */
{ "atime", FLDT_TIMESTAMP, OI(COFF(atime)), C1, 0, TYP_NONE },
{ "mtime", FLDT_TIMESTAMP, OI(COFF(mtime)), C1, 0, TYP_NONE },
{ "ctime", FLDT_TIMESTAMP, OI(COFF(ctime)), C1, 0, TYP_NONE },
{ "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 },
+ /* union 2 */
+ { "nextents", FLDT_UINT32D, inode_core_nextents_offset,
+ inode_core_nextents32_count, FLD_OFFSET|FLD_COUNT, TYP_NONE },
+ { "naextents", FLDT_UINT16D, inode_core_anextents_offset,
+ inode_core_anextents16_count, FLD_OFFSET|FLD_COUNT, TYP_NONE },
+ { "naextents", FLDT_UINT32D, inode_core_anextents_offset,
+ inode_core_anextents32_count, FLD_OFFSET|FLD_COUNT, TYP_NONE },
+ { "nrext64_pad", FLDT_UINT16D, OI(COFF(nrext64_pad)),
+ inode_core_nrext64_pad_count, FLD_COUNT|FLD_SKIPALL, 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 },
@@ -402,6 +428,181 @@ inode_core_projid_count(
}
static int
+inode_core_v3_pad_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if ((dic->di_version == 3)
+ && !(dic->di_flags2 & cpu_to_be64(XFS_DIFLAG2_NREXT64)))
+ return 1;
+
+ return 0;
+}
+
+static int
+inode_core_v2_pad_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (dic->di_version == 3)
+ return 0;
+
+ return 6;
+}
+
+static int
+inode_core_flushiter_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (dic->di_version == 3)
+ return 0;
+
+ return 1;
+}
+
+static int
+inode_core_nrext64_pad_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (xfs_dinode_has_large_extent_counts(dic))
+ return 1;
+
+ return 0;
+}
+
+static int
+inode_core_nextents_offset(
+ void *obj,
+ int startoff,
+ int idx)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(idx == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (xfs_dinode_has_large_extent_counts(dic))
+ return COFF(big_nextents);
+
+ return COFF(nextents);
+}
+
+static int
+inode_core_nextents32_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (xfs_dinode_has_large_extent_counts(dic))
+ return 0;
+
+ return 1;
+}
+
+static int
+inode_core_nextents64_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (xfs_dinode_has_large_extent_counts(dic))
+ return 1;
+
+ return 0;
+}
+
+static int
+inode_core_anextents_offset(
+ void *obj,
+ int startoff,
+ int idx)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(idx == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (xfs_dinode_has_large_extent_counts(dic))
+ return COFF(big_anextents);
+
+ return COFF(anextents);
+}
+
+static int
+inode_core_anextents16_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (xfs_dinode_has_large_extent_counts(dic))
+ return 0;
+
+ return 1;
+}
+
+static int
+inode_core_anextents32_count(
+ void *obj,
+ int startoff)
+{
+ struct xfs_dinode *dic;
+
+ ASSERT(startoff == 0);
+ ASSERT(obj == iocur_top->data);
+ dic = obj;
+
+ if (xfs_dinode_has_large_extent_counts(dic))
+ return 1;
+
+ return 0;
+}
+
+static int
inode_f(
int argc,
char **argv)
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index eb85bc9b22..82b404c99b 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -792,16 +792,41 @@ struct xfs_dinode {
__be32 di_nlink; /* number of links to file */
__be16 di_projid_lo; /* lower part of owner's project id */
__be16 di_projid_hi; /* higher part owner's project id */
- __u8 di_pad[6]; /* unused, zeroed space */
- __be16 di_flushiter; /* incremented on flush */
+ union {
+ /* Number of data fork extents if NREXT64 is set */
+ __be64 di_big_nextents;
+
+ /* Padding for V3 inodes without NREXT64 set. */
+ __be64 di_v3_pad;
+
+ /* Padding and inode flush counter for V2 inodes. */
+ struct {
+ __u8 di_v2_pad[6];
+ __be16 di_flushiter;
+ };
+ };
xfs_timestamp_t di_atime; /* time last accessed */
xfs_timestamp_t di_mtime; /* time last modified */
xfs_timestamp_t di_ctime; /* time created/inode modified */
__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*/
+ union {
+ /*
+ * For V2 inodes and V3 inodes without NREXT64 set, this
+ * is the number of data and attr fork extents.
+ */
+ struct {
+ __be32 di_nextents;
+ __be16 di_anextents;
+ } __packed;
+
+ /* Number of attr fork extents if NREXT64 is set. */
+ struct {
+ __be32 di_big_anextents;
+ __be16 di_nrext64_pad;
+ } __packed;
+ } __packed;
__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 */
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index deb143171f..bb0f8a7dd2 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -276,6 +276,25 @@ 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_large_extent_counts(ip)) {
+ to->di_big_nextents = cpu_to_be64(xfs_ifork_nextents(&ip->i_df));
+ to->di_big_anextents = cpu_to_be32(xfs_ifork_nextents(ip->i_afp));
+ /*
+ * We might be upgrading the inode to use larger extent counters
+ * than was previously used. Hence zero the unused field.
+ */
+ to->di_nrext64_pad = cpu_to_be16(0);
+ } else {
+ to->di_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
+ to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
+ }
+}
+
void
xfs_inode_to_disk(
struct xfs_inode *ip,
@@ -293,7 +312,6 @@ xfs_inode_to_disk(
to->di_projid_lo = cpu_to_be16(ip->i_projid & 0xffff);
to->di_projid_hi = cpu_to_be16(ip->i_projid >> 16);
- memset(to->di_pad, 0, sizeof(to->di_pad));
to->di_atime = xfs_inode_to_disk_ts(ip, inode->i_atime);
to->di_mtime = xfs_inode_to_disk_ts(ip, inode->i_mtime);
to->di_ctime = xfs_inode_to_disk_ts(ip, inode->i_ctime);
@@ -304,8 +322,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_nextents = cpu_to_be32(xfs_ifork_nextents(&ip->i_df));
- to->di_anextents = 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);
@@ -320,11 +336,14 @@ xfs_inode_to_disk(
to->di_lsn = cpu_to_be64(lsn);
memset(to->di_pad2, 0, sizeof(to->di_pad2));
uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid);
- to->di_flushiter = 0;
+ to->di_v3_pad = 0;
} else {
to->di_version = 2;
to->di_flushiter = cpu_to_be16(ip->i_flushiter);
+ memset(to->di_v2_pad, 0, sizeof(to->di_v2_pad));
}
+
+ xfs_inode_to_disk_iext_counters(ip, to);
}
static xfs_failaddr_t
@@ -395,6 +414,24 @@ xfs_dinode_verify_forkoff(
return NULL;
}
+static xfs_failaddr_t
+xfs_dinode_verify_nrext64(
+ struct xfs_mount *mp,
+ struct xfs_dinode *dip)
+{
+ if (xfs_dinode_has_large_extent_counts(dip)) {
+ if (!xfs_has_large_extent_counts(mp))
+ return __this_address;
+ if (dip->di_nrext64_pad != 0)
+ return __this_address;
+ } else if (dip->di_version >= 3) {
+ if (dip->di_v3_pad != 0)
+ return __this_address;
+ }
+
+ return NULL;
+}
+
xfs_failaddr_t
xfs_dinode_verify(
struct xfs_mount *mp,
@@ -439,6 +476,10 @@ xfs_dinode_verify(
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
return __this_address;
+ fa = xfs_dinode_verify_nrext64(mp, dip);
+ if (fa)
+ return fa;
+
nextents = xfs_dfork_data_extents(dip);
naextents = xfs_dfork_attr_extents(dip);
nblocks = be64_to_cpu(dip->di_nblocks);
diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h
index 967837a888..fd5c3c2d77 100644
--- a/libxfs/xfs_inode_fork.h
+++ b/libxfs/xfs_inode_fork.h
@@ -158,6 +158,9 @@ static inline xfs_extnum_t
xfs_dfork_data_extents(
struct xfs_dinode *dip)
{
+ if (xfs_dinode_has_large_extent_counts(dip))
+ return be64_to_cpu(dip->di_big_nextents);
+
return be32_to_cpu(dip->di_nextents);
}
@@ -165,6 +168,9 @@ static inline xfs_extnum_t
xfs_dfork_attr_extents(
struct xfs_dinode *dip)
{
+ if (xfs_dinode_has_large_extent_counts(dip))
+ return be32_to_cpu(dip->di_big_anextents);
+
return be16_to_cpu(dip->di_anextents);
}
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index fd66e70248..12234a880e 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -388,16 +388,41 @@ struct xfs_log_dinode {
uint32_t di_nlink; /* number of links to file */
uint16_t di_projid_lo; /* lower part of owner's project id */
uint16_t di_projid_hi; /* higher part of owner's project id */
- uint8_t di_pad[6]; /* unused, zeroed space */
- uint16_t di_flushiter; /* incremented on flush */
+ union {
+ /* Number of data fork extents if NREXT64 is set */
+ uint64_t di_big_nextents;
+
+ /* Padding for V3 inodes without NREXT64 set. */
+ uint64_t di_v3_pad;
+
+ /* Padding and inode flush counter for V2 inodes. */
+ struct {
+ uint8_t di_v2_pad[6]; /* V2 inode zeroed space */
+ uint16_t di_flushiter; /* V2 inode incremented on flush */
+ };
+ };
xfs_log_timestamp_t di_atime; /* time last accessed */
xfs_log_timestamp_t di_mtime; /* time last modified */
xfs_log_timestamp_t di_ctime; /* time created/inode modified */
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 */
- uint32_t di_nextents; /* number of extents in data fork */
- uint16_t di_anextents; /* number of extents in attribute fork*/
+ union {
+ /*
+ * For V2 inodes and V3 inodes without NREXT64 set, this
+ * is the number of data and attr fork extents.
+ */
+ struct {
+ uint32_t di_nextents;
+ uint16_t di_anextents;
+ } __packed;
+
+ /* Number of attr fork extents if NREXT64 is set. */
+ struct {
+ uint32_t di_big_anextents;
+ uint16_t di_nrext64_pad;
+ } __packed;
+ } __packed;
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 35e926a3ba..8aeb39b973 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -440,6 +440,8 @@ static void
xlog_print_trans_inode_core(
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,12 +452,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_big_nextents;
+ else
+ nextents = ip->di_nextents;
+ 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_nextents);
- 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_dmstate);
+ ip->di_extsize, nextents);
+
+ if (ip->di_flags2 & XFS_DIFLAG2_NREXT64)
+ nextents = ip->di_big_anextents;
+ else
+ nextents = ip->di_anextents;
+ 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);
if (ip->di_version == 3) {
diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c
index 182b9d53aa..f601f429f7 100644
--- a/logprint/log_print_all.c
+++ b/logprint/log_print_all.c
@@ -240,9 +240,21 @@ STATIC void
xlog_recover_print_inode_core(
struct xfs_log_dinode *di)
{
+ xfs_extnum_t nextents;
+ xfs_aextnum_t anextents;
+
printf(_(" CORE inode:\n"));
if (!print_inode)
return;
+
+ if (di->di_flags2 & XFS_DIFLAG2_NREXT64) {
+ nextents = di->di_big_nextents;
+ anextents = di->di_big_anextents;
+ } else {
+ nextents = di->di_nextents;
+ anextents = di->di_anextents;
+ }
+
printf(_(" magic:%c%c mode:0x%x ver:%d format:%d\n"),
(di->di_magic>>8) & 0xff, di->di_magic & 0xff,
di->di_mode, di->di_version, di->di_format);
@@ -255,9 +267,9 @@ xlog_recover_print_inode_core(
xlog_extract_dinode_ts(di->di_ctime));
printf(_(" flushiter:%d\n"), di->di_flushiter);
printf(_(" size:0x%llx nblks:0x%llx exsize:%d "
- "nextents:%d anextents:%d\n"), (unsigned long long)
+ "nextents:" PRIu64 " anextents:%u\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, 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,
diff --git a/repair/dinode.c b/repair/dinode.c
index 21d428a019..04e7f83e82 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -74,7 +74,11 @@ _("would have cleared inode %" PRIu64 " attributes\n"), ino_num);
if (xfs_dfork_attr_extents(dino) != 0) {
if (no_modify)
return(1);
- dino->di_anextents = cpu_to_be16(0);
+
+ if (xfs_dinode_has_large_extent_counts(dino))
+ dino->di_big_anextents = 0;
+ else
+ dino->di_anextents = 0;
}
if (dino->di_aformat != XFS_DINODE_FMT_EXTENTS) {
@@ -1826,7 +1830,10 @@ _("too many data fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
do_warn(
_("correcting nextents for inode %" PRIu64 ", was %" PRIu64 " - counted %" PRIu64 "\n"),
lino, dnextents, nextents);
- dino->di_nextents = cpu_to_be32(nextents);
+ if (xfs_dinode_has_large_extent_counts(dino))
+ dino->di_big_nextents = cpu_to_be64(nextents);
+ else
+ dino->di_nextents = cpu_to_be32(nextents);
*dirty = 1;
} else {
do_warn(
@@ -1849,7 +1856,10 @@ _("too many attr fork extents (%" PRIu64 ") in inode %" PRIu64 "\n"),
do_warn(
_("correcting anextents for inode %" PRIu64 ", was %" PRIu64 " - counted %" PRIu64 "\n"),
lino, danextents, anextents);
- dino->di_anextents = cpu_to_be16(anextents);
+ if (xfs_dinode_has_large_extent_counts(dino))
+ dino->di_big_anextents = cpu_to_be32(anextents);
+ else
+ dino->di_anextents = cpu_to_be16(anextents);
*dirty = 1;
} else {
do_warn(