]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: Introduce per-inode 64-bit extent counters
authorChandan Babu R <chandan.babu@oracle.com>
Wed, 22 Jun 2022 19:28:52 +0000 (14:28 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Wed, 22 Jun 2022 19:28:52 +0000 (14:28 -0500)
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>
db/field.c
db/field.h
db/inode.c
libxfs/xfs_format.h
libxfs/xfs_inode_buf.c
libxfs/xfs_inode_fork.h
libxfs/xfs_log_format.h
logprint/log_misc.c
logprint/log_print_all.c
repair/dinode.c

index 1d873d518a3ba002c612574df65849bd52e4a3d4..6a25b87246bbb0894448cb5f9a4c9ca1139f4f1d 100644 (file)
@@ -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,
index 387c189ec87a792fb76f9b7b29993716018c38b6..614fd0ab414801ff721dca82d6fe2175bced2576 100644 (file)
@@ -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,
index 3fbf1db0605c160ea3424862a1a1a87ec61d9c78..c9b506b905d03ae2811c3f7d9d0a6af98218dff6 100644 (file)
@@ -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 },
@@ -401,6 +427,181 @@ inode_core_projid_count(
        return dic->di_version >= 2;
 }
 
+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,
index eb85bc9b229b67157099c50a37eaeb6571c74514..82b404c99b800d5d396492b97afeddf03a8e95ce 100644 (file)
@@ -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 */
index deb143171ff3607ac6df999912dbd102ceb94ed3..bb0f8a7dd290c79fe5f2e96467ffbd4b894ba57d 100644 (file)
@@ -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);
index 967837a88860c63f1915d68693d3f40568c3beef..fd5c3c2d77e0dcabe9ca40fe41c02f4da760a55f 100644 (file)
@@ -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);
 }
 
index fd66e70248f7fe5a86d7e709ea801c9bb94db622..12234a880e942a7da2ad12c13645ae65bb700e95 100644 (file)
@@ -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 */
index 35e926a3baece3dfd27a2ff032a9eb722d15184f..8aeb39b973cf2a1e675c29194261534cd206e99c 100644 (file)
@@ -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) {
index 182b9d53aaaa5247c2cff24bae1e6cbeb3c937ba..f601f429f77d98d49889201a0914e1c29eae19c8 100644 (file)
@@ -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,
index 21d428a019829631fcdce76bec14e6bb7d19a82e..04e7f83e82cef0783aaed8ab8e05f4cb35c3a5aa 100644 (file)
@@ -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(