On Mon, Aug 17, 2020 at 04:00:22PM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > Report the large format timestamps. > > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > --- > db/dquot.c | 31 +++++++++++- > db/field.c | 6 ++ > db/field.h | 3 + > db/fprint.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++ > db/fprint.h | 6 ++ > db/inode.c | 28 ++++++++++- > db/sb.c | 2 + > libxfs/libxfs_api_defs.h | 3 + > 8 files changed, 194 insertions(+), 5 deletions(-) > > > diff --git a/db/dquot.c b/db/dquot.c > index edfcb0ca0744..30f4e6523c39 100644 > --- a/db/dquot.c > +++ b/db/dquot.c > @@ -44,6 +44,22 @@ const field_t dqblk_flds[] = { > { NULL } > }; > > +static int > +dquot_timestamp_count( > + void *obj, > + int startoff) > +{ > + return xfs_sb_version_hasbigtime(&mp->m_sb) ? 0 : 1; > +} > + > +static int > +dquot_bigtimestamp_count( > + void *obj, > + int startoff) > +{ > + return xfs_sb_version_hasbigtime(&mp->m_sb) ? 1 : 0; > +} > + > #define DOFF(f) bitize(offsetof(struct xfs_disk_dquot, d_ ## f)) > const field_t disk_dquot_flds[] = { > { "magic", FLDT_UINT16X, OI(DOFF(magic)), C1, 0, TYP_NONE }, > @@ -60,8 +76,14 @@ const field_t disk_dquot_flds[] = { > TYP_NONE }, > { "bcount", FLDT_QCNT, OI(DOFF(bcount)), C1, 0, TYP_NONE }, > { "icount", FLDT_QCNT, OI(DOFF(icount)), C1, 0, TYP_NONE }, > - { "itimer", FLDT_INT32D, OI(DOFF(itimer)), C1, 0, TYP_NONE }, > - { "btimer", FLDT_INT32D, OI(DOFF(btimer)), C1, 0, TYP_NONE }, > + { "itimer", FLDT_INT32D, OI(DOFF(itimer)), dquot_timestamp_count, > + FLD_COUNT, TYP_NONE }, > + { "btimer", FLDT_INT32D, OI(DOFF(btimer)), dquot_timestamp_count, > + FLD_COUNT, TYP_NONE }, > + { "itimer", FLDT_BTQTIMER, OI(DOFF(itimer)), dquot_bigtimestamp_count, > + FLD_COUNT, TYP_NONE }, > + { "btimer", FLDT_BTQTIMER, OI(DOFF(btimer)), dquot_bigtimestamp_count, > + FLD_COUNT, TYP_NONE }, > { "iwarns", FLDT_QWARNCNT, OI(DOFF(iwarns)), C1, 0, TYP_NONE }, > { "bwarns", FLDT_QWARNCNT, OI(DOFF(bwarns)), C1, 0, TYP_NONE }, > { "pad0", FLDT_UINT32X, OI(DOFF(pad0)), C1, FLD_SKIPALL, TYP_NONE }, > @@ -70,7 +92,10 @@ const field_t disk_dquot_flds[] = { > { "rtb_softlimit", FLDT_QCNT, OI(DOFF(rtb_softlimit)), C1, 0, > TYP_NONE }, > { "rtbcount", FLDT_QCNT, OI(DOFF(rtbcount)), C1, 0, TYP_NONE }, > - { "rtbtimer", FLDT_INT32D, OI(DOFF(rtbtimer)), C1, 0, TYP_NONE }, > + { "rtbtimer", FLDT_INT32D, OI(DOFF(rtbtimer)), dquot_timestamp_count, > + FLD_COUNT, TYP_NONE }, > + { "rtbtimer", FLDT_BTQTIMER, OI(DOFF(rtbtimer)), > + dquot_bigtimestamp_count, FLD_COUNT, TYP_NONE }, > { "rtbwarns", FLDT_QWARNCNT, OI(DOFF(rtbwarns)), C1, 0, TYP_NONE }, > { "pad", FLDT_UINT16X, OI(DOFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, > { NULL } > diff --git a/db/field.c b/db/field.c > index cf3002c730e6..fad17b1f082e 100644 > --- a/db/field.c > +++ b/db/field.c > @@ -351,6 +351,12 @@ const ftattr_t ftattrtab[] = { > NULL, NULL }, > { FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds, > SI(bitsz(union xfs_timestamp)), 0, NULL, timestamp_flds }, > + { FLDT_BTSEC, "btsec", fp_btsec, NULL, SI(bitsz(uint64_t)), 0, NULL, > + NULL }, > + { FLDT_BTNSEC, "btnsec", fp_btnsec, NULL, SI(bitsz(uint64_t)), 0, NULL, > + NULL }, > + { FLDT_BTQTIMER, "btqtimer", fp_btqtimer, NULL, SI(bitsz(uint32_t)), 0, > + NULL, NULL }, > { FLDT_UINT1, "uint1", fp_num, "%u", SI(1), 0, NULL, NULL }, > { FLDT_UINT16D, "uint16d", fp_num, "%u", SI(bitsz(uint16_t)), 0, NULL, > NULL }, > diff --git a/db/field.h b/db/field.h > index 15065373de39..0d27cd085b13 100644 > --- a/db/field.h > +++ b/db/field.h > @@ -170,6 +170,9 @@ typedef enum fldt { > > FLDT_TIME, > FLDT_TIMESTAMP, > + FLDT_BTSEC, > + FLDT_BTNSEC, > + FLDT_BTQTIMER, > FLDT_UINT1, > FLDT_UINT16D, > FLDT_UINT16O, > diff --git a/db/fprint.c b/db/fprint.c > index c9d07e1bca7e..3a4f839b355d 100644 > --- a/db/fprint.c > +++ b/db/fprint.c > @@ -19,6 +19,7 @@ > #include "sig.h" > #include "malloc.h" > #include "io.h" > +#include "init.h" > > int > fp_charns( > @@ -145,6 +146,125 @@ fp_time( > return 1; > } > > +static void > +fp_timespec64( > + struct timespec64 *ts) > +{ > + BUILD_BUG_ON(sizeof(long) != sizeof(time_t)); > + > + if (ts->tv_sec > LONG_MAX || ts->tv_sec < LONG_MIN) { > + dbprintf("%lld", (long long)ts->tv_sec); > + } else { > + time_t tt = ts->tv_sec; > + char *c; > + > + c = ctime(&tt); Hmm, this really ought to fall back to the %lld printf if an error occurs. --D > + dbprintf("%24.24s", c); > + } > +} > + > +int > +fp_btsec( > + void *obj, > + int bit, > + int count, > + char *fmtstr, > + int size, > + int arg, > + int base, > + int array) > +{ > + struct timespec64 ts; > + union xfs_timestamp *xts; > + int bitpos; > + int i; > + > + ASSERT(bitoffs(bit) == 0); > + for (i = 0, bitpos = bit; > + i < count && !seenint(); > + i++, bitpos += size) { > + if (array) > + dbprintf("%d:", i + base); > + xts = obj + byteize(bitpos); > + libxfs_inode_from_disk_timestamp(obj, &ts, xts); > + fp_timespec64(&ts); > + if (i < count - 1) > + dbprintf(" "); > + } > + return 1; > +} > + > +int > +fp_btnsec( > + void *obj, > + int bit, > + int count, > + char *fmtstr, > + int size, > + int arg, > + int base, > + int array) > +{ > + struct timespec64 ts; > + union xfs_timestamp *xts; > + int bitpos; > + int i; > + > + ASSERT(bitoffs(bit) == 0); > + for (i = 0, bitpos = bit; > + i < count && !seenint(); > + i++, bitpos += size) { > + if (array) > + dbprintf("%d:", i + base); > + xts = obj + byteize(bitpos); > + libxfs_inode_from_disk_timestamp(obj, &ts, xts); > + dbprintf("%u", ts.tv_nsec); > + if (i < count - 1) > + dbprintf(" "); > + } > + return 1; > +} > + > +int > +fp_btqtimer( > + void *obj, > + int bit, > + int count, > + char *fmtstr, > + int size, > + int arg, > + int base, > + int array) > +{ > + struct timespec64 ts = { 0 }; > + struct xfs_disk_dquot *ddq = obj; > + __be32 *t; > + int bitpos; > + int i; > + > + ASSERT(bitoffs(bit) == 0); > + for (i = 0, bitpos = bit; > + i < count && !seenint(); > + i++, bitpos += size) { > + if (array) > + dbprintf("%d:", i + base); > + t = obj + byteize(bitpos); > + libxfs_dquot_from_disk_timestamp(ddq, &ts.tv_sec, *t); > + > + /* > + * Display the raw value if it's the default grace expiration > + * period (root dquot) or if the quota has not expired. > + */ > + if (ddq->d_id == 0 || ts.tv_sec == 0) > + dbprintf("%llu", (unsigned long long)ts.tv_sec); > + else > + fp_timespec64(&ts); > + if (i < count - 1) > + dbprintf(" "); > + } > + return 1; > +} > + > /*ARGSUSED*/ > int > fp_uuid( > diff --git a/db/fprint.h b/db/fprint.h > index c958dca0ed92..a33dcd11248d 100644 > --- a/db/fprint.h > +++ b/db/fprint.h > @@ -15,6 +15,12 @@ extern int fp_sarray(void *obj, int bit, int count, char *fmtstr, int size, > int arg, int base, int array); > extern int fp_time(void *obj, int bit, int count, char *fmtstr, int size, > int arg, int base, int array); > +extern int fp_btsec(void *obj, int bit, int count, char *fmtstr, int size, > + int arg, int base, int array); > +extern int fp_btnsec(void *obj, int bit, int count, char *fmtstr, int size, > + int arg, int base, int array); > +extern int fp_btqtimer(void *obj, int bit, int count, char *fmtstr, > + int size, int arg, int base, int array); > extern int fp_uuid(void *obj, int bit, int count, char *fmtstr, int size, > int arg, int base, int array); > extern int fp_crc(void *obj, int bit, int count, char *fmtstr, int size, > diff --git a/db/inode.c b/db/inode.c > index 25112bb5e4d8..5fbfd4ddb5f5 100644 > --- a/db/inode.c > +++ b/db/inode.c > @@ -175,14 +175,38 @@ const field_t inode_v3_flds[] = { > { "dax", FLDT_UINT1, > OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_DAX_BIT - 1), C1, > 0, TYP_NONE }, > + { "bigtime", FLDT_UINT1, > + OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_BIGTIME_BIT - 1), C1, > + 0, TYP_NONE }, > { NULL } > }; > > +static int > +inode_timestamp_count( > + void *obj, > + int startoff) > +{ > + return xfs_sb_version_hasbigtime(&mp->m_sb) ? 0 : 1; > +} > + > +static int > +inode_bigtimestamp_count( > + void *obj, > + int startoff) > +{ > + return xfs_sb_version_hasbigtime(&mp->m_sb) ? 1 : 0; > +} > > #define TOFF(f) bitize(offsetof(union xfs_timestamp, t_ ## f)) > const field_t timestamp_flds[] = { > - { "sec", FLDT_TIME, OI(TOFF(sec)), C1, 0, TYP_NONE }, > - { "nsec", FLDT_NSEC, OI(TOFF(nsec)), C1, 0, TYP_NONE }, > + { "sec", FLDT_TIME, OI(TOFF(sec)), inode_timestamp_count, FLD_COUNT, > + TYP_NONE }, > + { "nsec", FLDT_NSEC, OI(TOFF(nsec)), inode_timestamp_count, FLD_COUNT, > + TYP_NONE }, > + { "sec", FLDT_BTSEC, OI(TOFF(bigtime)), inode_bigtimestamp_count, > + FLD_COUNT, TYP_NONE }, > + { "nsec", FLDT_BTNSEC, OI(TOFF(bigtime)), inode_bigtimestamp_count, > + FLD_COUNT, TYP_NONE }, > { NULL } > }; > > diff --git a/db/sb.c b/db/sb.c > index 33d9f7df49bb..c68bb9a958e7 100644 > --- a/db/sb.c > +++ b/db/sb.c > @@ -727,6 +727,8 @@ version_string( > strcat(s, ",REFLINK"); > if (xfs_sb_version_hasinobtcounts(sbp)) > strcat(s, ",INOBTCNT"); > + if (xfs_sb_version_hasbigtime(sbp)) > + strcat(s, ",BIGTIME"); > return s; > } > > diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h > index 4ee02473df0d..b83dc48a4802 100644 > --- a/libxfs/libxfs_api_defs.h > +++ b/libxfs/libxfs_api_defs.h > @@ -116,6 +116,7 @@ struct timespec64 { > #define xfs_dir_replace libxfs_dir_replace > > #define xfs_dqblk_repair libxfs_dqblk_repair > +#define xfs_dquot_from_disk_timestamp libxfs_dquot_from_disk_timestamp > #define xfs_dquot_verify libxfs_dquot_verify > > #define xfs_finobt_calc_reserves libxfs_finobt_calc_reserves > @@ -137,7 +138,9 @@ struct timespec64 { > #define xfs_inobt_maxrecs libxfs_inobt_maxrecs > #define xfs_inobt_stage_cursor libxfs_inobt_stage_cursor > #define xfs_inode_from_disk libxfs_inode_from_disk > +#define xfs_inode_from_disk_timestamp libxfs_inode_from_disk_timestamp > #define xfs_inode_to_disk libxfs_inode_to_disk > +#define xfs_inode_to_disk_timestamp libxfs_inode_to_disk_timestamp > #define xfs_inode_validate_cowextsize libxfs_inode_validate_cowextsize > #define xfs_inode_validate_extsize libxfs_inode_validate_extsize > >