import xfsprogs-5.0.0-10.el8

This commit is contained in:
CentOS Sources 2022-05-10 03:19:44 -04:00 committed by Stepan Oksanichenko
parent 2add3ba0d3
commit e1ec33f6ac
64 changed files with 4173 additions and 1 deletions

0
SOURCES/xfsprogs-4.17.0-reflink-default.patch Normal file → Executable file
View File

View File

@ -0,0 +1,106 @@
From b192e77cc38473964c718bd035502b702c6a6e34 Mon Sep 17 00:00:00 2001
From: Eric Sandeen <sandeen@redhat.com>
Date: Tue, 21 May 2019 11:03:43 -0500
Subject: [PATCH] libxfs: create current_time helper and sync
xfs_trans_ichgtime
Make xfs_trans_ichgtime() almost match kernelspace by creating a
new current_time() helper to match the kernel utility.
This reduces still more cosmetic change. We may want to sync the
creation flag over to the kernel even though it's not used today.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
index 52d79f3..76f9ac7 100644
--- a/include/xfs_inode.h
+++ b/include/xfs_inode.h
@@ -16,6 +16,16 @@ struct xfs_mount;
struct xfs_inode_log_item;
struct xfs_dir_ops;
+/*
+ * These are not actually used, they are only for userspace build
+ * compatibility in code that looks at i_state
+ */
+#define I_DIRTY_TIME 0
+#define I_DIRTY_TIME_EXPIRED 0
+
+#define IS_I_VERSION(inode) (0)
+#define inode_maybe_inc_iversion(inode,flags) (0)
+
/*
* Inode interface. This fakes up a "VFS inode" to make the xfs_inode appear
* similar to the kernel which now is used tohold certain parts of the on-disk
@@ -25,6 +35,7 @@ struct inode {
mode_t i_mode;
uint32_t i_nlink;
xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */
+ unsigned long i_state; /* Not actually used in userspace */
uint32_t i_generation;
uint64_t i_version;
struct timespec i_atime;
@@ -150,6 +161,9 @@ extern void libxfs_trans_ichgtime(struct xfs_trans *,
struct xfs_inode *, int);
extern int libxfs_iflush_int (struct xfs_inode *, struct xfs_buf *);
+#define timespec64 timespec
+extern struct timespec64 current_time(struct inode *inode);
+
/* Inode Cache Interfaces */
extern bool libxfs_inode_verify_forks(struct xfs_inode *ip);
extern int libxfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
diff --git a/libxfs/util.c b/libxfs/util.c
index 9fe9a36..951f7cf 100644
--- a/libxfs/util.c
+++ b/libxfs/util.c
@@ -136,11 +136,21 @@ xfs_log_calc_unit_res(
return unit_bytes;
}
+struct timespec64
+current_time(struct inode *inode)
+{
+ struct timespec64 tv;
+ struct timeval stv;
+
+ gettimeofday(&stv, (struct timezone *)0);
+ tv.tv_sec = stv.tv_sec;
+ tv.tv_nsec = stv.tv_usec * 1000;
+
+ return tv;
+}
+
/*
* Change the requested timestamp in the given inode.
- *
- * This was once shared with the kernel, but has diverged to the point
- * where it's no longer worth the hassle of maintaining common code.
*/
void
libxfs_trans_ichgtime(
@@ -148,12 +158,14 @@ libxfs_trans_ichgtime(
struct xfs_inode *ip,
int flags)
{
- struct timespec tv;
- struct timeval stv;
+ struct inode *inode = VFS_I(ip);
+ struct timespec64 tv;
+
+ ASSERT(tp);
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ tv = current_time(inode);
- gettimeofday(&stv, (struct timezone *)0);
- tv.tv_sec = stv.tv_sec;
- tv.tv_nsec = stv.tv_usec * 1000;
if (flags & XFS_ICHGTIME_MOD)
VFS_I(ip)->i_mtime = tv;
if (flags & XFS_ICHGTIME_CHG)

View File

View File

@ -0,0 +1,81 @@
From bf6d4cf988176ad7efd0089830bfbf200a5e0196 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] libfrog: convert cvttime to return time64_t
Change the cvttime function to return 64-bit time values so that we can
put them to use with the bigtime feature.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/include/convert.h b/include/convert.h
index 0489a1d..2b427df 100644
--- a/include/convert.h
+++ b/include/convert.h
@@ -16,7 +16,7 @@ extern uint16_t cvt_u16(char *s, int base);
extern long long cvtnum(size_t blocksize, size_t sectorsize, char *s);
extern void cvtstr(double value, char *str, size_t sz);
-extern unsigned long cvttime(char *s);
+extern time64_t cvttime(char *s);
extern uid_t uid_from_string(char *user);
extern gid_t gid_from_string(char *group);
diff --git a/libfrog/convert.c b/libfrog/convert.c
index ed4cae7..209b874 100644
--- a/libfrog/convert.c
+++ b/libfrog/convert.c
@@ -267,14 +267,14 @@ cvtstr(
#define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24))
#define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7))
-unsigned long
+time64_t
cvttime(
char *s)
{
- unsigned long i;
+ time64_t i;
char *sp;
- i = strtoul(s, &sp, 0);
+ i = strtoll(s, &sp, 0);
if (i == 0 && sp == s)
return 0;
if (*sp == '\0')
diff --git a/quota/edit.c b/quota/edit.c
index 01d358f..b3cad02 100644
--- a/quota/edit.c
+++ b/quota/edit.c
@@ -419,13 +419,13 @@ restore_f(
static void
set_timer(
- uint32_t id,
- uint type,
- uint mask,
- char *dev,
- uint value)
+ uint32_t id,
+ uint type,
+ uint mask,
+ char *dev,
+ time64_t value)
{
- fs_disk_quota_t d;
+ struct fs_disk_quota d;
memset(&d, 0, sizeof(d));
@@ -476,7 +476,7 @@ timer_f(
int argc,
char **argv)
{
- uint value;
+ time64_t value;
char *name = NULL;
uint32_t id = 0;
int c, flags = 0, type = 0, mask = 0;

View File

@ -0,0 +1,61 @@
From 0160c1490d4b49889c9ed01a39f760cba762eac5 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] libfrog: list the bigtime feature when reporting geometry
When we're reporting on a filesystem's geometry, report if the bigtime
feature is enabled on this filesystem.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index 8879d16..ddacd59 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -25,6 +25,7 @@ xfs_report_geom(
int spinodes;
int rmapbt_enabled;
int reflink_enabled;
+ int bigtime_enabled;
isint = geo->logstart > 0;
lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0;
@@ -40,12 +41,13 @@ xfs_report_geom(
spinodes = geo->flags & XFS_FSOP_GEOM_FLAGS_SPINODES ? 1 : 0;
rmapbt_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_RMAPBT ? 1 : 0;
reflink_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_REFLINK ? 1 : 0;
+ bigtime_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_BIGTIME ? 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=%u\n"
+" =%-22s reflink=%-4u bigtime=%u\n"
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
" =%-22s sunit=%-6u swidth=%u blks\n"
"naming =version %-14u bsize=%-6u ascii-ci=%d, ftype=%d\n"
@@ -55,7 +57,7 @@ xfs_report_geom(
mntpoint, geo->inodesize, geo->agcount, geo->agblocks,
"", geo->sectsize, attrversion, projid32bit,
"", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled,
- "", reflink_enabled,
+ "", reflink_enabled, bigtime_enabled,
"", geo->blocksize, (unsigned long long)geo->datablocks,
geo->imaxpct,
"", geo->sunit, geo->swidth,
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 00f367e..a0452c2 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -115,6 +115,7 @@
#define xfs_calc_dquots_per_chunk libxfs_calc_dquots_per_chunk
#define xfs_dquot_verify libxfs_dquot_verify
#define xfs_dqblk_repair libxfs_dqblk_repair
+#define xfs_dquot_from_disk_ts libxfs_dquot_from_disk_ts
#define xfs_symlink_blocks libxfs_symlink_blocks
#define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok

View File

@ -0,0 +1,89 @@
From ec24f6fa05f695af02b4e0fca5bc27cb1cab49b7 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 12:05:32 -0500
Subject: [PATCH] libxfs: create a real struct timespec64
Create a real struct timespec64 that supports 64-bit seconds counts.
The C library struct timespec doesn't support this on 32-bit
architectures and we cannot lose the upper bits in the incore inode.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/include/libxfs.h b/include/libxfs.h
index 731561c..2bdef70 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -36,8 +36,6 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
#include "xfs_cksum.h"
-#define timespec64 timespec
-
/*
* This mirrors the kernel include for xfs_buf.h - it's implicitly included in
* every files via a similar include in the kernel xfs_linux.h.
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
index e03d1cb..ddd48be 100644
--- a/include/xfs_inode.h
+++ b/include/xfs_inode.h
@@ -32,15 +32,15 @@ struct xfs_dir_ops;
* metadata.
*/
struct inode {
- mode_t i_mode;
- uint32_t i_nlink;
- xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */
- unsigned long i_state; /* Not actually used in userspace */
- uint32_t i_generation;
- uint64_t i_version;
- struct timespec i_atime;
- struct timespec i_mtime;
- struct timespec i_ctime;
+ mode_t i_mode;
+ uint32_t i_nlink;
+ xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */
+ unsigned long i_state; /* Not actually used in userspace */
+ uint32_t i_generation;
+ uint64_t i_version;
+ struct timespec64 i_atime;
+ struct timespec64 i_mtime;
+ struct timespec64 i_ctime;
};
typedef struct xfs_inode {
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index 8232f89..b45d07e 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -62,8 +62,6 @@ extern kmem_zone_t *xfs_buf_zone;
extern kmem_zone_t *xfs_inode_zone;
extern kmem_zone_t *xfs_trans_zone;
-#define timespec64 timespec
-
/* CRC stuff, buffer API dependent on it */
#define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l))
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index c8a3b12..fbc9031 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -686,6 +686,14 @@ struct xfs_extent_data {
#define XFS_IOC_CLONE_RANGE _IOW (0x94, 13, struct xfs_clone_args)
#define XFS_IOC_FILE_EXTENT_SAME _IOWR(0x94, 54, struct xfs_extent_data)
+/* 64-bit seconds counter that works independently of the C library time_t. */
+typedef long long int time64_t;
+
+struct timespec64 {
+ time64_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+
#ifndef HAVE_BBMACROS
/*
* Block I/O parameterization. A basic block (BB) is the lowest size of

View File

@ -0,0 +1,53 @@
From c0e580154e1469f1bcef132b1a7585409f66e1e5 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 14:52:31 -0500
Subject: [PATCH] libxfs: refactor NSEC_PER_SEC
Clean up all the open-coded and duplicate definitions of time unit
conversion factors.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
NOTE: scrub is not present in rhel8, so that hunk is omitted
diff --git a/include/platform_defs.h.in b/include/platform_defs.h.in
index d111ec6..0b7214e 100644
--- a/include/platform_defs.h.in
+++ b/include/platform_defs.h.in
@@ -77,4 +77,7 @@ typedef unsigned short umode_t;
# define ASSERT(EX) ((void) 0)
#endif
+#define NSEC_PER_SEC (1000000000ULL)
+#define NSEC_PER_USEC (1000ULL)
+
#endif /* __XFS_PLATFORM_DEFS_H__ */
diff --git a/repair/dinode.c b/repair/dinode.c
index 77f78f1..8fa5f88 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -2216,7 +2216,7 @@ check_nsec(
struct xfs_timestamp *t,
int *dirty)
{
- if (be32_to_cpu(t->t_nsec) < 1000000000)
+ if (be32_to_cpu(t->t_nsec) < NSEC_PER_SEC)
return;
do_warn(
diff --git a/scrub/progress.c b/scrub/progress.c
index d0afe90..2058f59 100644
--- a/scrub/progress.c
+++ b/scrub/progress.c
@@ -110,7 +110,6 @@ progress_report(
fflush(pt.fp);
}
-#define NSEC_PER_SEC (1000000000)
static void *
progress_report_thread(void *arg)
{

View File

@ -0,0 +1,139 @@
From 9eb0d6eb9066daa621e710139c8c8d50fedbabcf Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] mkfs: enable the inode btree counter feature
Teach mkfs how to enable the inode btree counter feature.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 9d6f315..45b150f 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -188,6 +188,21 @@ option set. When the option
.B \-m crc=0
is used, the free inode btree feature is not supported and is disabled.
.TP
+.BI inobtcount= value
+This option causes the filesystem to record the number of blocks used by
+the inode btree and the free inode btree.
+This can be used to reduce mount times when the free inode btree is enabled.
+.IP
+By default,
+.B mkfs.xfs
+will not enable this option.
+This feature is only available for filesystems created with the (default)
+.B \-m finobt=1
+option set.
+When the option
+.B \-m finobt=0
+is used, the inode btree counter feature is not supported and is disabled.
+.TP
.BI uuid= value
Use the given value as the filesystem UUID for the newly created filesystem.
The default is to generate a random UUID.
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 16819d8..87f15f4 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -117,6 +117,7 @@ enum {
M_UUID,
M_RMAPBT,
M_REFLINK,
+ M_INOBTCNT,
M_MAX_OPTS,
};
@@ -651,6 +652,7 @@ static struct opt_params mopts = {
[M_UUID] = "uuid",
[M_RMAPBT] = "rmapbt",
[M_REFLINK] = "reflink",
+ [M_INOBTCNT] = "inobtcount",
},
.subopt_params = {
{ .index = M_CRC,
@@ -681,6 +683,12 @@ static struct opt_params mopts = {
.maxval = 1,
.defaultval = 1,
},
+ { .index = M_INOBTCNT,
+ .conflicts = { { NULL, LAST_CONFLICT } },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ },
},
};
@@ -731,6 +739,7 @@ struct sb_feat_args {
bool spinodes; /* XFS_SB_FEAT_INCOMPAT_SPINODES */
bool rmapbt; /* XFS_SB_FEAT_RO_COMPAT_RMAPBT */
bool reflink; /* XFS_SB_FEAT_RO_COMPAT_REFLINK */
+ bool inobtcnt; /* XFS_SB_FEAT_RO_COMPAT_INOBTCNT */
bool nodalign;
bool nortalign;
};
@@ -853,7 +862,8 @@ usage( void )
{
fprintf(stderr, _("Usage: %s\n\
/* blocksize */ [-b size=num]\n\
-/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\
+/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
+ inobtcnt=0|1]\n\
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
sectsize=num\n\
@@ -1607,6 +1617,9 @@ meta_opts_parser(
case M_REFLINK:
cli->sb_feat.reflink = getnum(value, opts, subopt);
break;
+ case M_INOBTCNT:
+ cli->sb_feat.inobtcnt = getnum(value, opts, subopt);
+ break;
default:
return -EINVAL;
}
@@ -2037,6 +2050,22 @@ _("reflink not supported without CRC support\n"));
usage();
}
cli->sb_feat.reflink = false;
+
+ if (cli->sb_feat.inobtcnt && cli_opt_set(&mopts, M_INOBTCNT)) {
+ fprintf(stderr,
+_("inode btree counters not supported without CRC support\n"));
+ usage();
+ }
+ cli->sb_feat.inobtcnt = false;
+ }
+
+ if (!cli->sb_feat.finobt) {
+ if (cli->sb_feat.inobtcnt && cli_opt_set(&mopts, M_INOBTCNT)) {
+ fprintf(stderr,
+_("inode btree counters not supported without finobt support\n"));
+ usage();
+ }
+ cli->sb_feat.inobtcnt = false;
}
if ((cli->fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
@@ -3002,6 +3031,8 @@ sb_set_features(
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT;
if (fp->reflink)
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
+ if (fp->inobtcnt)
+ sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
/*
* Sparse inode chunk support has two main inode alignment requirements.
@@ -3917,6 +3948,7 @@ main(
.spinodes = true,
.rmapbt = false,
.reflink = true,
+ .inobtcnt = false,
.parent_pointers = false,
.nodalign = false,
.nortalign = false,

View File

@ -0,0 +1,130 @@
From e9601810beb7d5b36a5fbd03c593cf63f685bfff Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] mkfs: format bigtime filesystems
Allow formatting with large timestamps.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 45b150f..0a115cb 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -154,6 +154,22 @@ valid
are:
.RS 1.2i
.TP
+.BI bigtime= value
+This option enables filesystems that can handle inode timestamps from December
+1901 to July 2486, and quota timer expirations from January 1970 to July 2486.
+The value is either 0 to disable the feature, or 1 to enable large timestamps.
+.IP
+If this feature is not enabled, the filesystem can only handle timestamps from
+December 1901 to January 2038, and quota timers from January 1970 to February
+2106.
+.IP
+By default,
+.B mkfs.xfs
+will not enable this feature.
+If the option
+.B \-m crc=0
+is used, the large timestamp feature is not supported and is disabled.
+.TP
.BI crc= value
This is used to create a filesystem which maintains and checks CRC information
in all metadata objects on disk. The value is either 0 to disable the feature,
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 87f15f4..b74a00b 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -118,6 +118,7 @@ enum {
M_RMAPBT,
M_REFLINK,
M_INOBTCNT,
+ M_BIGTIME,
M_MAX_OPTS,
};
@@ -653,6 +654,7 @@ static struct opt_params mopts = {
[M_RMAPBT] = "rmapbt",
[M_REFLINK] = "reflink",
[M_INOBTCNT] = "inobtcount",
+ [M_BIGTIME] = "bigtime",
},
.subopt_params = {
{ .index = M_CRC,
@@ -689,6 +691,12 @@ static struct opt_params mopts = {
.maxval = 1,
.defaultval = 1,
},
+ { .index = M_BIGTIME,
+ .conflicts = { { NULL, LAST_CONFLICT } },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ },
},
};
@@ -740,6 +748,7 @@ struct sb_feat_args {
bool rmapbt; /* XFS_SB_FEAT_RO_COMPAT_RMAPBT */
bool reflink; /* XFS_SB_FEAT_RO_COMPAT_REFLINK */
bool inobtcnt; /* XFS_SB_FEAT_RO_COMPAT_INOBTCNT */
+ bool bigtime; /* XFS_SB_FEAT_INCOMPAT_BIGTIME */
bool nodalign;
bool nortalign;
};
@@ -863,7 +872,7 @@ usage( void )
fprintf(stderr, _("Usage: %s\n\
/* blocksize */ [-b size=num]\n\
/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
- inobtcnt=0|1]\n\
+ inobtcnt=0|1,bigtime=0|1]\n\
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
sectsize=num\n\
@@ -1620,6 +1629,9 @@ meta_opts_parser(
case M_INOBTCNT:
cli->sb_feat.inobtcnt = getnum(value, opts, subopt);
break;
+ case M_BIGTIME:
+ cli->sb_feat.bigtime = getnum(value, opts, subopt);
+ break;
default:
return -EINVAL;
}
@@ -2057,6 +2069,13 @@ _("inode btree counters not supported without CRC support\n"));
usage();
}
cli->sb_feat.inobtcnt = false;
+
+ if (cli->sb_feat.bigtime && cli_opt_set(&mopts, M_BIGTIME)) {
+ fprintf(stderr,
+_("timestamps later than 2038 not supported without CRC support\n"));
+ usage();
+ }
+ cli->sb_feat.bigtime = false;
}
if (!cli->sb_feat.finobt) {
@@ -3033,6 +3052,8 @@ sb_set_features(
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
if (fp->inobtcnt)
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
+ if (fp->bigtime)
+ sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_BIGTIME;
/*
* Sparse inode chunk support has two main inode alignment requirements.
@@ -3952,6 +3973,7 @@ main(
.parent_pointers = false,
.nodalign = false,
.nortalign = false,
+ .bigtime = false,
},
};

View File

@ -0,0 +1,32 @@
From cac80700d88a32c1835cb37f982e98ddd73021e5 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] xfs: enable big timestamps
Source kernel commit: 29887a22713192509cfc6068ea3b200cdb8856da
Enable the big timestamp feature.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 4848de8..722c9de 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -471,7 +471,8 @@ xfs_sb_has_ro_compat_feature(
#define XFS_SB_FEAT_INCOMPAT_ALL \
(XFS_SB_FEAT_INCOMPAT_FTYPE| \
XFS_SB_FEAT_INCOMPAT_SPINODES| \
- XFS_SB_FEAT_INCOMPAT_META_UUID)
+ XFS_SB_FEAT_INCOMPAT_META_UUID| \
+ XFS_SB_FEAT_INCOMPAT_BIGTIME)
#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL
static inline bool

View File

@ -0,0 +1,28 @@
From 46da703382fa31bb02049a4131602f8a40002dbb Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] xfs: enable new inode btree counters feature
Source kernel commit: b896a39faa5a2f97dadfb347928466afb12cc63a
Enable the new inode btree counters feature.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 9ba65e5..4848de8 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -453,7 +453,8 @@ xfs_sb_has_compat_feature(
#define XFS_SB_FEAT_RO_COMPAT_ALL \
(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
- XFS_SB_FEAT_RO_COMPAT_REFLINK)
+ XFS_SB_FEAT_RO_COMPAT_REFLINK| \
+ XFS_SB_FEAT_RO_COMPAT_INOBTCNT)
#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
static inline bool
xfs_sb_has_ro_compat_feature(

View File

@ -0,0 +1,74 @@
From 18e3b8c234fac67c6c96e9ff34f0ab4598220fa1 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 15:11:09 -0500
Subject: [PATCH] xfs: explicitly define inode timestamp range
Source kernel commit: 876fdc7c4f366a709ac272ef3336ae7dce58f2af
Formally define the inode timestamp ranges that existing filesystems
support, and switch the vfs timetamp ranges to use it.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
NOTE: we hvae no xfs_compat.h so S32_MAX etc went in xfs_fs.h
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 7f7b03a..5712aa0 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -839,11 +839,33 @@ typedef struct xfs_agfl {
ASSERT(xfs_daddr_to_agno(mp, d) == \
xfs_daddr_to_agno(mp, (d) + (len) - 1)))
+/*
+ * XFS Timestamps
+ * ==============
+ *
+ * Traditional ondisk inode timestamps consist of signed 32-bit counters for
+ * seconds and nanoseconds; time zero is the Unix epoch, Jan 1 00:00:00 UTC
+ * 1970, which means that the timestamp epoch is the same as the Unix epoch.
+ * Therefore, the ondisk min and max defined here can be used directly to
+ * constrain the incore timestamps on a Unix system.
+ */
typedef struct xfs_timestamp {
__be32 t_sec; /* timestamp seconds */
__be32 t_nsec; /* timestamp nanoseconds */
} xfs_timestamp_t;
+/*
+ * Smallest possible ondisk seconds value with traditional timestamps. This
+ * corresponds exactly with the incore timestamp Dec 13 20:45:52 UTC 1901.
+ */
+#define XFS_LEGACY_TIME_MIN ((int64_t)S32_MIN)
+
+/*
+ * Largest possible ondisk seconds value with traditional timestamps. This
+ * corresponds exactly with the incore timestamp Jan 19 03:14:07 UTC 2038.
+ */
+#define XFS_LEGACY_TIME_MAX ((int64_t)S32_MAX)
+
/*
* On-disk inode structure.
*
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index fbc9031..4fa9852 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -694,6 +694,10 @@ struct timespec64 {
long tv_nsec; /* nanoseconds */
};
+#define U32_MAX ((uint32_t)~0U)
+#define S32_MAX ((int32_t)(U32_MAX >> 1))
+#define S32_MIN ((int32_t)(-S32_MAX - 1))
+
#ifndef HAVE_BBMACROS
/*
* Block I/O parameterization. A basic block (BB) is the lowest size of

View File

@ -0,0 +1,94 @@
From acaa814953273827f380262ba900f0d50a95bee2 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 15:13:50 -0500
Subject: [PATCH] xfs: move xfs_log_dinode_to_disk to the log recovery code
Source kernel commit: 88947ea0ba713c9b74b212755b3b58242f0e7a56
Move this function to xfs_inode_item_recover.c since there's only one
caller of it.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 975f097..f80ce10 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -318,58 +318,6 @@ xfs_inode_to_disk(
}
}
-void
-xfs_log_dinode_to_disk(
- struct xfs_log_dinode *from,
- struct xfs_dinode *to)
-{
- to->di_magic = cpu_to_be16(from->di_magic);
- to->di_mode = cpu_to_be16(from->di_mode);
- to->di_version = from->di_version;
- to->di_format = from->di_format;
- to->di_onlink = 0;
- to->di_uid = cpu_to_be32(from->di_uid);
- to->di_gid = cpu_to_be32(from->di_gid);
- to->di_nlink = cpu_to_be32(from->di_nlink);
- to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
- to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
- memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
-
- to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
- to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec);
- to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec);
- to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec);
- to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec);
- to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec);
-
- to->di_size = cpu_to_be64(from->di_size);
- to->di_nblocks = cpu_to_be64(from->di_nblocks);
- to->di_extsize = cpu_to_be32(from->di_extsize);
- to->di_nextents = cpu_to_be32(from->di_nextents);
- to->di_anextents = cpu_to_be16(from->di_anextents);
- to->di_forkoff = from->di_forkoff;
- to->di_aformat = from->di_aformat;
- to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
- to->di_dmstate = cpu_to_be16(from->di_dmstate);
- to->di_flags = cpu_to_be16(from->di_flags);
- to->di_gen = cpu_to_be32(from->di_gen);
-
- if (from->di_version == 3) {
- to->di_changecount = cpu_to_be64(from->di_changecount);
- to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
- to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
- to->di_flags2 = cpu_to_be64(from->di_flags2);
- to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
- to->di_ino = cpu_to_be64(from->di_ino);
- to->di_lsn = cpu_to_be64(from->di_lsn);
- memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
- uuid_copy(&to->di_uuid, &from->di_uuid);
- to->di_flushiter = 0;
- } else {
- to->di_flushiter = cpu_to_be16(from->di_flushiter);
- }
-}
-
static xfs_failaddr_t
xfs_dinode_verify_fork(
struct xfs_dinode *dip,
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
index c9ac69c..0343368 100644
--- a/libxfs/xfs_inode_buf.h
+++ b/libxfs/xfs_inode_buf.h
@@ -59,8 +59,6 @@ void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
void xfs_inode_to_disk(struct xfs_inode *ip, struct xfs_dinode *to,
xfs_lsn_t lsn);
void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);
-void xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
- struct xfs_dinode *to);
bool xfs_dinode_good_version(struct xfs_mount *mp, __u8 version);

View File

@ -0,0 +1,101 @@
From fc3e21db4a30d0d81158938cabba0fb59fc57ad8 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Wed, 11 Nov 2020 13:48:47 -0500
Subject: [PATCH] xfs: redefine xfs_ictimestamp_t
Source kernel commit: 30e05599219f3c15bd5f24190af0e33cdb4a00e5
Redefine xfs_ictimestamp_t as a uint64_t typedef in preparation for the
bigtime functionality. Preserve the legacy structure format so that we
can let the compiler take care of the masking and shifting.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index e5f97c6..8dc0df0 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -368,10 +368,13 @@ static inline int xfs_ilog_fdata(int w)
* directly mirrors the xfs_dinode structure as it must contain all the same
* information.
*/
-typedef struct xfs_ictimestamp {
+typedef uint64_t xfs_ictimestamp_t;
+
+/* Legacy timestamp encoding format. */
+struct xfs_legacy_ictimestamp {
int32_t t_sec; /* timestamp seconds */
int32_t t_nsec; /* timestamp nanoseconds */
-} xfs_ictimestamp_t;
+};
/*
* Define the format of the inode core that is logged. This structure must be
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index c325f04..4fad82b 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -446,8 +446,10 @@ xlog_print_trans_inode_core(
(int)ip->di_format);
printf(_("nlink %hd uid %d gid %d\n"),
ip->di_nlink, ip->di_uid, ip->di_gid);
- printf(_("atime 0x%x mtime 0x%x ctime 0x%x\n"),
- ip->di_atime.t_sec, ip->di_mtime.t_sec, ip->di_ctime.t_sec);
+ printf(_("atime 0x%llx mtime 0x%llx ctime 0x%llx\n"),
+ 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"),
(unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks,
ip->di_extsize, ip->di_nextents);
@@ -739,6 +741,16 @@ xlog_print_trans_icreate(
******************************************************************************
*/
+time64_t
+xlog_extract_dinode_ts(
+ const xfs_ictimestamp_t its)
+{
+ struct xfs_legacy_ictimestamp *lits;
+
+ lits = (struct xfs_legacy_ictimestamp *)&its;
+ return (time64_t)lits->t_sec;
+}
+
void
xlog_print_lseek(struct xlog *log, int fd, xfs_daddr_t blkno, int whence)
{
diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c
index eafffe2..3ca01b1 100644
--- a/logprint/log_print_all.c
+++ b/logprint/log_print_all.c
@@ -249,8 +249,10 @@ xlog_recover_print_inode_core(
printf(_(" uid:%d gid:%d nlink:%d projid:0x%04x%04x\n"),
di->di_uid, di->di_gid, di->di_nlink,
di->di_projid_hi, di->di_projid_lo);
- printf(_(" atime:%d mtime:%d ctime:%d\n"),
- di->di_atime.t_sec, di->di_mtime.t_sec, di->di_ctime.t_sec);
+ printf(_(" atime:%lld mtime:%lld ctime:%lld\n"),
+ xlog_extract_dinode_ts(di->di_atime),
+ xlog_extract_dinode_ts(di->di_mtime),
+ 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)
diff --git a/logprint/logprint.h b/logprint/logprint.h
index 98ac0d4..0061d5a 100644
--- a/logprint/logprint.h
+++ b/logprint/logprint.h
@@ -18,6 +18,7 @@ extern int print_no_data;
extern int print_no_print;
/* exports */
+extern time64_t xlog_extract_dinode_ts(const xfs_ictimestamp_t);
extern void xlog_print_lseek(struct xlog *, int, xfs_daddr_t, int);
extern void xfs_log_copy(struct xlog *, int, char *);

View File

@ -0,0 +1,196 @@
From a252aadfc977473e0851acf0d529c930c6e8e181 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 16:29:40 -0500
Subject: [PATCH] xfs: redefine xfs_timestamp_t
Source kernel commit: 5a0bb066f60fa02f453d7721844eae59f505c06e
Redefine xfs_timestamp_t as a __be64 typedef in preparation for the
bigtime functionality. Preserve the legacy structure format so that we
can let the compiler take care of masking and shifting.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/db/field.c b/db/field.c
index 66fa37e..4a45c66 100644
--- a/db/field.c
+++ b/db/field.c
@@ -350,7 +350,7 @@ const ftattr_t ftattrtab[] = {
{ FLDT_TIME, "time", fp_time, NULL, SI(bitsz(int32_t)), FTARG_SIGNED,
NULL, NULL },
{ FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds,
- SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds },
+ SI(bitsz(struct xfs_legacy_timestamp)), 0, NULL, timestamp_flds },
{ 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/inode.c b/db/inode.c
index 697f7fe..b308538 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -176,7 +176,7 @@ const field_t inode_v3_flds[] = {
};
-#define TOFF(f) bitize(offsetof(xfs_timestamp_t, t_ ## f))
+#define TOFF(f) bitize(offsetof(struct xfs_legacy_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 },
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 8858341..371f5cd 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -847,12 +847,16 @@ typedef struct xfs_agfl {
* seconds and nanoseconds; time zero is the Unix epoch, Jan 1 00:00:00 UTC
* 1970, which means that the timestamp epoch is the same as the Unix epoch.
* Therefore, the ondisk min and max defined here can be used directly to
- * constrain the incore timestamps on a Unix system.
+ * constrain the incore timestamps on a Unix system. Note that we actually
+ * encode a __be64 value on disk.
*/
-typedef struct xfs_timestamp {
+typedef __be64 xfs_timestamp_t;
+
+/* Legacy timestamp encoding format. */
+struct xfs_legacy_timestamp {
__be32 t_sec; /* timestamp seconds */
__be32 t_nsec; /* timestamp nanoseconds */
-} xfs_timestamp_t;
+};
/*
* Smallest possible ondisk seconds value with traditional timestamps. This
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index f80ce10..d8831a1 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -195,6 +195,21 @@ xfs_imap_to_bp(
return 0;
}
+/* Convert an ondisk timestamp to an incore timestamp. */
+struct timespec64
+xfs_inode_from_disk_ts(
+ const xfs_timestamp_t ts)
+{
+ struct timespec64 tv;
+ struct xfs_legacy_timestamp *lts;
+
+ lts = (struct xfs_legacy_timestamp *)&ts;
+ tv.tv_sec = (int)be32_to_cpu(lts->t_sec);
+ tv.tv_nsec = (int)be32_to_cpu(lts->t_nsec);
+
+ return tv;
+}
+
void
xfs_inode_from_disk(
struct xfs_inode *ip,
@@ -231,12 +246,10 @@ xfs_inode_from_disk(
* a time before epoch is converted to a time long after epoch
* on 64 bit systems.
*/
- inode->i_atime.tv_sec = (int)be32_to_cpu(from->di_atime.t_sec);
- inode->i_atime.tv_nsec = (int)be32_to_cpu(from->di_atime.t_nsec);
- inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec);
- inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec);
- inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec);
- inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec);
+ inode->i_atime = xfs_inode_from_disk_ts(from->di_atime);
+ inode->i_mtime = xfs_inode_from_disk_ts(from->di_mtime);
+ inode->i_ctime = xfs_inode_from_disk_ts(from->di_ctime);
+
inode->i_generation = be32_to_cpu(from->di_gen);
inode->i_mode = be16_to_cpu(from->di_mode);
@@ -254,13 +267,27 @@ xfs_inode_from_disk(
if (to->di_version == 3) {
inode_set_iversion_queried(inode,
be64_to_cpu(from->di_changecount));
- to->di_crtime.tv_sec = be32_to_cpu(from->di_crtime.t_sec);
- to->di_crtime.tv_nsec = be32_to_cpu(from->di_crtime.t_nsec);
+ to->di_crtime = xfs_inode_from_disk_ts(from->di_crtime);
to->di_flags2 = be64_to_cpu(from->di_flags2);
to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
}
}
+/* Convert an incore timestamp to an ondisk timestamp. */
+static inline xfs_timestamp_t
+xfs_inode_to_disk_ts(
+ const struct timespec64 tv)
+{
+ struct xfs_legacy_timestamp *lts;
+ xfs_timestamp_t ts;
+
+ lts = (struct xfs_legacy_timestamp *)&ts;
+ lts->t_sec = cpu_to_be32(tv.tv_sec);
+ lts->t_nsec = cpu_to_be32(tv.tv_nsec);
+
+ return ts;
+}
+
void
xfs_inode_to_disk(
struct xfs_inode *ip,
@@ -281,12 +308,9 @@ xfs_inode_to_disk(
to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
memset(to->di_pad, 0, sizeof(to->di_pad));
- to->di_atime.t_sec = cpu_to_be32(inode->i_atime.tv_sec);
- to->di_atime.t_nsec = cpu_to_be32(inode->i_atime.tv_nsec);
- to->di_mtime.t_sec = cpu_to_be32(inode->i_mtime.tv_sec);
- to->di_mtime.t_nsec = cpu_to_be32(inode->i_mtime.tv_nsec);
- to->di_ctime.t_sec = cpu_to_be32(inode->i_ctime.tv_sec);
- to->di_ctime.t_nsec = cpu_to_be32(inode->i_ctime.tv_nsec);
+ to->di_atime = xfs_inode_to_disk_ts(inode->i_atime);
+ to->di_mtime = xfs_inode_to_disk_ts(inode->i_mtime);
+ to->di_ctime = xfs_inode_to_disk_ts(inode->i_ctime);
to->di_nlink = cpu_to_be32(inode->i_nlink);
to->di_gen = cpu_to_be32(inode->i_generation);
to->di_mode = cpu_to_be16(inode->i_mode);
@@ -304,8 +328,7 @@ xfs_inode_to_disk(
if (from->di_version == 3) {
to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
- to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.tv_sec);
- to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.tv_nsec);
+ to->di_crtime = xfs_inode_to_disk_ts(from->di_crtime);
to->di_flags2 = cpu_to_be64(from->di_flags2);
to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
to->di_ino = cpu_to_be64(ip->i_ino);
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
index 0343368..6147f42 100644
--- a/libxfs/xfs_inode_buf.h
+++ b/libxfs/xfs_inode_buf.h
@@ -76,4 +76,6 @@ xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp,
uint32_t cowextsize, uint16_t mode, uint16_t flags,
uint64_t flags2);
+struct timespec64 xfs_inode_from_disk_ts(const xfs_timestamp_t ts);
+
#endif /* __XFS_INODE_BUF_H__ */
diff --git a/repair/dinode.c b/repair/dinode.c
index 8fa5f88..0c40f2a 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -2213,9 +2213,12 @@ static void
check_nsec(
const char *name,
xfs_ino_t lino,
- struct xfs_timestamp *t,
+ xfs_timestamp_t *ts,
int *dirty)
{
+ struct xfs_legacy_timestamp *t;
+
+ t = (struct xfs_legacy_timestamp *)ts;
if (be32_to_cpu(t->t_nsec) < NSEC_PER_SEC)
return;

View File

@ -0,0 +1,49 @@
From abc0f20536e3bc1505f575f452c55585c34f6e06 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 15:11:43 -0500
Subject: [PATCH] xfs: refactor default quota grace period setting code
Source kernel commit: ccc8e771aa7a80eb047fc263780816ca76dd02a6
Refactor the code that sets the default quota grace period into a helper
function so that we can override the ondisk behavior later.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index c67bd61..8858341 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1190,6 +1190,11 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
* been reached, and therefore no expiration has been set. Therefore, the
* ondisk min and max defined here can be used directly to constrain the incore
* quota expiration timestamps on a Unix system.
+ *
+ * The grace period for each quota type is stored in the root dquot (id = 0)
+ * and is applied to a non-root dquot when it exceeds the soft or hard limits.
+ * The length of quota grace periods are unsigned 32-bit quantities measured in
+ * units of seconds. A value of zero means to use the default period.
*/
/*
@@ -1204,6 +1209,14 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
*/
#define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX)
+/*
+ * Default quota grace periods, ranging from zero (use the compiled defaults)
+ * to ~136 years. These are applied to a non-root dquot that has exceeded
+ * either limit.
+ */
+#define XFS_DQ_GRACE_MIN ((int64_t)0)
+#define XFS_DQ_GRACE_MAX ((int64_t)U32_MAX)
+
/*
* This is the main portion of the on-disk representation of quota
* information for a user. This is the q_core of the xfs_dquot_t that

View File

@ -0,0 +1,54 @@
From 94c5482a7e0cbb6fd289745a4b5f49a133a4f5e8 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 15:11:09 -0500
Subject: [PATCH] xfs: refactor quota expiration timer modification
Source kernel commit: 11d8a9190275855f79d62093d789e962cc7228fb
Define explicit limits on the range of quota grace period expiration
timeouts and refactor the code that modifies the timeouts into helpers
that clamp the values appropriately. Note that we'll refactor the
default grace period timer separately.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 5712aa0..c67bd61 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1180,6 +1180,30 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
#define XFS_DQUOT_MAGIC 0x4451 /* 'DQ' */
#define XFS_DQUOT_VERSION (uint8_t)0x01 /* latest version number */
+/*
+ * XFS Quota Timers
+ * ================
+ *
+ * Traditional quota grace period expiration timers are an unsigned 32-bit
+ * seconds counter; time zero is the Unix epoch, Jan 1 00:00:01 UTC 1970.
+ * Note that an expiration value of zero means that the quota limit has not
+ * been reached, and therefore no expiration has been set. Therefore, the
+ * ondisk min and max defined here can be used directly to constrain the incore
+ * quota expiration timestamps on a Unix system.
+ */
+
+/*
+ * Smallest possible ondisk quota expiration value with traditional timestamps.
+ * This corresponds exactly with the incore expiration Jan 1 00:00:01 UTC 1970.
+ */
+#define XFS_DQ_LEGACY_EXPIRY_MIN ((int64_t)1)
+
+/*
+ * Largest possible ondisk quota expiration value with traditional timestamps.
+ * This corresponds exactly with the incore expiration Feb 7 06:28:15 UTC 2106.
+ */
+#define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX)
+
/*
* This is the main portion of the on-disk representation of quota
* information for a user. This is the q_core of the xfs_dquot_t that

View File

@ -0,0 +1,58 @@
From 68879320b482e73e6ce202a8e680c8ab7e6a2af4 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 15:12:50 -0500
Subject: [PATCH] xfs: refactor quota timestamp coding
Source kernel commit: 9f99c8fe551a056c0929dff13cbce62b6b150156
Refactor quota timestamp encoding and decoding into helper functions so
that we can add extra behavior in the next patch.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
index 324f528..963f8ea 100644
--- a/libxfs/xfs_dquot_buf.c
+++ b/libxfs/xfs_dquot_buf.c
@@ -286,3 +286,21 @@ const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {
.verify_read = xfs_dquot_buf_readahead_verify,
.verify_write = xfs_dquot_buf_write_verify,
};
+
+/* Convert an on-disk timer value into an incore timer value. */
+time64_t
+xfs_dquot_from_disk_ts(
+ struct xfs_disk_dquot *ddq,
+ __be32 dtimer)
+{
+ return be32_to_cpu(dtimer);
+}
+
+/* Convert an incore timer value into an on-disk timer value. */
+__be32
+xfs_dquot_to_disk_ts(
+ struct xfs_dquot *dqp,
+ time64_t timer)
+{
+ return cpu_to_be32(timer);
+}
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
index c69dba4..2f61cd3 100644
--- a/libxfs/xfs_quota_defs.h
+++ b/libxfs/xfs_quota_defs.h
@@ -149,4 +149,9 @@ extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
extern int xfs_dqblk_repair(struct xfs_mount *mp, struct xfs_dqblk *dqb,
xfs_dqid_t id, uint type);
+struct xfs_dquot;
+time64_t xfs_dquot_from_disk_ts(struct xfs_disk_dquot *ddq,
+ __be32 dtimer);
+__be32 xfs_dquot_to_disk_ts(struct xfs_dquot *ddq, time64_t timer);
+
#endif /* __XFS_QUOTA_H__ */

View File

@ -0,0 +1,159 @@
From 177c81e25b763c90f9815b1f4055d9d5c515a845 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 15:11:09 -0500
Subject: [PATCH] xfs: store inode btree block counts in AGI header
Source kernel commit: 2a39946c984464e4aac82c556ba9915589be7323
Add a btree block usage counters for both inode btrees to the AGI header
so that we don't have to walk the entire finobt at mount time to create
the per-AG reservations.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
NOTE: kernel routines are not used to initialize AGIs in this
version, so I added to the open-coded function in xfs_mkfs.c
diff --git a/libxfs/xfs_ag.c b/libxfs/xfs_ag.c
index a7d1a0d..850d6e3 100644
--- a/libxfs/xfs_ag.c
+++ b/libxfs/xfs_ag.c
@@ -258,6 +258,11 @@ xfs_agiblock_init(
}
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+ agi->agi_iblocks = cpu_to_be32(1);
+ if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ agi->agi_fblocks = cpu_to_be32(1);
+ }
}
typedef void (*aghdr_init_work_f)(struct xfs_mount *mp, struct xfs_buf *bp,
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 23eca3b..7f7b03a 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -449,6 +449,7 @@ xfs_sb_has_compat_feature(
#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */
#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */
#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */
+#define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */
#define XFS_SB_FEAT_RO_COMPAT_ALL \
(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
@@ -546,6 +547,17 @@ static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK);
}
+/*
+ * Inode btree block counter. We record the number of inobt and finobt blocks
+ * in the AGI header so that we can skip the finobt walk at mount time when
+ * setting up per-AG reservations.
+ */
+static inline bool xfs_sb_version_hasinobtcounts(struct xfs_sb *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+ (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT);
+}
+
/*
* end of superblock version macros
*/
@@ -750,6 +762,9 @@ typedef struct xfs_agi {
__be32 agi_free_root; /* root of the free inode btree */
__be32 agi_free_level;/* levels in free inode btree */
+ __be32 agi_iblocks; /* inobt blocks used */
+ __be32 agi_fblocks; /* finobt blocks used */
+
/* structure must be padded to 64 bit alignment */
} xfs_agi_t;
@@ -770,7 +785,8 @@ typedef struct xfs_agi {
#define XFS_AGI_ALL_BITS_R1 ((1 << XFS_AGI_NUM_BITS_R1) - 1)
#define XFS_AGI_FREE_ROOT (1 << 11)
#define XFS_AGI_FREE_LEVEL (1 << 12)
-#define XFS_AGI_NUM_BITS_R2 13
+#define XFS_AGI_IBLOCKS (1 << 13) /* both inobt/finobt block counters */
+#define XFS_AGI_NUM_BITS_R2 14
/* disk block (xfs_daddr_t) in the AG */
#define XFS_AGI_DADDR(mp) ((xfs_daddr_t)(2 << (mp)->m_sectbb_log))
diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
index a600c03..9d380f9 100644
--- a/libxfs/xfs_ialloc.c
+++ b/libxfs/xfs_ialloc.c
@@ -2451,6 +2451,7 @@ xfs_ialloc_log_agi(
offsetof(xfs_agi_t, agi_unlinked),
offsetof(xfs_agi_t, agi_free_root),
offsetof(xfs_agi_t, agi_free_level),
+ offsetof(xfs_agi_t, agi_iblocks),
sizeof(xfs_agi_t)
};
#ifdef DEBUG
diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c
index 716a81f..9db87e9 100644
--- a/libxfs/xfs_ialloc_btree.c
+++ b/libxfs/xfs_ialloc_btree.c
@@ -68,6 +68,25 @@ xfs_finobt_set_root(
XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL);
}
+/* Update the inode btree block counter for this btree. */
+static inline void
+xfs_inobt_mod_blockcount(
+ struct xfs_btree_cur *cur,
+ int howmuch)
+{
+ struct xfs_buf *agbp = cur->bc_private.a.agbp;
+ struct xfs_agi *agi = agbp->b_addr;
+
+ if (!xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb))
+ return;
+
+ if (cur->bc_btnum == XFS_BTNUM_FINO)
+ be32_add_cpu(&agi->agi_fblocks, howmuch);
+ else if (cur->bc_btnum == XFS_BTNUM_INO)
+ be32_add_cpu(&agi->agi_iblocks, howmuch);
+ xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_IBLOCKS);
+}
+
STATIC int
__xfs_inobt_alloc_block(
struct xfs_btree_cur *cur,
@@ -103,6 +122,7 @@ __xfs_inobt_alloc_block(
new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno));
*stat = 1;
+ xfs_inobt_mod_blockcount(cur, 1);
return 0;
}
@@ -135,6 +155,7 @@ __xfs_inobt_free_block(
struct xfs_buf *bp,
enum xfs_ag_resv_type resv)
{
+ xfs_inobt_mod_blockcount(cur, -1);
return xfs_free_extent(cur->bc_tp,
XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
&XFS_RMAP_OINFO_INOBT, resv);
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 16819d8..992224d 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -3588,6 +3588,11 @@ initialise_ag_headers(
platform_uuid_copy(&agi->agi_uuid, &sbp->sb_uuid);
for (c = 0; c < XFS_AGI_UNLINKED_BUCKETS; c++)
agi->agi_unlinked[c] = cpu_to_be32(NULLAGINO);
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+ agi->agi_iblocks = cpu_to_be32(1);
+ if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ agi->agi_fblocks = cpu_to_be32(1);
+ }
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
/*

View File

@ -0,0 +1,61 @@
From eb2c6897f36d560f84ed5124b246f2759c470f11 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 10 Nov 2020 15:11:09 -0500
Subject: [PATCH] xfs: use the finobt block counts to speed up mount times
Source kernel commit: 1ac35f061af011442eeb731632f6daae991ecf7c
Now that we have reliable finobt block counts, use them to speed up the
per-AG block reservation calculations at mount time.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c
index 9db87e9..b1adc80 100644
--- a/libxfs/xfs_ialloc_btree.c
+++ b/libxfs/xfs_ialloc_btree.c
@@ -593,6 +593,28 @@ xfs_inobt_count_blocks(
return error;
}
+/* Read finobt block count from AGI header. */
+static int
+xfs_finobt_read_blocks(
+ struct xfs_mount *mp,
+ struct xfs_trans *tp,
+ xfs_agnumber_t agno,
+ xfs_extlen_t *tree_blocks)
+{
+ struct xfs_buf *agbp;
+ struct xfs_agi *agi;
+ int error;
+
+ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
+ if (error)
+ return error;
+
+ agi = agbp->b_addr;
+ *tree_blocks = be32_to_cpu(agi->agi_fblocks);
+ xfs_trans_brelse(tp, agbp);
+ return 0;
+}
+
/*
* Figure out how many blocks to reserve and how many are used by this btree.
*/
@@ -610,7 +632,11 @@ xfs_finobt_calc_reserves(
if (!xfs_sb_version_hasfinobt(&mp->m_sb))
return 0;
- error = xfs_inobt_count_blocks(mp, tp, agno, XFS_BTNUM_FINO, &tree_len);
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb))
+ error = xfs_finobt_read_blocks(mp, tp, agno, &tree_len);
+ else
+ error = xfs_inobt_count_blocks(mp, tp, agno, XFS_BTNUM_FINO,
+ &tree_len);
if (error)
return error;

View File

@ -0,0 +1,371 @@
From e7e3beb95efd751f227a0ced4c83fc5b88582e2e Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Wed, 11 Nov 2020 20:08:14 -0500
Subject: [PATCH] xfs: widen ondisk inode timestamps to deal with y2038+
Source kernel commit: f93e5436f0ee5a85eaa3a86d2614d215873fb18b
Redesign the ondisk inode timestamps to be a simple unsigned 64-bit
counter of nanoseconds since 14 Dec 1901 (i.e. the minimum time in the
32-bit unix time epoch). This enables us to handle dates up to 2486,
which solves the y2038 problem.
sandeen: update xfs_flags2diflags2() as well, to match
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
NOTE: xfs_trans_inode.c was not brought over in this version, so code
landed in trans.c
We also do not have the pre-computed geometry, so that needs to be
explicitly added to libxfs_ialloc rather than inheriting from igeo.
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
index ddd48be..25f2eac 100644
--- a/include/xfs_inode.h
+++ b/include/xfs_inode.h
@@ -146,6 +146,11 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
}
+static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip)
+{
+ return ip->i_d.di_flags2 & XFS_DIFLAG2_BIGTIME;
+}
+
typedef struct cred {
uid_t cr_uid;
gid_t cr_gid;
diff --git a/libxfs/trans.c b/libxfs/trans.c
index db90624..54e4dd6 100644
--- a/libxfs/trans.c
+++ b/libxfs/trans.c
@@ -415,6 +415,17 @@ xfs_trans_log_inode(
tp->t_flags |= XFS_TRANS_DIRTY;
set_bit(XFS_LI_DIRTY, &ip->i_itemp->ili_item.li_flags);
+ /*
+ * If we're updating the inode core or the timestamps and it's possible
+ * to upgrade this inode to bigtime format, do so now.
+ */
+ if ((flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) &&
+ xfs_sb_version_hasbigtime(&ip->i_mount->m_sb) &&
+ !xfs_inode_has_bigtime(ip)) {
+ ip->i_d.di_flags2 |= XFS_DIFLAG2_BIGTIME;
+ flags |= XFS_ILOG_CORE;
+ }
+
/*
* Always OR in the bits from the ili_last_fields field.
* This is to coordinate with the xfs_iflush() and xfs_iflush_done()
diff --git a/libxfs/util.c b/libxfs/util.c
index 9383bb8..7a8729f 100644
--- a/libxfs/util.c
+++ b/libxfs/util.c
@@ -222,7 +222,8 @@ xfs_flags2diflags2(
unsigned int xflags)
{
uint64_t di_flags2 =
- (ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK);
+ (ip->i_d.di_flags2 & (XFS_DIFLAG2_REFLINK |
+ XFS_DIFLAG2_BIGTIME));
if (xflags & FS_XFLAG_DAX)
di_flags2 |= XFS_DIFLAG2_DAX;
@@ -317,8 +318,14 @@ libxfs_ialloc(
ASSERT(ip->i_d.di_ino == ino);
ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid));
VFS_I(ip)->i_version = 1;
- ip->i_d.di_flags2 = pip ? 0 : xfs_flags2diflags2(ip,
- fsx->fsx_xflags);
+ if (pip) {
+ ip->i_d.di_flags2 = 0;
+ if (xfs_sb_version_hasbigtime(&ip->i_mount->m_sb))
+ ip->i_d.di_flags2 |= XFS_DIFLAG2_BIGTIME;
+ } else {
+ ip->i_d.di_flags2 = xfs_flags2diflags2(ip, fsx->fsx_xflags);
+ }
+
ip->i_d.di_crtime.tv_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
ip->i_d.di_crtime.tv_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
ip->i_d.di_cowextsize = pip ? 0 : fsx->fsx_cowextsize;
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 371f5cd..b1f6219 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -466,6 +466,7 @@ xfs_sb_has_ro_compat_feature(
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
+#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
#define XFS_SB_FEAT_INCOMPAT_ALL \
(XFS_SB_FEAT_INCOMPAT_FTYPE| \
XFS_SB_FEAT_INCOMPAT_SPINODES| \
@@ -580,6 +581,12 @@ xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
#define XFS_FSB_TO_DADDR(mp,fsbno) XFS_AGB_TO_DADDR(mp, \
XFS_FSB_TO_AGNO(mp,fsbno), XFS_FSB_TO_AGBNO(mp,fsbno))
+static inline bool xfs_sb_version_hasbigtime(struct xfs_sb *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+ (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME);
+}
+
/*
* File system sector to basic block conversions.
*/
@@ -849,6 +856,13 @@ typedef struct xfs_agfl {
* Therefore, the ondisk min and max defined here can be used directly to
* constrain the incore timestamps on a Unix system. Note that we actually
* encode a __be64 value on disk.
+ *
+ * When the bigtime feature is enabled, ondisk inode timestamps become an
+ * unsigned 64-bit nanoseconds counter. This means that the bigtime inode
+ * timestamp epoch is the start of the classic timestamp range, which is
+ * Dec 31 20:45:52 UTC 1901. Because the epochs are not the same, callers
+ * /must/ use the bigtime conversion functions when encoding and decoding raw
+ * timestamps.
*/
typedef __be64 xfs_timestamp_t;
@@ -870,6 +884,50 @@ struct xfs_legacy_timestamp {
*/
#define XFS_LEGACY_TIME_MAX ((int64_t)S32_MAX)
+/*
+ * Smallest possible ondisk seconds value with bigtime timestamps. This
+ * corresponds (after conversion to a Unix timestamp) with the traditional
+ * minimum timestamp of Dec 13 20:45:52 UTC 1901.
+ */
+#define XFS_BIGTIME_TIME_MIN ((int64_t)0)
+
+/*
+ * Largest supported ondisk seconds value with bigtime timestamps. This
+ * corresponds (after conversion to a Unix timestamp) with an incore timestamp
+ * of Jul 2 20:20:24 UTC 2486.
+ *
+ * We round down the ondisk limit so that the bigtime quota and inode max
+ * timestamps will be the same.
+ */
+#define XFS_BIGTIME_TIME_MAX ((int64_t)((-1ULL / NSEC_PER_SEC) & ~0x3ULL))
+
+/*
+ * Bigtime epoch is set exactly to the minimum time value that a traditional
+ * 32-bit timestamp can represent when using the Unix epoch as a reference.
+ * Hence the Unix epoch is at a fixed offset into the supported bigtime
+ * timestamp range.
+ *
+ * The bigtime epoch also matches the minimum value an on-disk 32-bit XFS
+ * timestamp can represent so we will not lose any fidelity in converting
+ * to/from unix and bigtime timestamps.
+ *
+ * The following conversion factor converts a seconds counter from the Unix
+ * epoch to the bigtime epoch.
+ */
+#define XFS_BIGTIME_EPOCH_OFFSET (-(int64_t)S32_MIN)
+
+/* Convert a timestamp from the Unix epoch to the bigtime epoch. */
+static inline uint64_t xfs_unix_to_bigtime(time64_t unix_seconds)
+{
+ return (uint64_t)unix_seconds + XFS_BIGTIME_EPOCH_OFFSET;
+}
+
+/* Convert a timestamp from the bigtime epoch to the Unix epoch. */
+static inline time64_t xfs_bigtime_to_unix(uint64_t ondisk_seconds)
+{
+ return (time64_t)ondisk_seconds - XFS_BIGTIME_EPOCH_OFFSET;
+}
+
/*
* On-disk inode structure.
*
@@ -1096,12 +1154,22 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
#define XFS_DIFLAG2_DAX_BIT 0 /* use DAX for this inode */
#define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */
#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */
+#define XFS_DIFLAG2_BIGTIME_BIT 3 /* big timestamps */
+
#define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT)
#define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT)
#define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT)
+#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT)
#define XFS_DIFLAG2_ANY \
- (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)
+ (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \
+ XFS_DIFLAG2_BIGTIME)
+
+static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
+{
+ return dip->di_version >= 3 &&
+ (dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_BIGTIME));
+}
/*
* Inode number format:
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 4fa9852..714dba1 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -231,6 +231,7 @@ typedef struct xfs_fsop_resblks {
#define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */
#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */
#define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */
+#define XFS_FSOP_GEOM_FLAGS_BIGTIME 0x200000 /* 64-bit nsec timestamps */
/*
* Minimum and maximum sizes need for growth checks.
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index d8831a1..8cd16bf 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -195,14 +195,29 @@ xfs_imap_to_bp(
return 0;
}
+static inline struct timespec64 xfs_inode_decode_bigtime(uint64_t ts)
+{
+ struct timespec64 tv;
+ uint32_t n;
+
+ tv.tv_sec = xfs_bigtime_to_unix(div_u64_rem(ts, NSEC_PER_SEC, &n));
+ tv.tv_nsec = n;
+
+ return tv;
+}
+
/* Convert an ondisk timestamp to an incore timestamp. */
struct timespec64
xfs_inode_from_disk_ts(
+ struct xfs_dinode *dip,
const xfs_timestamp_t ts)
{
struct timespec64 tv;
struct xfs_legacy_timestamp *lts;
+ if (xfs_dinode_has_bigtime(dip))
+ return xfs_inode_decode_bigtime(be64_to_cpu(ts));
+
lts = (struct xfs_legacy_timestamp *)&ts;
tv.tv_sec = (int)be32_to_cpu(lts->t_sec);
tv.tv_nsec = (int)be32_to_cpu(lts->t_nsec);
@@ -246,9 +261,9 @@ xfs_inode_from_disk(
* a time before epoch is converted to a time long after epoch
* on 64 bit systems.
*/
- inode->i_atime = xfs_inode_from_disk_ts(from->di_atime);
- inode->i_mtime = xfs_inode_from_disk_ts(from->di_mtime);
- inode->i_ctime = xfs_inode_from_disk_ts(from->di_ctime);
+ inode->i_atime = xfs_inode_from_disk_ts(from, from->di_atime);
+ inode->i_mtime = xfs_inode_from_disk_ts(from, from->di_mtime);
+ inode->i_ctime = xfs_inode_from_disk_ts(from, from->di_ctime);
inode->i_generation = be32_to_cpu(from->di_gen);
inode->i_mode = be16_to_cpu(from->di_mode);
@@ -267,7 +282,7 @@ xfs_inode_from_disk(
if (to->di_version == 3) {
inode_set_iversion_queried(inode,
be64_to_cpu(from->di_changecount));
- to->di_crtime = xfs_inode_from_disk_ts(from->di_crtime);
+ to->di_crtime = xfs_inode_from_disk_ts(from, from->di_crtime);
to->di_flags2 = be64_to_cpu(from->di_flags2);
to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
}
@@ -276,11 +291,15 @@ xfs_inode_from_disk(
/* Convert an incore timestamp to an ondisk timestamp. */
static inline xfs_timestamp_t
xfs_inode_to_disk_ts(
+ struct xfs_inode *ip,
const struct timespec64 tv)
{
struct xfs_legacy_timestamp *lts;
xfs_timestamp_t ts;
+ if (xfs_inode_has_bigtime(ip))
+ return cpu_to_be64(xfs_inode_encode_bigtime(tv));
+
lts = (struct xfs_legacy_timestamp *)&ts;
lts->t_sec = cpu_to_be32(tv.tv_sec);
lts->t_nsec = cpu_to_be32(tv.tv_nsec);
@@ -308,9 +327,9 @@ xfs_inode_to_disk(
to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
memset(to->di_pad, 0, sizeof(to->di_pad));
- to->di_atime = xfs_inode_to_disk_ts(inode->i_atime);
- to->di_mtime = xfs_inode_to_disk_ts(inode->i_mtime);
- to->di_ctime = xfs_inode_to_disk_ts(inode->i_ctime);
+ 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);
to->di_nlink = cpu_to_be32(inode->i_nlink);
to->di_gen = cpu_to_be32(inode->i_generation);
to->di_mode = cpu_to_be16(inode->i_mode);
@@ -328,7 +347,7 @@ xfs_inode_to_disk(
if (from->di_version == 3) {
to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
- to->di_crtime = xfs_inode_to_disk_ts(from->di_crtime);
+ to->di_crtime = xfs_inode_to_disk_ts(ip, from->di_crtime);
to->di_flags2 = cpu_to_be64(from->di_flags2);
to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
to->di_ino = cpu_to_be64(ip->i_ino);
@@ -547,6 +566,11 @@ xfs_dinode_verify(
if (fa)
return fa;
+ /* bigtime iflag can only happen on bigtime filesystems */
+ if (xfs_dinode_has_bigtime(dip) &&
+ !xfs_sb_version_hasbigtime(&mp->m_sb))
+ return __this_address;
+
return NULL;
}
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
index 6147f42..2b91e60 100644
--- a/libxfs/xfs_inode_buf.h
+++ b/libxfs/xfs_inode_buf.h
@@ -40,6 +40,11 @@ struct xfs_icdinode {
struct timespec64 di_crtime; /* time created */
};
+static inline bool xfs_icdinode_has_bigtime(const struct xfs_icdinode *icd)
+{
+ return icd->di_flags2 & XFS_DIFLAG2_BIGTIME;
+}
+
/*
* Inode location information. Stored in the inode and passed to
* xfs_imap_to_bp() to get a buffer and dinode for a given inode.
@@ -76,6 +81,12 @@ xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp,
uint32_t cowextsize, uint16_t mode, uint16_t flags,
uint64_t flags2);
-struct timespec64 xfs_inode_from_disk_ts(const xfs_timestamp_t ts);
+static inline uint64_t xfs_inode_encode_bigtime(struct timespec64 tv)
+{
+ return xfs_unix_to_bigtime(tv.tv_sec) * NSEC_PER_SEC + tv.tv_nsec;
+}
+
+struct timespec64 xfs_inode_from_disk_ts(struct xfs_dinode *dip,
+ const xfs_timestamp_t ts);
#endif /* __XFS_INODE_BUF_H__ */
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index cee77a6..d11545b 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -1124,6 +1124,8 @@ xfs_fs_geometry(
geo->flags |= XFS_FSOP_GEOM_FLAGS_RMAPBT;
if (xfs_sb_version_hasreflink(sbp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_REFLINK;
+ if (xfs_sb_version_hasbigtime(sbp))
+ geo->flags |= XFS_FSOP_GEOM_FLAGS_BIGTIME;
if (xfs_sb_version_hassector(sbp))
geo->logsectsize = sbp->sb_logsectsize;
else

View File

@ -0,0 +1,170 @@
From 06963ef0d4ff9a6736f699d1ca8ef5a0c194799b Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Thu, 12 Nov 2020 16:49:42 -0500
Subject: [PATCH] xfs: widen ondisk quota expiration timestamps to handle
y2038+
Source kernel commit: 4ea1ff3b49681af45a4a8c14baf7f0b3d11aa74a
Enable the bigtime feature for quota timers. We decrease the accuracy
of the timers to ~4s in exchange for being able to set timers up to the
bigtime maximum.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
NOTE: Again, slightly different macro names due to lack of the
quota type/flags split.
diff --git a/include/xfs_mount.h b/include/xfs_mount.h
index 8651d6a..beb2328 100644
--- a/include/xfs_mount.h
+++ b/include/xfs_mount.h
@@ -202,4 +202,8 @@ extern xfs_mount_t *libxfs_mount (xfs_mount_t *, xfs_sb_t *,
extern void libxfs_umount (xfs_mount_t *);
extern void libxfs_rtmount_destroy (xfs_mount_t *);
+/* Dummy xfs_dquot so that libxfs compiles. */
+struct xfs_dquot {
+ int q_type;
+};
#endif /* __XFS_MOUNT_H__ */
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
index 963f8ea..db93dda 100644
--- a/libxfs/xfs_dquot_buf.c
+++ b/libxfs/xfs_dquot_buf.c
@@ -69,6 +69,13 @@ xfs_dquot_verify(
ddq_type != XFS_DQ_GROUP)
return __this_address;
+ if ((ddq->d_flags & XFS_DQ_BIGTIME) &&
+ !xfs_sb_version_hasbigtime(&mp->m_sb))
+ return __this_address;
+
+ if ((ddq->d_flags & XFS_DQ_BIGTIME) && !ddq->d_id)
+ return __this_address;
+
if (id != -1 && id != be32_to_cpu(ddq->d_id))
return __this_address;
@@ -293,7 +300,12 @@ xfs_dquot_from_disk_ts(
struct xfs_disk_dquot *ddq,
__be32 dtimer)
{
- return be32_to_cpu(dtimer);
+ uint32_t t = be32_to_cpu(dtimer);
+
+ if (t != 0 && (ddq->d_flags & XFS_DQ_BIGTIME))
+ return xfs_dq_bigtime_to_unix(t);
+
+ return t;
}
/* Convert an incore timer value into an on-disk timer value. */
@@ -302,5 +314,10 @@ xfs_dquot_to_disk_ts(
struct xfs_dquot *dqp,
time64_t timer)
{
- return cpu_to_be32(timer);
+ uint32_t t = timer;
+
+ if (timer != 0 && (dqp->q_type & XFS_DQ_BIGTIME))
+ t = xfs_dq_unix_to_bigtime(timer);
+
+ return cpu_to_be32(t);
}
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index b1f6219..9ba65e5 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1263,6 +1263,10 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
* ondisk min and max defined here can be used directly to constrain the incore
* quota expiration timestamps on a Unix system.
*
+ * When bigtime is enabled, we trade two bits of precision to expand the
+ * expiration timeout range to match that of big inode timestamps. The min and
+ * max recorded here are the on-disk limits, not a Unix timestamp.
+ *
* The grace period for each quota type is stored in the root dquot (id = 0)
* and is applied to a non-root dquot when it exceeds the soft or hard limits.
* The length of quota grace periods are unsigned 32-bit quantities measured in
@@ -1281,6 +1285,48 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
*/
#define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX)
+/*
+ * Smallest possible ondisk quota expiration value with bigtime timestamps.
+ * This corresponds (after conversion to a Unix timestamp) with the incore
+ * expiration of Jan 1 00:00:04 UTC 1970.
+ */
+#define XFS_DQ_BIGTIME_EXPIRY_MIN (XFS_DQ_LEGACY_EXPIRY_MIN)
+
+/*
+ * Largest supported ondisk quota expiration value with bigtime timestamps.
+ * This corresponds (after conversion to a Unix timestamp) with an incore
+ * expiration of Jul 2 20:20:24 UTC 2486.
+ *
+ * The ondisk field supports values up to -1U, which corresponds to an incore
+ * expiration in 2514. This is beyond the maximum the bigtime inode timestamp,
+ * so we cap the maximum bigtime quota expiration to the max inode timestamp.
+ */
+#define XFS_DQ_BIGTIME_EXPIRY_MAX ((int64_t)4074815106U)
+
+/*
+ * The following conversion factors assist in converting a quota expiration
+ * timestamp between the incore and ondisk formats.
+ */
+#define XFS_DQ_BIGTIME_SHIFT (2)
+#define XFS_DQ_BIGTIME_SLACK ((int64_t)(1ULL << XFS_DQ_BIGTIME_SHIFT) - 1)
+
+/* Convert an incore quota expiration timestamp to an ondisk bigtime value. */
+static inline uint32_t xfs_dq_unix_to_bigtime(time64_t unix_seconds)
+{
+ /*
+ * Round the expiration timestamp up to the nearest bigtime timestamp
+ * that we can store, to give users the most time to fix problems.
+ */
+ return ((uint64_t)unix_seconds + XFS_DQ_BIGTIME_SLACK) >>
+ XFS_DQ_BIGTIME_SHIFT;
+}
+
+/* Convert an ondisk bigtime quota expiration value to an incore timestamp. */
+static inline time64_t xfs_dq_bigtime_to_unix(uint32_t ondisk_seconds)
+{
+ return (time64_t)ondisk_seconds << XFS_DQ_BIGTIME_SHIFT;
+}
+
/*
* Default quota grace periods, ranging from zero (use the compiled defaults)
* to ~136 years. These are applied to a non-root dquot that has exceeded
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
index 2f61cd3..70d89cc 100644
--- a/libxfs/xfs_quota_defs.h
+++ b/libxfs/xfs_quota_defs.h
@@ -28,17 +28,20 @@ typedef uint16_t xfs_qwarncnt_t;
#define XFS_DQ_GROUP 0x0004 /* a group quota */
#define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */
#define XFS_DQ_FREEING 0x0010 /* dquot is being torn down */
+#define XFS_DQ_BIGTIME 0x0080 /* large expiry timestamps */
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
-#define XFS_DQTYPE_ANY (XFS_DQ_ALLTYPES)
+#define XFS_DQTYPE_ANY (XFS_DQ_ALLTYPES | \
+ XFS_DQ_BIGTIME)
#define XFS_DQ_FLAGS \
{ XFS_DQ_USER, "USER" }, \
{ XFS_DQ_PROJ, "PROJ" }, \
{ XFS_DQ_GROUP, "GROUP" }, \
{ XFS_DQ_DIRTY, "DIRTY" }, \
- { XFS_DQ_FREEING, "FREEING" }
+ { XFS_DQ_FREEING, "FREEING" }, \
+ { XFS_DQ_BIGTIME, "BIGTIME" }
/*
* We have the possibility of all three quota types being active at once, and

View File

@ -0,0 +1,122 @@
From a9a32fcb9176c82aed6d85f209e7279b76c8b55f Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] xfs_db: refactor quota timer printing
Introduce type-specific printing functions to xfs_db to print a quota
timer instead of printing a raw int32 value. This is needed to stay
ahead of changes that we're going to make to the quota timer format in
the following patches.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/db/dquot.c b/db/dquot.c
index dd9e83f..5c82456 100644
--- a/db/dquot.c
+++ b/db/dquot.c
@@ -60,8 +60,8 @@ 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_QTIMER, OI(DOFF(itimer)), C1, 0, TYP_NONE },
+ { "btimer", FLDT_QTIMER, OI(DOFF(btimer)), C1, 0, 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 +70,7 @@ 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_QTIMER, OI(DOFF(rtbtimer)), C1, 0, 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 a187a72..770acda 100644
--- a/db/field.c
+++ b/db/field.c
@@ -351,6 +351,8 @@ const ftattr_t ftattrtab[] = {
FTARG_SIGNED, NULL, NULL },
{ FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds,
SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds },
+ { FLDT_QTIMER, "qtimer", fp_qtimer, 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 1506537..387c189 100644
--- a/db/field.h
+++ b/db/field.h
@@ -170,6 +170,7 @@ typedef enum fldt {
FLDT_TIME,
FLDT_TIMESTAMP,
+ FLDT_QTIMER,
FLDT_UINT1,
FLDT_UINT16D,
FLDT_UINT16O,
diff --git a/db/fprint.c b/db/fprint.c
index 6e72bf0..72ed55f 100644
--- a/db/fprint.c
+++ b/db/fprint.c
@@ -180,6 +180,40 @@ fp_nsec(
return 1;
}
+int
+fp_qtimer(
+ void *obj,
+ int bit,
+ int count,
+ char *fmtstr,
+ int size,
+ int arg,
+ int base,
+ int array)
+{
+ uint32_t sec;
+ __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);
+ sec = be32_to_cpu(*t);
+
+ dbprintf("%u", sec);
+
+ if (i < count - 1)
+ dbprintf(" ");
+ }
+ return 1;
+}
+
/*ARGSUSED*/
int
fp_uuid(
diff --git a/db/fprint.h b/db/fprint.h
index bfeed15..a1ea935 100644
--- a/db/fprint.h
+++ b/db/fprint.h
@@ -17,6 +17,8 @@ extern int fp_time(void *obj, int bit, int count, char *fmtstr, int size,
int arg, int base, int array);
extern int fp_nsec(void *obj, int bit, int count, char *fmtstr, int size,
int arg, int base, int array);
+extern int fp_qtimer(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,

View File

@ -0,0 +1,176 @@
From 300422226c423222e78d82d54b09d0ae27c7d4af Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] xfs_db: refactor timestamp printing
Introduce type-specific printing functions to xfs_db to print an
xfs_timestamp instead of open-coding the timestamp decoding. This is
needed to stay ahead of changes that we're going to make to
xfs_timestamp_t in the following patches.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/db/field.c b/db/field.c
index 4a45c66..a187a72 100644
--- a/db/field.c
+++ b/db/field.c
@@ -334,8 +334,8 @@ const ftattr_t ftattrtab[] = {
FTARG_SIGNED, NULL, NULL },
{ FLDT_INT8D, "int8d", fp_num, "%d", SI(bitsz(int8_t)), FTARG_SIGNED,
NULL, NULL },
- { FLDT_NSEC, "nsec", fp_num, "%09d", SI(bitsz(int32_t)), FTARG_SIGNED,
- NULL, NULL },
+ { FLDT_NSEC, "nsec", fp_nsec, NULL, SI(bitsz(xfs_timestamp_t)),
+ FTARG_SIGNED, NULL, NULL },
{ FLDT_QCNT, "qcnt", fp_num, "%llu", SI(bitsz(xfs_qcnt_t)), 0, NULL,
NULL },
{ FLDT_QWARNCNT, "qwarncnt", fp_num, "%u", SI(bitsz(xfs_qwarncnt_t)), 0,
@@ -347,10 +347,10 @@ const ftattr_t ftattrtab[] = {
{ FLDT_SYMLINK_CRC, "symlink", NULL, (char *)symlink_crc_flds,
symlink_size, FTARG_SIZE, NULL, symlink_crc_flds },
- { FLDT_TIME, "time", fp_time, NULL, SI(bitsz(int32_t)), FTARG_SIGNED,
- NULL, NULL },
+ { FLDT_TIME, "time", fp_time, NULL, SI(bitsz(xfs_timestamp_t)),
+ FTARG_SIGNED, NULL, NULL },
{ FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds,
- SI(bitsz(struct xfs_legacy_timestamp)), 0, NULL, timestamp_flds },
+ SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds },
{ 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/fprint.c b/db/fprint.c
index c9d07e1..6e72bf0 100644
--- a/db/fprint.c
+++ b/db/fprint.c
@@ -112,22 +112,21 @@ fp_sarray(
return 1;
}
-/*ARGSUSED*/
int
fp_time(
- void *obj,
- int bit,
- int count,
- char *fmtstr,
- int size,
- int arg,
- int base,
- int array)
+ void *obj,
+ int bit,
+ int count,
+ char *fmtstr,
+ int size,
+ int arg,
+ int base,
+ int array)
{
- int bitpos;
- char *c;
- int i;
- time_t t;
+ struct timespec64 tv;
+ xfs_timestamp_t *ts;
+ int bitpos;
+ int i;
ASSERT(bitoffs(bit) == 0);
for (i = 0, bitpos = bit;
@@ -135,10 +134,46 @@ fp_time(
i++, bitpos += size) {
if (array)
dbprintf("%d:", i + base);
- t = (time_t)getbitval((char *)obj + byteize(bitpos), 0,
- sizeof(int32_t) * 8, BVSIGNED);
- c = ctime(&t);
- dbprintf("%24.24s", c);
+
+ ts = obj + byteize(bitpos);
+ tv = libxfs_inode_from_disk_ts(obj, *ts);
+
+ dbprintf("%24.24s", tv.tv_sec);
+
+ if (i < count - 1)
+ dbprintf(" ");
+ }
+ return 1;
+}
+
+int
+fp_nsec(
+ void *obj,
+ int bit,
+ int count,
+ char *fmtstr,
+ int size,
+ int arg,
+ int base,
+ int array)
+{
+ struct timespec64 tv;
+ xfs_timestamp_t *ts;
+ 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);
+
+ ts = obj + byteize(bitpos);
+ tv = libxfs_inode_from_disk_ts(obj, *ts);
+
+ dbprintf("%u", tv.tv_nsec);
+
if (i < count - 1)
dbprintf(" ");
}
diff --git a/db/fprint.h b/db/fprint.h
index c958dca..bfeed15 100644
--- a/db/fprint.h
+++ b/db/fprint.h
@@ -15,6 +15,8 @@ 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_nsec(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 b308538..bbfee74 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -176,10 +176,9 @@ const field_t inode_v3_flds[] = {
};
-#define TOFF(f) bitize(offsetof(struct xfs_legacy_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(0), C1, 0, TYP_NONE },
+ { "nsec", FLDT_NSEC, OI(0), C1, 0, TYP_NONE },
{ NULL }
};
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index f4f7626..00f367e 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -89,6 +89,7 @@
#define xfs_da_get_buf libxfs_da_get_buf
#define xfs_inode_from_disk libxfs_inode_from_disk
+#define xfs_inode_from_disk_ts libxfs_inode_from_disk_ts
#define xfs_inode_to_disk libxfs_inode_to_disk
#define xfs_dinode_calc_crc libxfs_dinode_calc_crc
#define xfs_idata_realloc libxfs_idata_realloc

View File

@ -0,0 +1,122 @@
From 344f38a9e5d0f938dae337c8c769853e6368d480 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] xfs_db: report bigtime format timestamps
Report the large format timestamps in a human-readable manner if it is
possible to do so without loss of information.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/db/fprint.c b/db/fprint.c
index 72ed55f..65accfd 100644
--- a/db/fprint.c
+++ b/db/fprint.c
@@ -112,6 +112,35 @@ fp_sarray(
return 1;
}
+static void
+fp_time64(
+ time64_t sec)
+{
+ time_t tt = sec;
+ time64_t tt_sec = tt;
+ char *c;
+
+ /*
+ * Stupid time_t shenanigans -- POSIX.1-2017 only requires that this
+ * type represent a time in seconds. Since we have no idea if our
+ * time64_t filesystem timestamps can actually be represented by the C
+ * library, we resort to converting the input value from time64_t to
+ * time_t and back to time64_t to check for information loss. If so,
+ * we print the raw value; otherwise we print a human-readable value.
+ */
+ if (tt_sec != sec)
+ goto raw;
+
+ c = ctime(&tt);
+ if (!c)
+ goto raw;
+
+ dbprintf("%24.24s", c);
+ return;
+raw:
+ dbprintf("%lld", sec);
+}
+
int
fp_time(
void *obj,
@@ -138,7 +167,7 @@ fp_time(
ts = obj + byteize(bitpos);
tv = libxfs_inode_from_disk_ts(obj, *ts);
- dbprintf("%24.24s", tv.tv_sec);
+ fp_time64(tv.tv_sec);
if (i < count - 1)
dbprintf(" ");
@@ -191,7 +220,8 @@ fp_qtimer(
int base,
int array)
{
- uint32_t sec;
+ struct xfs_disk_dquot *ddq = obj;
+ time64_t sec;
__be32 *t;
int bitpos;
int i;
@@ -204,9 +234,16 @@ fp_qtimer(
dbprintf("%d:", i + base);
t = obj + byteize(bitpos);
- sec = be32_to_cpu(*t);
+ sec = libxfs_dquot_from_disk_ts(ddq, *t);
- dbprintf("%u", sec);
+ /*
+ * 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 || sec == 0)
+ dbprintf("%lld", sec);
+ else
+ fp_time64(sec);
if (i < count - 1)
dbprintf(" ");
diff --git a/db/inode.c b/db/inode.c
index bbfee74..37c7dc0 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -172,10 +172,12 @@ const field_t inode_v3_flds[] = {
{ "cowextsz", FLDT_UINT1,
OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_COWEXTSIZE_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 }
};
-
const field_t timestamp_flds[] = {
{ "sec", FLDT_TIME, OI(0), C1, 0, TYP_NONE },
{ "nsec", FLDT_NSEC, OI(0), C1, 0, TYP_NONE },
diff --git a/db/sb.c b/db/sb.c
index d63fc71..109fdc3 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -689,6 +689,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;
}

View File

@ -0,0 +1,39 @@
From 13b8917251601e06660ed6ebe6bdeafa4c431ca3 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] xfs_db: support displaying inode btree block counts in AGI
header
Fix up xfs_db to support displaying the btree block counts.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/db/agi.c b/db/agi.c
index bf21b2d..cfb4f7b 100644
--- a/db/agi.c
+++ b/db/agi.c
@@ -48,6 +48,8 @@ const field_t agi_flds[] = {
{ "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
{ "free_root", FLDT_AGBLOCK, OI(OFF(free_root)), C1, 0, TYP_FINOBT },
{ "free_level", FLDT_UINT32D, OI(OFF(free_level)), C1, 0, TYP_NONE },
+ { "ino_blocks", FLDT_UINT32D, OI(OFF(iblocks)), C1, 0, TYP_NONE },
+ { "fino_blocks", FLDT_UINT32D, OI(OFF(fblocks)), C1, 0, TYP_NONE },
{ NULL }
};
diff --git a/db/sb.c b/db/sb.c
index 5059b26..d63fc71 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -687,6 +687,8 @@ version_string(
strcat(s, ",RMAPBT");
if (xfs_sb_version_hasreflink(sbp))
strcat(s, ",REFLINK");
+ if (xfs_sb_version_hasinobtcounts(sbp))
+ strcat(s, ",INOBTCNT");
return s;
}

View File

@ -0,0 +1,245 @@
From 4893718570dac172f639cc5e8687e782c4f759ee Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] xfs_db: support printing time limits
Support printing the minimum and maxium timestamp limits on this
filesystem.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/db/Makefile b/db/Makefile
index 8fecfc1..68ab659 100644
--- a/db/Makefile
+++ b/db/Makefile
@@ -14,7 +14,7 @@ HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \
io.h logformat.h malloc.h metadump.h output.h print.h quit.h sb.h \
sig.h strvec.h text.h type.h write.h attrset.h symlink.h fsmap.h \
fuzz.h
-CFILES = $(HFILES:.h=.c) btdump.c info.c
+CFILES = $(HFILES:.h=.c) btdump.c info.c timelimit.c
LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh
LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
diff --git a/db/command.c b/db/command.c
index c7c5234..73b06a7 100644
--- a/db/command.c
+++ b/db/command.c
@@ -139,4 +139,5 @@ init_commands(void)
write_init();
dquot_init();
fuzz_init();
+ timelimit_init();
}
diff --git a/db/command.h b/db/command.h
index eacfd46..1a9b4d2 100644
--- a/db/command.h
+++ b/db/command.h
@@ -30,3 +30,4 @@ extern void init_commands(void);
extern void btdump_init(void);
extern void info_init(void);
+extern void timelimit_init(void);
diff --git a/db/timelimit.c b/db/timelimit.c
new file mode 100644
index 0000000..53a0a39
--- /dev/null
+++ b/db/timelimit.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Oracle. All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#include "libxfs.h"
+#include "command.h"
+#include "output.h"
+#include "init.h"
+
+enum show_what {
+ SHOW_AUTO,
+ SHOW_CLASSIC,
+ SHOW_BIGTIME,
+};
+
+
+enum print_how {
+ PRINT_RAW,
+ PRINT_PRETTY,
+ PRINT_COMPACT,
+};
+
+static void
+show_limit(
+ const char *tag,
+ int64_t limit,
+ enum print_how how)
+{
+ if (how == PRINT_COMPACT) {
+ dbprintf("%" PRId64 " ", limit);
+ return;
+ }
+
+ if (how == PRINT_PRETTY && limit <= LONG_MAX && limit >= LONG_MIN) {
+ time_t tt = limit;
+ char *c;
+
+ c = ctime(&tt);
+ if (c) {
+ dbprintf("%s = %24.24s\n", tag, c);
+ return;
+ }
+ }
+
+ dbprintf("%s = %" PRId64 "\n", tag, limit);
+}
+
+static void
+show_limits(
+ enum show_what whatkind,
+ enum print_how how)
+{
+ enum print_how grace_how = how;
+
+ switch (whatkind) {
+ case SHOW_AUTO:
+ /* should never get here */
+ break;
+ case SHOW_CLASSIC:
+ show_limit("time.min", XFS_LEGACY_TIME_MIN, how);
+ show_limit("time.max", XFS_LEGACY_TIME_MAX, how);
+ show_limit("dqtimer.min", XFS_DQ_LEGACY_EXPIRY_MIN, how);
+ show_limit("dqtimer.max", XFS_DQ_LEGACY_EXPIRY_MAX, how);
+ break;
+ case SHOW_BIGTIME:
+ show_limit("time.min",
+ xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MIN), how);
+ show_limit("time.max",
+ xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MAX), how);
+ show_limit("dqtimer.min",
+ xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MIN),
+ how);
+ show_limit("dqtimer.max",
+ xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MAX),
+ how);
+ break;
+ }
+
+ /* grace periods are always integers */
+ if (grace_how != PRINT_COMPACT)
+ grace_how = PRINT_RAW;
+ show_limit("dqgrace.min", XFS_DQ_GRACE_MIN, grace_how);
+ show_limit("dqgrace.min", XFS_DQ_GRACE_MAX, grace_how);
+
+ if (how == PRINT_COMPACT)
+ dbprintf("\n");
+}
+
+static int
+timelimit_f(
+ int argc,
+ char **argv)
+{
+ enum show_what whatkind = SHOW_AUTO;
+ enum print_how how = PRINT_RAW;
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp("--classic", argv[i]))
+ whatkind = SHOW_CLASSIC;
+ else if (!strcmp("--bigtime", argv[i]))
+ whatkind = SHOW_BIGTIME;
+ else if (!strcmp("--pretty", argv[i]))
+ how = PRINT_PRETTY;
+ else if (!strcmp("--compact", argv[i]))
+ how = PRINT_COMPACT;
+ else {
+ dbprintf(_("%s: bad option for timelimit command\n"),
+ argv[i]);
+ return 1;
+ }
+ }
+
+ if (whatkind == SHOW_AUTO) {
+ if (xfs_sb_version_hasbigtime(&mp->m_sb))
+ whatkind = SHOW_BIGTIME;
+ else
+ whatkind = SHOW_CLASSIC;
+ }
+
+ show_limits(whatkind, how);
+ return 0;
+}
+
+static void
+timelimit_help(void)
+{
+ dbprintf(_(
+"\n"
+" Print the minimum and maximum supported values for inode timestamps,\n"
+" disk quota expiration timers, and disk quota grace periods supported\n"
+" by this filesystem.\n"
+"\n"
+" Options:\n"
+" --classic -- Force printing of the classic time limits.\n"
+" --bigtime -- Force printing of the bigtime limits.\n"
+" --pretty -- Pretty-print the time limits.\n"
+" --compact -- Print the limits in a single line.\n"
+"\n"
+));
+
+}
+
+static const cmdinfo_t timelimit_cmd = {
+ .name = "timelimit",
+ .cfunc = timelimit_f,
+ .argmin = 0,
+ .argmax = -1,
+ .canpush = 0,
+ .args = N_("[--classic|--bigtime] [--pretty]"),
+ .oneline = N_("display timestamp limits"),
+ .help = timelimit_help,
+};
+
+void
+timelimit_init(void)
+{
+ add_command(&timelimit_cmd);
+}
diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
index a1ee351..f46e936 100644
--- a/man/man8/xfs_db.8
+++ b/man/man8/xfs_db.8
@@ -785,6 +785,29 @@ The possible data types are:
.BR rtsummary ", " sb ", " symlink " and " text .
See the TYPES section below for more information on these data types.
.TP
+.BI "timelimit [" OPTIONS ]
+Print the minimum and maximum supported values for inode timestamps,
+quota expiration timers, and quota grace periods supported by this
+filesystem.
+Options include:
+.RS 1.0i
+.TP 0.4i
+.B \--bigtime
+Print the time limits of an XFS filesystem with the
+.B bigtime
+feature enabled.
+.TP 0.4i
+.B \--classic
+Print the time limits of a classic XFS filesystem.
+.TP 0.4i
+.B \--compact
+Print all limits as raw values on a single line.
+.TP 0.4i
+.B \--pretty
+Print the timestamps in the current locale's date and time format instead of
+raw seconds since the Unix epoch.
+.RE
+.TP
.BI "uuid [" uuid " | " generate " | " rewrite " | " restore ]
Set the filesystem universally unique identifier (UUID).
The filesystem UUID can be used by

View File

@ -0,0 +1,199 @@
From 219285adf56da85171fa90f42714341484750856 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] xfs_quota: convert time_to_string to use time64_t
Rework the time_to_string helper to be capable of dealing with 64-bit
timestamps.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/quota/quota.c b/quota/quota.c
index 9545cc4..8ba0995 100644
--- a/quota/quota.c
+++ b/quota/quota.c
@@ -48,6 +48,7 @@ quota_mount(
uint flags)
{
fs_disk_quota_t d;
+ time64_t timer;
char *dev = mount->fs_name;
char c[8], h[8], s[8];
uint qflags;
@@ -100,6 +101,7 @@ quota_mount(
}
if (form & XFS_BLOCK_QUOTA) {
+ timer = d.d_btimer;
qflags = (flags & HUMAN_FLAG);
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
qflags |= LIMIT_FLAG;
@@ -111,16 +113,17 @@ quota_mount(
bbs_to_string(d.d_blk_softlimit, s, sizeof(s)),
bbs_to_string(d.d_blk_hardlimit, h, sizeof(h)),
d.d_bwarns,
- time_to_string(d.d_btimer, qflags));
+ time_to_string(timer, qflags));
else
fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
(unsigned long long)d.d_bcount >> 1,
(unsigned long long)d.d_blk_softlimit >> 1,
(unsigned long long)d.d_blk_hardlimit >> 1,
d.d_bwarns,
- time_to_string(d.d_btimer, qflags));
+ time_to_string(timer, qflags));
}
if (form & XFS_INODE_QUOTA) {
+ timer = d.d_itimer;
qflags = (flags & HUMAN_FLAG);
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
qflags |= LIMIT_FLAG;
@@ -132,16 +135,17 @@ quota_mount(
num_to_string(d.d_ino_softlimit, s, sizeof(s)),
num_to_string(d.d_ino_hardlimit, h, sizeof(h)),
d.d_iwarns,
- time_to_string(d.d_itimer, qflags));
+ time_to_string(timer, qflags));
else
fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
(unsigned long long)d.d_icount,
(unsigned long long)d.d_ino_softlimit,
(unsigned long long)d.d_ino_hardlimit,
d.d_iwarns,
- time_to_string(d.d_itimer, qflags));
+ time_to_string(timer, qflags));
}
if (form & XFS_RTBLOCK_QUOTA) {
+ timer = d.d_rtbtimer;
qflags = (flags & HUMAN_FLAG);
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
qflags |= LIMIT_FLAG;
@@ -153,14 +157,14 @@ quota_mount(
bbs_to_string(d.d_rtb_softlimit, s, sizeof(s)),
bbs_to_string(d.d_rtb_hardlimit, h, sizeof(h)),
d.d_rtbwarns,
- time_to_string(d.d_rtbtimer, qflags));
+ time_to_string(timer, qflags));
else
fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
(unsigned long long)d.d_rtbcount >> 1,
(unsigned long long)d.d_rtb_softlimit >> 1,
(unsigned long long)d.d_rtb_hardlimit >> 1,
d.d_rtbwarns,
- time_to_string(d.d_rtbtimer, qflags));
+ time_to_string(timer, qflags));
}
fprintf(fp, "%s\n", mount->fs_dir);
return 1;
diff --git a/quota/quota.h b/quota/quota.h
index b7f259e..13ae450 100644
--- a/quota/quota.h
+++ b/quota/quota.h
@@ -40,7 +40,7 @@ enum {
*/
extern char *type_to_string(uint __type);
extern char *form_to_string(uint __form);
-extern char *time_to_string(time_t __time, uint __flags);
+extern char *time_to_string(time64_t __time, uint __flags);
extern char *bbs_to_string(uint64_t __v, char *__c, uint __size);
extern char *num_to_string(uint64_t __v, char *__c, uint __size);
extern char *pct_to_string(uint64_t __v, uint64_t __t, char *__c, uint __s);
diff --git a/quota/report.c b/quota/report.c
index e6def91..2d5024e 100644
--- a/quota/report.c
+++ b/quota/report.c
@@ -330,6 +330,7 @@ report_mount(
uint flags)
{
fs_disk_quota_t d;
+ time64_t timer;
char *dev = mount->fs_name;
char c[8], h[8], s[8];
uint qflags;
@@ -397,6 +398,7 @@ report_mount(
}
if (form & XFS_BLOCK_QUOTA) {
+ timer = d.d_btimer;
qflags = (flags & HUMAN_FLAG);
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
qflags |= LIMIT_FLAG;
@@ -408,16 +410,17 @@ report_mount(
bbs_to_string(d.d_blk_softlimit, s, sizeof(s)),
bbs_to_string(d.d_blk_hardlimit, h, sizeof(h)),
d.d_bwarns,
- time_to_string(d.d_btimer, qflags));
+ time_to_string(timer, qflags));
else
fprintf(fp, " %10llu %10llu %10llu %02d %9s",
(unsigned long long)d.d_bcount >> 1,
(unsigned long long)d.d_blk_softlimit >> 1,
(unsigned long long)d.d_blk_hardlimit >> 1,
d.d_bwarns,
- time_to_string(d.d_btimer, qflags));
+ time_to_string(timer, qflags));
}
if (form & XFS_INODE_QUOTA) {
+ timer = d.d_itimer;
qflags = (flags & HUMAN_FLAG);
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
qflags |= LIMIT_FLAG;
@@ -429,16 +432,17 @@ report_mount(
num_to_string(d.d_ino_softlimit, s, sizeof(s)),
num_to_string(d.d_ino_hardlimit, h, sizeof(h)),
d.d_iwarns,
- time_to_string(d.d_itimer, qflags));
+ time_to_string(timer, qflags));
else
fprintf(fp, " %10llu %10llu %10llu %02d %9s",
(unsigned long long)d.d_icount,
(unsigned long long)d.d_ino_softlimit,
(unsigned long long)d.d_ino_hardlimit,
d.d_iwarns,
- time_to_string(d.d_itimer, qflags));
+ time_to_string(timer, qflags));
}
if (form & XFS_RTBLOCK_QUOTA) {
+ timer = d.d_rtbtimer;
qflags = (flags & HUMAN_FLAG);
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
qflags |= LIMIT_FLAG;
@@ -450,14 +454,14 @@ report_mount(
bbs_to_string(d.d_rtb_softlimit, s, sizeof(s)),
bbs_to_string(d.d_rtb_hardlimit, h, sizeof(h)),
d.d_rtbwarns,
- time_to_string(d.d_rtbtimer, qflags));
+ time_to_string(timer, qflags));
else
fprintf(fp, " %10llu %10llu %10llu %02d %9s",
(unsigned long long)d.d_rtbcount >> 1,
(unsigned long long)d.d_rtb_softlimit >> 1,
(unsigned long long)d.d_rtb_hardlimit >> 1,
d.d_rtbwarns,
- time_to_string(d.d_rtbtimer, qflags));
+ time_to_string(timer, qflags));
}
fputc('\n', fp);
return 1;
diff --git a/quota/util.c b/quota/util.c
index 50470ab..361d2a8 100644
--- a/quota/util.c
+++ b/quota/util.c
@@ -18,11 +18,12 @@
char *
time_to_string(
- time_t origin,
+ time64_t origin,
uint flags)
{
static char timestamp[32];
- time_t now, timer;
+ time64_t timer;
+ time_t now;
uint days, hours, minutes, seconds;
if (flags & ABSOLUTE_FLAG) {

View File

@ -0,0 +1,236 @@
From f3eb31d9c005558ce975e2806f8dc73b0ecbd7f7 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] xfs_quota: support editing and reporting quotas with bigtime
Enhance xfs_quota to detect and report grace period expirations past
2038.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/include/xqm.h b/include/xqm.h
index 8ab1907..573441d 100644
--- a/include/xqm.h
+++ b/include/xqm.h
@@ -47,7 +47,10 @@ typedef struct fs_disk_quota {
__s32 d_btimer; /* similar to above; for disk blocks */
__u16 d_iwarns; /* # warnings issued wrt num inodes */
__u16 d_bwarns; /* # warnings issued wrt disk blocks */
- __s32 d_padding2; /* padding2 - for future use */
+ __s8 d_itimer_hi; /* upper 8 bits of timer values */
+ __s8 d_btimer_hi;
+ __s8 d_rtbtimer_hi;
+ __s8 d_padding2; /* padding2 - for future use */
__u64 d_rtb_hardlimit;/* absolute limit on realtime blks */
__u64 d_rtb_softlimit;/* preferred limit on RT disk blks */
__u64 d_rtbcount; /* # realtime blocks owned */
@@ -93,6 +96,21 @@ typedef struct fs_disk_quota {
#define FS_DQ_RTBWARNS (1<<11)
#define FS_DQ_WARNS_MASK (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)
+/*
+ * Accounting values. These can only be set for filesystem with
+ * non-transactional quotas that require quotacheck(8) in userspace.
+ */
+#define FS_DQ_BCOUNT (1<<12)
+#define FS_DQ_ICOUNT (1<<13)
+#define FS_DQ_RTBCOUNT (1<<14)
+#define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT)
+
+/*
+ * Quota expiration timestamps are 40-bit signed integers, with the upper 8
+ * bits encoded in the _hi fields.
+ */
+#define FS_DQ_BIGTIME (1<<15)
+
/*
* Various flags related to quotactl(2). Only relevant to XFS filesystems.
*/
diff --git a/quota/edit.c b/quota/edit.c
index b3cad02..1a3b2d9 100644
--- a/quota/edit.c
+++ b/quota/edit.c
@@ -417,6 +417,53 @@ restore_f(
return 0;
}
+time64_t
+decode_timer(
+ const struct fs_disk_quota *d,
+ __s32 timer_lo,
+ __s8 timer_hi)
+{
+ if (d->d_fieldmask & FS_DQ_BIGTIME)
+ return (uint32_t)timer_lo | (int64_t)timer_hi << 32;
+ return timer_lo;
+}
+
+static inline void
+encode_timer(
+ const struct fs_disk_quota *d,
+ __s32 *timer_lo,
+ __s8 *timer_hi,
+ time64_t timer)
+{
+ *timer_lo = timer;
+ if (d->d_fieldmask & FS_DQ_BIGTIME)
+ *timer_hi = timer >> 32;
+ else
+ *timer_hi = 0;
+}
+
+static inline bool want_bigtime(time64_t timer)
+{
+ return timer > INT32_MAX || timer < INT32_MIN;
+}
+
+static void
+encode_timers(
+ struct fs_disk_quota *d,
+ time64_t btimer,
+ time64_t itimer,
+ time64_t rtbtimer)
+{
+ d->d_fieldmask &= ~FS_DQ_BIGTIME;
+ if (want_bigtime(btimer) || want_bigtime(itimer) ||
+ want_bigtime(rtbtimer))
+ d->d_fieldmask |= FS_DQ_BIGTIME;
+
+ encode_timer(d, &d->d_btimer, &d->d_btimer_hi, btimer);
+ encode_timer(d, &d->d_itimer, &d->d_itimer_hi, itimer);
+ encode_timer(d, &d->d_rtbtimer, &d->d_rtbtimer_hi, rtbtimer);
+}
+
static void
set_timer(
uint32_t id,
@@ -426,6 +473,7 @@ set_timer(
time64_t value)
{
struct fs_disk_quota d;
+ time64_t btimer, itimer, rtbtimer;
memset(&d, 0, sizeof(d));
@@ -446,23 +494,28 @@ set_timer(
time(&now);
+ btimer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
+ itimer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
+ rtbtimer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
+
/* Only set grace time if user is already past soft limit */
if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit)
- d.d_btimer = now + value;
+ btimer = now + value;
if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit)
- d.d_itimer = now + value;
+ itimer = now + value;
if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit)
- d.d_rtbtimer = now + value;
+ rtbtimer = now + value;
} else {
- d.d_btimer = value;
- d.d_itimer = value;
- d.d_rtbtimer = value;
+ btimer = value;
+ itimer = value;
+ rtbtimer = value;
}
d.d_version = FS_DQUOT_VERSION;
d.d_flags = type;
d.d_fieldmask = mask;
d.d_id = id;
+ encode_timers(&d, btimer, itimer, rtbtimer);
if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) {
exitcode = 1;
diff --git a/quota/quota.c b/quota/quota.c
index 8ba0995..0747ced 100644
--- a/quota/quota.c
+++ b/quota/quota.c
@@ -101,7 +101,7 @@ quota_mount(
}
if (form & XFS_BLOCK_QUOTA) {
- timer = d.d_btimer;
+ timer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
qflags = (flags & HUMAN_FLAG);
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
qflags |= LIMIT_FLAG;
@@ -123,7 +123,7 @@ quota_mount(
time_to_string(timer, qflags));
}
if (form & XFS_INODE_QUOTA) {
- timer = d.d_itimer;
+ timer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
qflags = (flags & HUMAN_FLAG);
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
qflags |= LIMIT_FLAG;
@@ -145,7 +145,7 @@ quota_mount(
time_to_string(timer, qflags));
}
if (form & XFS_RTBLOCK_QUOTA) {
- timer = d.d_rtbtimer;
+ timer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
qflags = (flags & HUMAN_FLAG);
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
qflags |= LIMIT_FLAG;
diff --git a/quota/quota.h b/quota/quota.h
index 13ae450..74eb146 100644
--- a/quota/quota.h
+++ b/quota/quota.h
@@ -3,6 +3,8 @@
* Copyright (c) 2005 Silicon Graphics, Inc.
* All Rights Reserved.
*/
+#ifndef XFS_QUOTA_QUOTA_H_
+#define XFS_QUOTA_QUOTA_H_
#include "xqm.h"
#include "path.h"
@@ -73,3 +75,8 @@ extern char *uid_to_name(uint32_t __uid);
extern char *gid_to_name(uint32_t __gid);
extern char *prid_to_name(uint32_t __prid);
extern bool isdigits_only(const char *);
+
+time64_t decode_timer(const struct fs_disk_quota *d, __s32 timer_lo,
+ __s8 timer_hi);
+
+#endif /* XFS_QUOTA_QUOTA_H_ */
diff --git a/quota/report.c b/quota/report.c
index 2d5024e..6ac5549 100644
--- a/quota/report.c
+++ b/quota/report.c
@@ -398,7 +398,7 @@ report_mount(
}
if (form & XFS_BLOCK_QUOTA) {
- timer = d.d_btimer;
+ timer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
qflags = (flags & HUMAN_FLAG);
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
qflags |= LIMIT_FLAG;
@@ -420,7 +420,7 @@ report_mount(
time_to_string(timer, qflags));
}
if (form & XFS_INODE_QUOTA) {
- timer = d.d_itimer;
+ timer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
qflags = (flags & HUMAN_FLAG);
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
qflags |= LIMIT_FLAG;
@@ -442,7 +442,7 @@ report_mount(
time_to_string(timer, qflags));
}
if (form & XFS_RTBLOCK_QUOTA) {
- timer = d.d_rtbtimer;
+ timer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
qflags = (flags & HUMAN_FLAG);
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
qflags |= LIMIT_FLAG;

View File

@ -0,0 +1,98 @@
From 62c713cb0c7791717c0b2a663ff0cc72842fe6c7 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] xfs_repair: check inode btree block counters in AGI
Make sure that both inode btree block counters in the AGI are correct.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/repair/scan.c b/repair/scan.c
index 5b76212..086a3cd 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -1933,6 +1933,12 @@ _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
return suspect;
}
+struct ino_priv {
+ struct aghdr_cnts *agcnts;
+ uint32_t ino_blocks;
+ uint32_t fino_blocks;
+};
+
/*
* this one walks the inode btrees sucking the info there into
* the incore avl tree. We try and rescue corrupted btree records
@@ -1961,7 +1967,8 @@ scan_inobt(
void *priv,
const struct xfs_buf_ops *ops)
{
- struct aghdr_cnts *agcnts = priv;
+ struct ino_priv *ipriv = priv;
+ struct aghdr_cnts *agcnts = ipriv->agcnts;
char *name;
int i;
int numrecs;
@@ -1977,10 +1984,12 @@ scan_inobt(
case XFS_FIBT_MAGIC:
case XFS_FIBT_CRC_MAGIC:
name = "fino";
+ ipriv->fino_blocks++;
break;
case XFS_IBT_MAGIC:
case XFS_IBT_CRC_MAGIC:
name = "ino";
+ ipriv->ino_blocks++;
break;
default:
name = "(unknown)";
@@ -2320,6 +2329,9 @@ validate_agi(
xfs_agnumber_t agno,
struct aghdr_cnts *agcnts)
{
+ struct ino_priv priv = {
+ .agcnts = agcnts,
+ };
xfs_agblock_t bno;
int i;
uint32_t magic;
@@ -2329,7 +2341,7 @@ validate_agi(
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC
: XFS_IBT_MAGIC;
scan_sbtree(bno, be32_to_cpu(agi->agi_level),
- agno, 0, scan_inobt, 1, magic, agcnts,
+ agno, 0, scan_inobt, 1, magic, &priv,
&xfs_inobt_buf_ops);
} else {
do_warn(_("bad agbno %u for inobt root, agno %d\n"),
@@ -2342,7 +2354,7 @@ validate_agi(
magic = xfs_sb_version_hascrc(&mp->m_sb) ?
XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC;
scan_sbtree(bno, be32_to_cpu(agi->agi_free_level),
- agno, 0, scan_inobt, 1, magic, agcnts,
+ agno, 0, scan_inobt, 1, magic, &priv,
&xfs_inobt_buf_ops);
} else {
do_warn(_("bad agbno %u for finobt root, agno %d\n"),
@@ -2350,6 +2362,17 @@ validate_agi(
}
}
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+ if (be32_to_cpu(agi->agi_iblocks) != priv.ino_blocks)
+ do_warn(_("bad inobt block count %u, saw %u\n"),
+ be32_to_cpu(agi->agi_iblocks),
+ priv.ino_blocks);
+ if (be32_to_cpu(agi->agi_fblocks) != priv.fino_blocks)
+ do_warn(_("bad finobt block count %u, saw %u\n"),
+ be32_to_cpu(agi->agi_fblocks),
+ priv.fino_blocks);
+ }
+
if (be32_to_cpu(agi->agi_count) != agcnts->agicount) {
do_warn(_("agi_count %u, counted %u in ag %u\n"),
be32_to_cpu(agi->agi_count), agcnts->agicount, agno);

View File

@ -0,0 +1,29 @@
From 086250dc5707ee6fcfb1ee8499e7af092904a7a6 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:27 -0500
Subject: [PATCH] xfs_repair: regenerate inode btree block counters in AGI
Reset both inode btree block counters in the AGI when rebuilding the
metadata indexes.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/repair/phase5.c b/repair/phase5.c
index ad9394d..a37d672 100644
--- a/repair/phase5.c
+++ b/repair/phase5.c
@@ -1126,6 +1126,11 @@ build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs,
agi->agi_free_level = cpu_to_be32(finobt_curs->num_levels);
}
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+ agi->agi_iblocks = cpu_to_be32(btree_curs->num_tot_blocks);
+ agi->agi_fblocks = cpu_to_be32(finobt_curs->num_tot_blocks);
+ }
+
libxfs_writebuf(agi_buf, 0);
}

View File

@ -0,0 +1,81 @@
From 37c7dda1c20bfd2cc73679275bab2dd43e0ad9b8 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 20 Nov 2020 17:03:28 -0500
Subject: [PATCH] xfs_repair: support bigtime timestamp checking
Make sure that inodes don't have the bigtime flag set when the feature
is disabled, and don't check for overflows in the nanoseconds when
bigtime is enabled because that is no longer possible. Also make sure
that quotas don't have bigtime set erroneously.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
NOTE: we do not have quota repair in this version of xfsprogs
diff --git a/repair/dinode.c b/repair/dinode.c
index 0c40f2a..561603b 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -2213,11 +2213,15 @@ static void
check_nsec(
const char *name,
xfs_ino_t lino,
+ struct xfs_dinode *dip,
xfs_timestamp_t *ts,
int *dirty)
{
struct xfs_legacy_timestamp *t;
+ if (xfs_dinode_has_bigtime(dip))
+ return;
+
t = (struct xfs_legacy_timestamp *)ts;
if (be32_to_cpu(t->t_nsec) < NSEC_PER_SEC)
return;
@@ -2625,6 +2629,27 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
flags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
}
+ if (xfs_dinode_has_bigtime(dino) &&
+ !xfs_sb_version_hasbigtime(&mp->m_sb)) {
+ if (!uncertain) {
+ do_warn(
+ _("inode %" PRIu64 " is marked bigtime but file system does not support large timestamps\n"),
+ lino);
+ }
+ flags2 &= ~XFS_DIFLAG2_BIGTIME;
+
+ if (no_modify) {
+ do_warn(_("would zero timestamps.\n"));
+ } else {
+ do_warn(_("zeroing timestamps.\n"));
+ dino->di_atime = 0;
+ dino->di_mtime = 0;
+ dino->di_ctime = 0;
+ dino->di_crtime = 0;
+ *dirty = 1;
+ }
+ }
+
if (!verify_mode && flags2 != be64_to_cpu(dino->di_flags2)) {
if (!no_modify) {
do_warn(_("fixing bad flags2.\n"));
@@ -2752,11 +2777,11 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "),
}
/* nsec fields cannot be larger than 1 billion */
- check_nsec("atime", lino, &dino->di_atime, dirty);
- check_nsec("mtime", lino, &dino->di_mtime, dirty);
- check_nsec("ctime", lino, &dino->di_ctime, dirty);
+ check_nsec("atime", lino, dino, &dino->di_atime, dirty);
+ check_nsec("mtime", lino, dino, &dino->di_mtime, dirty);
+ check_nsec("ctime", lino, dino, &dino->di_ctime, dirty);
if (dino->di_version >= 3)
- check_nsec("crtime", lino, &dino->di_crtime, dirty);
+ check_nsec("crtime", lino, dino, &dino->di_crtime, dirty);
/*
* general size/consistency checks:

View File

@ -0,0 +1,38 @@
From 2c40c5a72b3cd0c4599bc84a7a8b09a496d46db3 Mon Sep 17 00:00:00 2001
From: Zorro Lang <zlang@redhat.com>
Date: Fri, 12 Feb 2021 17:23:05 -0500
Subject: [PATCH] mkfs: fix wrong inobtcount usage error output
When mkfs fails, it shows:
...
/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
inobtcnt=0|1,bigtime=0|1]\n\
...
The "inobtcnt=0|1" is wrong usage, it must be inobtcount, there's not
an alias. To avoid misadvice, fix it.
Signed-off-by: Zorro Lang <zlang@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
mkfs/xfs_mkfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 0c66255a..964299d3 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -928,7 +928,7 @@ usage( void )
fprintf(stderr, _("Usage: %s\n\
/* blocksize */ [-b size=num]\n\
/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
- inobtcnt=0|1,bigtime=0|1]\n\
+ inobtcount=0|1,bigtime=0|1]\n\
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
sectsize=num\n\
--
2.27.0

View File

@ -0,0 +1,53 @@
From dcad5c60c59bfcdf4e27dc552b94591eced0a452 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Thu, 15 Apr 2021 15:44:10 -0400
Subject: [PATCH] libfrog: report inobtcount in geometry
Report the inode btree counter feature in fs feature reports.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
libfrog/fsgeom.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index 14507668..4f1a1842 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -29,6 +29,7 @@ xfs_report_geom(
int rmapbt_enabled;
int reflink_enabled;
int bigtime_enabled;
+ int inobtcount;
isint = geo->logstart > 0;
lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0;
@@ -45,12 +46,13 @@ xfs_report_geom(
rmapbt_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_RMAPBT ? 1 : 0;
reflink_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_REFLINK ? 1 : 0;
bigtime_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_BIGTIME ? 1 : 0;
+ inobtcount = geo->flags & XFS_FSOP_GEOM_FLAGS_INOBTCNT ? 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\n"
+" =%-22s reflink=%-4u bigtime=%u inobtcount=%u\n"
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
" =%-22s sunit=%-6u swidth=%u blks\n"
"naming =version %-14u bsize=%-6u ascii-ci=%d, ftype=%d\n"
@@ -60,7 +62,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,
+ "", reflink_enabled, bigtime_enabled, inobtcount,
"", geo->blocksize, (unsigned long long)geo->datablocks,
geo->imaxpct,
"", geo->sunit, geo->swidth,
--
2.27.0

View File

@ -0,0 +1,29 @@
From d625f74125863304d111f5c6a0817a115f8e502d Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 7 May 2021 10:42:17 -0400
Subject: [PATCH] libxfs: copy crtime correctly now that it's timespec64
The incore i_mtime and di_crtime are both timespec64 now, which means
that tv_sec is a 64-bit value. Don't cast that to int32_t when we're
creating an inode, because we'll end up truncating the creation time
incorrectly, should an xfsprogs of this vintage make it to 2039. :P
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/util.c b/libxfs/util.c
index 7a8729f..fd4906f 100644
--- a/libxfs/util.c
+++ b/libxfs/util.c
@@ -326,8 +326,7 @@ libxfs_ialloc(
ip->i_d.di_flags2 = xfs_flags2diflags2(ip, fsx->fsx_xflags);
}
- ip->i_d.di_crtime.tv_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
- ip->i_d.di_crtime.tv_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
+ ip->i_d.di_crtime = VFS_I(ip)->i_mtime; /* struct copy */
ip->i_d.di_cowextsize = pip ? 0 : fsx->fsx_cowextsize;
}

View File

@ -0,0 +1,42 @@
From bdeb014153934e1d98787a9609a7532baf6a5c37 Mon Sep 17 00:00:00 2001
From: Zorro Lang <zlang@redhat.com>
Date: Tue, 6 Apr 2021 16:56:32 -0400
Subject: [PATCH] libxfs: expose inobtcount in xfs geometry
Source kernel commit: bc41fa5321f93ecbabec177f888451cfc17ad66d
As xfs supports the feature of inode btree block counters now, expose
this feature flag in xfs geometry, for userspace can check if the
inobtcnt is enabled or not.
Signed-off-by: Zorro Lang <zlang@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 714dba1..4e4a22e 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -232,6 +232,7 @@ typedef struct xfs_fsop_resblks {
#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */
#define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */
#define XFS_FSOP_GEOM_FLAGS_BIGTIME 0x200000 /* 64-bit nsec timestamps */
+#define XFS_FSOP_GEOM_FLAGS_INOBTCNT 0x400000 /* inobt btree counter */
/*
* Minimum and maximum sizes need for growth checks.
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index d11545b..6249e9a 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -1126,6 +1126,8 @@ xfs_fs_geometry(
geo->flags |= XFS_FSOP_GEOM_FLAGS_REFLINK;
if (xfs_sb_version_hasbigtime(sbp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_BIGTIME;
+ if (xfs_sb_version_hasinobtcounts(sbp))
+ geo->flags |= XFS_FSOP_GEOM_FLAGS_INOBTCNT;
if (xfs_sb_version_hassector(sbp))
geo->logsectsize = sbp->sb_logsectsize;
else

View File

@ -0,0 +1,29 @@
From 5b9782c9317b7ac0ff942dffb667bad8502f0932 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Wed, 30 Jun 2021 18:29:41 -0400
Subject: [PATCH] xfs: remove the unused xfs_icdinode_has_bigtime helper
Source kernel commit: 55f773380e922d3b975a7acb24331c76611cce30
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
index 2b91e60..8d6737b 100644
--- a/libxfs/xfs_inode_buf.h
+++ b/libxfs/xfs_inode_buf.h
@@ -40,11 +40,6 @@ struct xfs_icdinode {
struct timespec64 di_crtime; /* time created */
};
-static inline bool xfs_icdinode_has_bigtime(const struct xfs_icdinode *icd)
-{
- return icd->di_flags2 & XFS_DIFLAG2_BIGTIME;
-}
-
/*
* Inode location information. Stored in the inode and passed to
* xfs_imap_to_bp() to get a buffer and dinode for a given inode.

View File

@ -0,0 +1,46 @@
From 59301887102cc0415c8350a5e9562fe4beb083b6 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Wed, 30 Jun 2021 18:38:58 -0400
Subject: [PATCH] xfs: rename struct xfs_legacy_ictimestamp
Source kernel commit: 732de7dbdbd30df40a6d260a8da6fc5262039439
Rename struct xfs_legacy_ictimestamp to struct xfs_log_legacy_timestamp
as it is a type used for logging timestamps with no relationship to the
in-core inode.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index 85ac52c..bc26894 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -371,7 +371,7 @@ static inline int xfs_ilog_fdata(int w)
typedef uint64_t xfs_log_timestamp_t;
/* Legacy timestamp encoding format. */
-struct xfs_legacy_ictimestamp {
+struct xfs_log_legacy_timestamp {
int32_t t_sec; /* timestamp seconds */
int32_t t_nsec; /* timestamp nanoseconds */
};
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index f4fd7a8..4889e65 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -745,9 +745,9 @@ time64_t
xlog_extract_dinode_ts(
const xfs_log_timestamp_t its)
{
- struct xfs_legacy_ictimestamp *lits;
+ struct xfs_log_legacy_timestamp *lits;
- lits = (struct xfs_legacy_ictimestamp *)&its;
+ lits = (struct xfs_log_legacy_timestamp *)&its;
return (time64_t)lits->t_sec;
}

View File

@ -0,0 +1,77 @@
From 27bb0efa5e615a9162f5bc3e228bdb7c337faa4c Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Wed, 30 Jun 2021 18:38:58 -0400
Subject: [PATCH] xfs: rename xfs_ictimestamp_t
Source kernel commit: 6fc277c7c935c7e1fdee23e82da988d9d3cb6bef
Rename xfs_ictimestamp_t to xfs_log_timestamp_t as it is a type used
for logging timestamps with no relationship to the in-core inode.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index 8dc0df0..85ac52c 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -368,7 +368,7 @@ static inline int xfs_ilog_fdata(int w)
* directly mirrors the xfs_dinode structure as it must contain all the same
* information.
*/
-typedef uint64_t xfs_ictimestamp_t;
+typedef uint64_t xfs_log_timestamp_t;
/* Legacy timestamp encoding format. */
struct xfs_legacy_ictimestamp {
@@ -393,9 +393,9 @@ struct xfs_log_dinode {
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 */
- xfs_ictimestamp_t di_atime; /* time last accessed */
- xfs_ictimestamp_t di_mtime; /* time last modified */
- xfs_ictimestamp_t di_ctime; /* time created/inode modified */
+ 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 */
@@ -420,7 +420,7 @@ struct xfs_log_dinode {
uint8_t di_pad2[12]; /* more padding for future expansion */
/* fields only written to during inode creation */
- xfs_ictimestamp_t di_crtime; /* time created */
+ xfs_log_timestamp_t di_crtime; /* time created */
xfs_ino_t di_ino; /* inode number */
uuid_t di_uuid; /* UUID of the filesystem */
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index 4fad82b..f4fd7a8 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -743,7 +743,7 @@ xlog_print_trans_icreate(
time64_t
xlog_extract_dinode_ts(
- const xfs_ictimestamp_t its)
+ const xfs_log_timestamp_t its)
{
struct xfs_legacy_ictimestamp *lits;
diff --git a/logprint/logprint.h b/logprint/logprint.h
index 0061d5a..fe3831d 100644
--- a/logprint/logprint.h
+++ b/logprint/logprint.h
@@ -18,7 +18,7 @@ extern int print_no_data;
extern int print_no_print;
/* exports */
-extern time64_t xlog_extract_dinode_ts(const xfs_ictimestamp_t);
+extern time64_t xlog_extract_dinode_ts(const xfs_log_timestamp_t);
extern void xlog_print_lseek(struct xlog *, int, xfs_daddr_t, int);
extern void xfs_log_copy(struct xlog *, int, char *);

View File

View File

@ -0,0 +1,123 @@
From cb49e9a41477791af390a397c97da28da31fb81d Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Wed, 22 Jan 2020 11:29:44 -0500
Subject: [PATCH] xfs: use a struct timespec64 for the in-core crtime
Source kernel commit: 8d2d878db897d7501aaa2f72e10bb28295bb5498
struct xfs_icdinode is purely an in-memory data structure, so don't use
a log on-disk structure for it. This simplifies the code a bit, and
also reduces our include hell slightly.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
[darrick: fix a minor indenting problem in xfs_trans_ichgtime]
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/include/libxfs.h b/include/libxfs.h
index 2bdef70..731561c 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -36,6 +36,8 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
#include "xfs_cksum.h"
+#define timespec64 timespec
+
/*
* This mirrors the kernel include for xfs_buf.h - it's implicitly included in
* every files via a similar include in the kernel xfs_linux.h.
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
index 76f9ac7..e03d1cb 100644
--- a/include/xfs_inode.h
+++ b/include/xfs_inode.h
@@ -161,7 +161,6 @@ extern void libxfs_trans_ichgtime(struct xfs_trans *,
struct xfs_inode *, int);
extern int libxfs_iflush_int (struct xfs_inode *, struct xfs_buf *);
-#define timespec64 timespec
extern struct timespec64 current_time(struct inode *inode);
/* Inode Cache Interfaces */
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index b45d07e..8232f89 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -62,6 +62,8 @@ extern kmem_zone_t *xfs_buf_zone;
extern kmem_zone_t *xfs_inode_zone;
extern kmem_zone_t *xfs_trans_zone;
+#define timespec64 timespec
+
/* CRC stuff, buffer API dependent on it */
#define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l))
diff --git a/libxfs/util.c b/libxfs/util.c
index 951f7cf..9383bb8 100644
--- a/libxfs/util.c
+++ b/libxfs/util.c
@@ -170,10 +170,8 @@ libxfs_trans_ichgtime(
VFS_I(ip)->i_mtime = tv;
if (flags & XFS_ICHGTIME_CHG)
VFS_I(ip)->i_ctime = tv;
- if (flags & XFS_ICHGTIME_CREATE) {
- ip->i_d.di_crtime.t_sec = (int32_t)tv.tv_sec;
- ip->i_d.di_crtime.t_nsec = (int32_t)tv.tv_nsec;
- }
+ if (flags & XFS_ICHGTIME_CREATE)
+ ip->i_d.di_crtime = tv;
}
STATIC uint16_t
@@ -321,8 +319,8 @@ libxfs_ialloc(
VFS_I(ip)->i_version = 1;
ip->i_d.di_flags2 = pip ? 0 : xfs_flags2diflags2(ip,
fsx->fsx_xflags);
- ip->i_d.di_crtime.t_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
- ip->i_d.di_crtime.t_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
+ ip->i_d.di_crtime.tv_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
+ ip->i_d.di_crtime.tv_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
ip->i_d.di_cowextsize = pip ? 0 : fsx->fsx_cowextsize;
}
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 503990f..975f097 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -254,8 +254,8 @@ xfs_inode_from_disk(
if (to->di_version == 3) {
inode_set_iversion_queried(inode,
be64_to_cpu(from->di_changecount));
- to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec);
- to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec);
+ to->di_crtime.tv_sec = be32_to_cpu(from->di_crtime.t_sec);
+ to->di_crtime.tv_nsec = be32_to_cpu(from->di_crtime.t_nsec);
to->di_flags2 = be64_to_cpu(from->di_flags2);
to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
}
@@ -304,8 +304,8 @@ xfs_inode_to_disk(
if (from->di_version == 3) {
to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
- to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
- to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
+ to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.tv_sec);
+ to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.tv_nsec);
to->di_flags2 = cpu_to_be64(from->di_flags2);
to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
to->di_ino = cpu_to_be64(ip->i_ino);
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
index ab0f841..c9ac69c 100644
--- a/libxfs/xfs_inode_buf.h
+++ b/libxfs/xfs_inode_buf.h
@@ -37,7 +37,7 @@ struct xfs_icdinode {
uint64_t di_flags2; /* more random flags */
uint32_t di_cowextsize; /* basic cow extent size for file */
- xfs_ictimestamp_t di_crtime; /* time created */
+ struct timespec64 di_crtime; /* time created */
};
/*

View File

View File

View File

@ -0,0 +1,101 @@
From bce109af5ea0b0d6547d8cd0500560f32532e6bd Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Fri, 4 Sep 2020 16:05:20 -0400
Subject: [PATCH] xfs: drop the type parameter from xfs_dquot_verify
Source kernel commit: f9751c4ad3d17fa93773c187732f10c8a49940e3
xfs_qm_reset_dqcounts (aka quotacheck) is the only xfs_dqblk_verify
caller that actually knows the specific quota type that it's looking
for. Since everything else just pass in type==0 (including the buffer
verifier), drop the parameter and open-code the check like
xfs_dquot_from_disk already does.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
index 5e31938..a3e8ba1 100644
--- a/libxfs/xfs_dquot_buf.c
+++ b/libxfs/xfs_dquot_buf.c
@@ -37,8 +37,7 @@ xfs_failaddr_t
xfs_dquot_verify(
struct xfs_mount *mp,
xfs_disk_dquot_t *ddq,
- xfs_dqid_t id,
- uint type) /* used only during quotacheck */
+ xfs_dqid_t id) /* used only during quotacheck */
{
/*
* We can encounter an uninitialized dquot buffer for 2 reasons:
@@ -60,8 +59,6 @@ xfs_dquot_verify(
if (ddq->d_version != XFS_DQUOT_VERSION)
return __this_address;
- if (type && ddq->d_flags != type)
- return __this_address;
if (ddq->d_flags != XFS_DQ_USER &&
ddq->d_flags != XFS_DQ_PROJ &&
ddq->d_flags != XFS_DQ_GROUP)
@@ -95,14 +92,13 @@ xfs_failaddr_t
xfs_dqblk_verify(
struct xfs_mount *mp,
struct xfs_dqblk *dqb,
- xfs_dqid_t id,
- uint type) /* used only during quotacheck */
+ xfs_dqid_t id) /* used only during quotacheck */
{
if (xfs_sb_version_hascrc(&mp->m_sb) &&
!uuid_equal(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid))
return __this_address;
- return xfs_dquot_verify(mp, &dqb->dd_diskdq, id, type);
+ return xfs_dquot_verify(mp, &dqb->dd_diskdq, id);
}
/*
@@ -207,7 +203,7 @@ xfs_dquot_buf_verify(
if (i == 0)
id = be32_to_cpu(ddq->d_id);
- fa = xfs_dqblk_verify(mp, &dqb[i], id + i, 0);
+ fa = xfs_dqblk_verify(mp, &dqb[i], id + i);
if (fa) {
if (!readahead)
xfs_buf_verifier_error(bp, -EFSCORRUPTED,
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
index d3f2977..afe1ea0 100644
--- a/libxfs/xfs_quota_defs.h
+++ b/libxfs/xfs_quota_defs.h
@@ -140,9 +140,9 @@ typedef uint16_t xfs_qwarncnt_t;
#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
extern xfs_failaddr_t xfs_dquot_verify(struct xfs_mount *mp,
- struct xfs_disk_dquot *ddq, xfs_dqid_t id, uint type);
+ struct xfs_disk_dquot *ddq, xfs_dqid_t id);
extern xfs_failaddr_t xfs_dqblk_verify(struct xfs_mount *mp,
- struct xfs_dqblk *dqb, xfs_dqid_t id, uint type);
+ struct xfs_dqblk *dqb, xfs_dqid_t id);
extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
extern int xfs_dqblk_repair(struct xfs_mount *mp, struct xfs_dqblk *dqb,
xfs_dqid_t id, uint type);
diff --git a/repair/dinode.c b/repair/dinode.c
index 04c2dd5..77f78f1 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -1233,8 +1233,10 @@ _("cannot read inode %" PRIu64 ", file block %" PRIu64 ", disk block %" PRIu64 "
goto bad;
}
}
- if (libxfs_dquot_verify(mp, &dqb->dd_diskdq, dqid,
- quota_type) != NULL) {
+ if (libxfs_dquot_verify(mp, &dqb->dd_diskdq, dqid)
+ != NULL ||
+ (dqb->dd_diskdq.d_flags & XFS_DQ_ALLTYPES)
+ != quota_type) {
do_warn(_("%s: Corrupt quota for id %u. "),
quota_string, dqid);
bad_dqb = 1;

View File

@ -0,0 +1,98 @@
From 28518f7782310951019d6d28f2a6e9f9fc6e4a1c Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Date: Tue, 15 Sep 2020 15:50:35 -0400
Subject: [PATCH] xfs: improve ondisk dquot flags checking
Source kernel commit: a990f7a84edc9941956ea3c1dfb89733c80f9ad0
Create an XFS_DQTYPE_ANY mask for ondisk dquots flags, and use that to
ensure that we never accept any garbage flags when we're loading dquots.
While we're at it, restructure the quota type flag checking to use the
proper masking.
Note that I plan to add y2038 support soon, which will require a new
xfs_dqtype_t flag for extended timestamp support, hence all the work to
make the type masking work correctly.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
NOTES: I did not backport the type-vs-flags split, so some of the
naming convenstions are different here.
diff --git a/db/check.c b/db/check.c
index c3dae20..27f6639 100644
--- a/db/check.c
+++ b/db/check.c
@@ -3452,7 +3452,7 @@ process_quota(
error++;
continue;
}
- if (dqb->dd_diskdq.d_flags != exp_flags) {
+ if (dqb->dd_diskdq.d_flags & ~XFS_DQTYPE_ANY) {
if (scicb)
dbprintf(_("bad flags %#x for %s dqblk "
"%lld entry %d id %u\n"),
@@ -3461,6 +3461,17 @@ process_quota(
error++;
continue;
}
+ if ((dqb->dd_diskdq.d_flags & XFS_DQ_ALLTYPES)
+ != exp_flags) {
+ if (scicb)
+ dbprintf(_("wrong type %#x for %s dqblk "
+ "%lld entry %d id %u\n"),
+ dqb->dd_diskdq.d_flags &
+ XFS_DQ_ALLTYPES, s,
+ (xfs_fileoff_t)qbno, i, dqid);
+ error++;
+ continue;
+ }
if (be32_to_cpu(dqb->dd_diskdq.d_id) != dqid) {
if (scicb)
dbprintf(_("bad id %u for %s dqblk %lld "
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
index a3e8ba1..324f528 100644
--- a/libxfs/xfs_dquot_buf.c
+++ b/libxfs/xfs_dquot_buf.c
@@ -39,6 +39,8 @@ xfs_dquot_verify(
xfs_disk_dquot_t *ddq,
xfs_dqid_t id) /* used only during quotacheck */
{
+ __u8 ddq_type;
+
/*
* We can encounter an uninitialized dquot buffer for 2 reasons:
* 1. If we crash while deleting the quotainode(s), and those blks got
@@ -59,9 +61,12 @@ xfs_dquot_verify(
if (ddq->d_version != XFS_DQUOT_VERSION)
return __this_address;
- if (ddq->d_flags != XFS_DQ_USER &&
- ddq->d_flags != XFS_DQ_PROJ &&
- ddq->d_flags != XFS_DQ_GROUP)
+ if (ddq->d_flags & ~XFS_DQTYPE_ANY)
+ return __this_address;
+ ddq_type = ddq->d_flags & XFS_DQ_ALLTYPES;
+ if (ddq_type != XFS_DQ_USER &&
+ ddq_type != XFS_DQ_PROJ &&
+ ddq_type != XFS_DQ_GROUP)
return __this_address;
if (id != -1 && id != be32_to_cpu(ddq->d_id))
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
index afe1ea0..c69dba4 100644
--- a/libxfs/xfs_quota_defs.h
+++ b/libxfs/xfs_quota_defs.h
@@ -31,6 +31,8 @@ typedef uint16_t xfs_qwarncnt_t;
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
+#define XFS_DQTYPE_ANY (XFS_DQ_ALLTYPES)
+
#define XFS_DQ_FLAGS \
{ XFS_DQ_USER, "USER" }, \
{ XFS_DQ_PROJ, "PROJ" }, \

View File

@ -1,7 +1,7 @@
Summary: Utilities for managing the XFS filesystem
Name: xfsprogs
Version: 5.0.0
Release: 9%{?dist}
Release: 10%{?dist}
License: GPL+ and LGPLv2+
Group: System Environment/Base
URL: https://xfs.wiki.kernel.org
@ -40,6 +40,46 @@ Patch19: xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_g
Patch20: xfsprogs-5.8.0-xfs_quota-command-error-message-improvement.patch
Patch21: xfsprogs-5.8.0-xfs_quota-display-warning-limits-when-printing-quota.patch
Patch22: xfsprogs-5.8.0-xfs_quota-state-command-should-report-ugp-grace-time.patch
Patch23: xfsprogs-5.1.0-libxfs-create-current_time-helper-and-sync-xfs_trans.patch
Patch24: xfsprogs-5.5.0-xfs-use-a-struct-timespec64-for-the-in-core-crtime.patch
Patch25: xfsprogs-5.9.0-xfs-drop-the-type-parameter-from-xfs_dquot_verify.patch
Patch26: xfsprogs-5.9.0-xfs-improve-ondisk-dquot-flags-checking.patch
Patch27: xfsprogs-5.10.0-libxfs-create-a-real-struct-timespec64.patch
Patch28: xfsprogs-5.10.0-libxfs-refactor-NSEC_PER_SEC.patch
Patch29: xfsprogs-5.10.0-xfs-store-inode-btree-block-counts-in-AGI-header.patch
Patch30: xfsprogs-5.10.0-xfs-use-the-finobt-block-counts-to-speed-up-mount-ti.patch
Patch31: xfsprogs-5.10.0-xfs-explicitly-define-inode-timestamp-range.patch
Patch32: xfsprogs-5.10.0-xfs-refactor-quota-expiration-timer-modification.patch
Patch33: xfsprogs-5.10.0-xfs-refactor-default-quota-grace-period-setting-code.patch
Patch34: xfsprogs-5.10.0-xfs-refactor-quota-timestamp-coding.patch
Patch35: xfsprogs-5.10.0-xfs-move-xfs_log_dinode_to_disk-to-the-log-recovery-.patch
Patch36: xfsprogs-5.10.0-xfs-redefine-xfs_timestamp_t.patch
Patch37: xfsprogs-5.10.0-xfs-redefine-xfs_ictimestamp_t.patch
Patch38: xfsprogs-5.10.0-xfs-widen-ondisk-inode-timestamps-to-deal-with-y2038.patch
Patch39: xfsprogs-5.10.0-xfs-widen-ondisk-quota-expiration-timestamps-to-hand.patch
Patch40: xfsprogs-5.10.0-xfs_db-support-displaying-inode-btree-block-counts-i.patch
Patch41: xfsprogs-5.10.0-xfs_repair-check-inode-btree-block-counters-in-AGI.patch
Patch42: xfsprogs-5.10.0-xfs_repair-regenerate-inode-btree-block-counters-in-.patch
Patch43: xfsprogs-5.10.0-xfs-enable-new-inode-btree-counters-feature.patch
Patch44: xfsprogs-5.10.0-mkfs-enable-the-inode-btree-counter-feature.patch
Patch45: xfsprogs-5.10.0-libfrog-convert-cvttime-to-return-time64_t.patch
Patch46: xfsprogs-5.10.0-xfs_quota-convert-time_to_string-to-use-time64_t.patch
Patch47: xfsprogs-5.10.0-xfs_db-refactor-timestamp-printing.patch
Patch48: xfsprogs-5.10.0-xfs_db-refactor-quota-timer-printing.patch
Patch49: xfsprogs-5.10.0-libfrog-list-the-bigtime-feature-when-reporting-geom.patch
Patch50: xfsprogs-5.10.0-xfs_db-report-bigtime-format-timestamps.patch
Patch51: xfsprogs-5.10.0-xfs_db-support-printing-time-limits.patch
Patch52: xfsprogs-5.10.0-xfs_quota-support-editing-and-reporting-quotas-with-.patch
Patch53: xfsprogs-5.10.0-xfs_repair-support-bigtime-timestamp-checking.patch
Patch54: xfsprogs-5.10.0-xfs-enable-big-timestamps.patch
Patch55: xfsprogs-5.10.0-mkfs-format-bigtime-filesystems.patch
Patch56: xfsprogs-5.12.0-libxfs-copy-crtime-correctly-now-that-it-s-timespec6.patch
Patch57: xfsprogs-5.13.0-xfs-remove-the-unused-xfs_icdinode_has_bigtime-helpe.patch
Patch58: xfsprogs-5.13.0-xfs-rename-xfs_ictimestamp_t.patch
Patch59: xfsprogs-5.13.0-xfs-rename-struct-xfs_legacy_ictimestamp.patch
Patch60: xfsprogs-5.11.0-mkfs-fix-wrong-inobtcount-usage-error-output.patch
Patch61: xfsprogs-5.12.0-libxfs-expose-inobtcount-in-xfs-geometry.patch
Patch62: xfsprogs-5.12.0-libfrog-report-inobtcount-in-geometry.patch
%description
A set of commands to use the XFS filesystem, including mkfs.xfs.
@ -93,6 +133,46 @@ also want to install xfsprogs.
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch48 -p1
%patch49 -p1
%patch50 -p1
%patch51 -p1
%patch52 -p1
%patch53 -p1
%patch54 -p1
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch60 -p1
%patch61 -p1
%patch62 -p1
%build
export tagname=CC
@ -152,6 +232,9 @@ rm -rf $RPM_BUILD_ROOT/%{_mandir}/man8/xfs_scrub*
%{_libdir}/*.so
%changelog
* Thu Dec 09 2021 Bill O'Donnell <bodonnel@redhat.com> 5.0.0-10
- xfsprogs: enable bigtime and inode btree counter features in RHEL8 (#2024201))
* Thu Jul 08 2021 Bill O'Donnell <bodonnel@redhat.com> 5.0.0-9
- xfs_quota: state command should report ugp grace time (#1949743)