From 369f7b1d9e2da7f2ded30466539d4f11110cde9a Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 10 May 2022 03:19:44 -0400 Subject: [PATCH] import xfsprogs-5.0.0-10.el8 --- .gitignore | 1 + .xfsprogs.metadata | 1 + SOURCES/xfsprogs-4.17.0-reflink-default.patch | 74 ++++ ...rrent_time-helper-and-sync-xfs_trans.patch | 106 +++++ ...fs_verify_fsbno-before-m_sb-is-fully.patch | 60 +++ ...lidate-start-and-end-of-aligned-logs.patch | 52 +++ ...fsprogs-Fix-uninitialized-cfg-lsunit.patch | 42 ++ ...g-convert-cvttime-to-return-time64_t.patch | 81 ++++ ...-bigtime-feature-when-reporting-geom.patch | 61 +++ ...bxfs-create-a-real-struct-timespec64.patch | 89 ++++ ...-5.10.0-libxfs-refactor-NSEC_PER_SEC.patch | 53 +++ ...able-the-inode-btree-counter-feature.patch | 139 +++++++ ...10.0-mkfs-format-bigtime-filesystems.patch | 130 ++++++ ...ogs-5.10.0-xfs-enable-big-timestamps.patch | 32 ++ ...ble-new-inode-btree-counters-feature.patch | 28 ++ ...licitly-define-inode-timestamp-range.patch | 74 ++++ ..._dinode_to_disk-to-the-log-recovery-.patch | 94 +++++ ....10.0-xfs-redefine-xfs_ictimestamp_t.patch | 101 +++++ ...-5.10.0-xfs-redefine-xfs_timestamp_t.patch | 196 +++++++++ ...ault-quota-grace-period-setting-code.patch | 49 +++ ...-quota-expiration-timer-modification.patch | 54 +++ ...-xfs-refactor-quota-timestamp-coding.patch | 58 +++ ...ode-btree-block-counts-in-AGI-header.patch | 159 +++++++ ...bt-block-counts-to-speed-up-mount-ti.patch | 61 +++ ...-inode-timestamps-to-deal-with-y2038.patch | 371 +++++++++++++++++ ...-quota-expiration-timestamps-to-hand.patch | 170 ++++++++ ...xfs_db-refactor-quota-timer-printing.patch | 122 ++++++ ...0-xfs_db-refactor-timestamp-printing.patch | 176 ++++++++ ..._db-report-bigtime-format-timestamps.patch | 122 ++++++ ...isplaying-inode-btree-block-counts-i.patch | 39 ++ ...-xfs_db-support-printing-time-limits.patch | 245 +++++++++++ ...nvert-time_to_string-to-use-time64_t.patch | 199 +++++++++ ...ment-how-the-default-quota-is-stored.patch | 35 ++ ...t-editing-and-reporting-quotas-with-.patch | 236 +++++++++++ ...max-values-in-compute_level_geometry.patch | 92 +++++ ...ck-inode-btree-block-counters-in-AGI.patch | 98 +++++ ...erate-inode-btree-block-counters-in-.patch | 29 ++ ...r-support-bigtime-timestamp-checking.patch | 81 ++++ ...-wrong-inobtcount-usage-error-output.patch | 38 ++ ...ibfrog-report-inobtcount-in-geometry.patch | 53 +++ ...me-correctly-now-that-it-s-timespec6.patch | 29 ++ ...fs-expose-inobtcount-in-xfs-geometry.patch | 42 ++ ...nused-xfs_icdinode_has_bigtime-helpe.patch | 29 ++ ...rename-struct-xfs_legacy_ictimestamp.patch | 46 +++ ...-5.13.0-xfs-rename-xfs_ictimestamp_t.patch | 77 ++++ ...llow-mounted-device-node-as-argument.patch | 70 ++++ ...ak-block-discard-into-chunks-of-2-GB.patch | 109 +++++ ...0-mkfs-tidy-up-discard-notifications.patch | 56 +++ ...C_FL_ZERO_RANGE-in-libxfs_device_zer.patch | 112 +++++ ...ct-timespec64-for-the-in-core-crtime.patch | 123 ++++++ ...ota-allow-individual-timer-extension.patch | 227 ++++++++++ ...uota-fix-unsigned-int-id-comparisons.patch | 69 ++++ ...factor-code-to-generate-id-from-name.patch | 271 ++++++++++++ ...-for-AG-btree-records-that-would-wra.patch | 54 +++ ...ain-about-bad-interior-btree-pointer.patch | 124 ++++++ ...epair-convert-to-libxfs_verify_agbno.patch | 209 ++++++++++ ...ebuilding-btree-block-less-than-minr.patch | 290 +++++++++++++ ...-tag-inobt-vs-finobt-errors-properly.patch | 88 ++++ ...-circuit-type_f-if-type-is-unchanged.patch | 31 ++ ...ta-command-error-message-improvement.patch | 76 ++++ ...y-warning-limits-when-printing-quota.patch | 52 +++ ...command-should-report-ugp-grace-time.patch | 141 +++++++ ...SERT-on-too-small-device-with-stripe.patch | 76 ++++ ...type-parameter-from-xfs_dquot_verify.patch | 101 +++++ ...-improve-ondisk-dquot-flags-checking.patch | 98 +++++ SPECS/xfsprogs.spec | 387 ++++++++++++++++++ 66 files changed, 6888 insertions(+) create mode 100644 .gitignore create mode 100644 .xfsprogs.metadata create mode 100755 SOURCES/xfsprogs-4.17.0-reflink-default.patch create mode 100755 SOURCES/xfsprogs-5.1.0-libxfs-create-current_time-helper-and-sync-xfs_trans.patch create mode 100755 SOURCES/xfsprogs-5.1.0-mkfs-don-t-use-xfs_verify_fsbno-before-m_sb-is-fully.patch create mode 100755 SOURCES/xfsprogs-5.1.0-mkfs-validate-start-and-end-of-aligned-logs.patch create mode 100755 SOURCES/xfsprogs-5.1.0-xfsprogs-Fix-uninitialized-cfg-lsunit.patch create mode 100755 SOURCES/xfsprogs-5.10.0-libfrog-convert-cvttime-to-return-time64_t.patch create mode 100755 SOURCES/xfsprogs-5.10.0-libfrog-list-the-bigtime-feature-when-reporting-geom.patch create mode 100755 SOURCES/xfsprogs-5.10.0-libxfs-create-a-real-struct-timespec64.patch create mode 100755 SOURCES/xfsprogs-5.10.0-libxfs-refactor-NSEC_PER_SEC.patch create mode 100755 SOURCES/xfsprogs-5.10.0-mkfs-enable-the-inode-btree-counter-feature.patch create mode 100755 SOURCES/xfsprogs-5.10.0-mkfs-format-bigtime-filesystems.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-enable-big-timestamps.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-enable-new-inode-btree-counters-feature.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-explicitly-define-inode-timestamp-range.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-move-xfs_log_dinode_to_disk-to-the-log-recovery-.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_ictimestamp_t.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_timestamp_t.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-refactor-default-quota-grace-period-setting-code.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-expiration-timer-modification.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-timestamp-coding.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-store-inode-btree-block-counts-in-AGI-header.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-use-the-finobt-block-counts-to-speed-up-mount-ti.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-inode-timestamps-to-deal-with-y2038.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-quota-expiration-timestamps-to-hand.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_db-refactor-quota-timer-printing.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_db-refactor-timestamp-printing.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_db-report-bigtime-format-timestamps.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_db-support-displaying-inode-btree-block-counts-i.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_db-support-printing-time-limits.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_quota-convert-time_to_string-to-use-time64_t.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_quota-document-how-the-default-quota-is-stored.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_quota-support-editing-and-reporting-quotas-with-.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_geometry.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_repair-check-inode-btree-block-counters-in-AGI.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_repair-regenerate-inode-btree-block-counters-in-.patch create mode 100755 SOURCES/xfsprogs-5.10.0-xfs_repair-support-bigtime-timestamp-checking.patch create mode 100755 SOURCES/xfsprogs-5.11.0-mkfs-fix-wrong-inobtcount-usage-error-output.patch create mode 100755 SOURCES/xfsprogs-5.12.0-libfrog-report-inobtcount-in-geometry.patch create mode 100755 SOURCES/xfsprogs-5.12.0-libxfs-copy-crtime-correctly-now-that-it-s-timespec6.patch create mode 100755 SOURCES/xfsprogs-5.12.0-libxfs-expose-inobtcount-in-xfs-geometry.patch create mode 100755 SOURCES/xfsprogs-5.13.0-xfs-remove-the-unused-xfs_icdinode_has_bigtime-helpe.patch create mode 100755 SOURCES/xfsprogs-5.13.0-xfs-rename-struct-xfs_legacy_ictimestamp.patch create mode 100755 SOURCES/xfsprogs-5.13.0-xfs-rename-xfs_ictimestamp_t.patch create mode 100755 SOURCES/xfsprogs-5.3.0-xfs_growfs-allow-mounted-device-node-as-argument.patch create mode 100755 SOURCES/xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch create mode 100755 SOURCES/xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch create mode 100755 SOURCES/xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch create mode 100755 SOURCES/xfsprogs-5.5.0-xfs-use-a-struct-timespec64-for-the-in-core-crtime.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_quota-fix-unsigned-int-id-comparisons.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_quota-refactor-code-to-generate-id-from-name.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_repair-check-for-AG-btree-records-that-would-wra.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_repair-complain-about-bad-interior-btree-pointer.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_repair-convert-to-libxfs_verify_agbno.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_repair-fix-rebuilding-btree-block-less-than-minr.patch create mode 100755 SOURCES/xfsprogs-5.7.0-xfs_repair-tag-inobt-vs-finobt-errors-properly.patch create mode 100755 SOURCES/xfsprogs-5.8.0-xfs_db-short-circuit-type_f-if-type-is-unchanged.patch create mode 100755 SOURCES/xfsprogs-5.8.0-xfs_quota-command-error-message-improvement.patch create mode 100755 SOURCES/xfsprogs-5.8.0-xfs_quota-display-warning-limits-when-printing-quota.patch create mode 100755 SOURCES/xfsprogs-5.8.0-xfs_quota-state-command-should-report-ugp-grace-time.patch create mode 100755 SOURCES/xfsprogs-5.9.0-mkfs.xfs-fix-ASSERT-on-too-small-device-with-stripe.patch create mode 100755 SOURCES/xfsprogs-5.9.0-xfs-drop-the-type-parameter-from-xfs_dquot_verify.patch create mode 100755 SOURCES/xfsprogs-5.9.0-xfs-improve-ondisk-dquot-flags-checking.patch create mode 100644 SPECS/xfsprogs.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5bc0f06 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/xfsprogs-5.0.0.tar.xz diff --git a/.xfsprogs.metadata b/.xfsprogs.metadata new file mode 100644 index 0000000..fbd87e2 --- /dev/null +++ b/.xfsprogs.metadata @@ -0,0 +1 @@ +1a3d7ce8ebf75e001463162e4a44c0f5bf0beab7 SOURCES/xfsprogs-5.0.0.tar.xz diff --git a/SOURCES/xfsprogs-4.17.0-reflink-default.patch b/SOURCES/xfsprogs-4.17.0-reflink-default.patch new file mode 100755 index 0000000..3d7ea87 --- /dev/null +++ b/SOURCES/xfsprogs-4.17.0-reflink-default.patch @@ -0,0 +1,74 @@ +Index: xfsprogs-4.19.0/mkfs/xfs_mkfs.c +=================================================================== +--- xfsprogs-4.19.0.orig/mkfs/xfs_mkfs.c ++++ xfsprogs-4.19.0/mkfs/xfs_mkfs.c +@@ -1973,15 +1973,15 @@ _("Directory ftype field always enabled + usage(); + } + +- } else { ++ } else { /* !crcs_enabled */ + /* +- * The kernel doesn't currently support crc=0,finobt=1 +- * filesystems. If crcs are not enabled and the user has not +- * explicitly turned finobt on, then silently turn it off to +- * avoid an unnecessary warning. ++ * The kernel doesn't support crc=0,finobt=1 filesystems. ++ * If crcs are not enabled and the user has not explicitly ++ * turned finobt on, then silently turn it off to avoid an ++ * unnecessary warning. + * If the user explicitly tried to use crc=0,finobt=1, + * then issue an error. +- * The same is also for sparse inodes. ++ * The same is also true for sparse inodes and reflink. + */ + if (cli->sb_feat.finobt && cli_opt_set(&mopts, M_FINOBT)) { + fprintf(stderr, +@@ -2004,7 +2004,7 @@ _("rmapbt not supported without CRC supp + } + cli->sb_feat.rmapbt = false; + +- if (cli->sb_feat.reflink) { ++ if (cli->sb_feat.reflink && cli_opt_set(&mopts, M_REFLINK)) { + fprintf(stderr, + _("reflink not supported without CRC support\n")); + usage(); +@@ -3788,7 +3788,7 @@ main( + .finobt = true, + .spinodes = true, + .rmapbt = false, +- .reflink = false, ++ .reflink = true, + .parent_pointers = false, + .nodalign = false, + .nortalign = false, +Index: xfsprogs-4.19.0/man/man8/mkfs.xfs.8 +=================================================================== +--- xfsprogs-4.19.0.orig/man/man8/mkfs.xfs.8 ++++ xfsprogs-4.19.0/man/man8/mkfs.xfs.8 +@@ -229,9 +229,9 @@ mapping will be changed to the new block + enables the creation of per-file snapshots and deduplication. It is only + available for the data forks of regular files. + .IP +-By default, ++By default in Red Hat Enterprise Linux 8, + .B mkfs.xfs +-will not create reference count btrees and therefore will not enable the ++will create reference count btrees and therefore will enable the + reflink feature. This feature is only available for filesystems created with + the (default) + .B \-m crc=1 +@@ -239,6 +239,13 @@ option set. When the option + .B \-m crc=0 + is used, the reference count btree feature is not supported and reflink is + disabled. ++.IP ++Note: the filesystem DAX mount option ( ++.B \-o dax ++) is incompatible with ++reflink-enabled XFS filesystems. To use filesystem DAX with XFS, specify the ++.B \-m reflink=0 ++option to mkfs.xfs to disable the reflink feature. + .RE + .TP + .BI \-d " data_section_options" diff --git a/SOURCES/xfsprogs-5.1.0-libxfs-create-current_time-helper-and-sync-xfs_trans.patch b/SOURCES/xfsprogs-5.1.0-libxfs-create-current_time-helper-and-sync-xfs_trans.patch new file mode 100755 index 0000000..e994ea9 --- /dev/null +++ b/SOURCES/xfsprogs-5.1.0-libxfs-create-current_time-helper-and-sync-xfs_trans.patch @@ -0,0 +1,106 @@ +From b192e77cc38473964c718bd035502b702c6a6e34 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +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 +Reviewed-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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) diff --git a/SOURCES/xfsprogs-5.1.0-mkfs-don-t-use-xfs_verify_fsbno-before-m_sb-is-fully.patch b/SOURCES/xfsprogs-5.1.0-mkfs-don-t-use-xfs_verify_fsbno-before-m_sb-is-fully.patch new file mode 100755 index 0000000..ef58f5b --- /dev/null +++ b/SOURCES/xfsprogs-5.1.0-mkfs-don-t-use-xfs_verify_fsbno-before-m_sb-is-fully.patch @@ -0,0 +1,60 @@ +From 9c726ef0d2d829ae83756d3817f271e9c2c8777a Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Wed, 10 Jul 2019 11:35:07 -0400 +Subject: [PATCH] mkfs: don't use xfs_verify_fsbno() before m_sb is fully set + up + +Commit 8da5298 mkfs: validate start and end of aligned logs stopped +open-coding log end block checks, and used xfs_verify_fsbno() instead. +It also used xfs_verify_fsbno() to validate the log start. This +seemed to make sense, but then xfs/306 started failing on 4k sector +filesystems, which leads to a log striep unite being set on a single +AG filesystem. + +As it turns out, if xfs_verify_fsbno() is testing a block in the +last AG, it needs to have mp->m_sb.sb_dblocks set, which isn't done +until later. With sb_dblocks unset we can't know how many blocks +are in the last AG, and hence can't validate it. + +To fix all this, go back to open-coding the checks; note that this +/does/ rely on m_sb.sb_agblklog being set, but that /is/ already +done in the early call to start_superblock_setup(). + +Fixes: 8da5298 ("mkfs: validate start and end of aligned logs") +Reported-by: Dave Chinner +Signed-off-by: Eric Sandeen +Reviewed-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + mkfs/xfs_mkfs.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c +index 468b8fde..4e576a5c 100644 +--- a/mkfs/xfs_mkfs.c ++++ b/mkfs/xfs_mkfs.c +@@ -3040,7 +3040,7 @@ align_internal_log( + cfg->logstart = ((cfg->logstart + (sunit - 1)) / sunit) * sunit; + + /* If our log start overlaps the next AG's metadata, fail. */ +- if (!xfs_verify_fsbno(mp, cfg->logstart)) { ++ if (XFS_FSB_TO_AGBNO(mp, cfg->logstart) <= XFS_AGFL_BLOCK(mp)) { + fprintf(stderr, + _("Due to stripe alignment, the internal log start (%lld) cannot be aligned\n" + "within an allocation group.\n"), +@@ -3051,10 +3051,9 @@ _("Due to stripe alignment, the internal log start (%lld) cannot be aligned\n" + /* round up/down the log size now */ + align_log_size(cfg, sunit); + +- /* check the aligned log still fits in an AG. */ ++ /* check the aligned log still starts and ends in the same AG. */ + logend = cfg->logstart + cfg->logblocks - 1; +- if (XFS_FSB_TO_AGNO(mp, cfg->logstart) != XFS_FSB_TO_AGNO(mp, logend) || +- !xfs_verify_fsbno(mp, logend)) { ++ if (XFS_FSB_TO_AGNO(mp, cfg->logstart) != XFS_FSB_TO_AGNO(mp, logend)) { + fprintf(stderr, + _("Due to stripe alignment, the internal log size (%lld) is too large.\n" + "Must fit within an allocation group.\n"), +-- +2.17.0 + diff --git a/SOURCES/xfsprogs-5.1.0-mkfs-validate-start-and-end-of-aligned-logs.patch b/SOURCES/xfsprogs-5.1.0-mkfs-validate-start-and-end-of-aligned-logs.patch new file mode 100755 index 0000000..7fd0b7e --- /dev/null +++ b/SOURCES/xfsprogs-5.1.0-mkfs-validate-start-and-end-of-aligned-logs.patch @@ -0,0 +1,52 @@ +From 8da52988ad210958f21c178620bb1e44f1188cd0 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Tue, 25 Jun 2019 17:04:42 -0400 +Subject: [PATCH] mkfs: validate start and end of aligned logs + +Validate that the start and end of the log stay within a single AG if +we adjust either end to align to stripe units. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Eric Sandeen +Signed-off-by: Eric Sandeen +--- + mkfs/xfs_mkfs.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c +index ddb25ecc..468b8fde 100644 +--- a/mkfs/xfs_mkfs.c ++++ b/mkfs/xfs_mkfs.c +@@ -3033,15 +3033,28 @@ align_internal_log( + struct xfs_mount *mp, + int sunit) + { ++ uint64_t logend; ++ + /* round up log start if necessary */ + if ((cfg->logstart % sunit) != 0) + cfg->logstart = ((cfg->logstart + (sunit - 1)) / sunit) * sunit; + ++ /* If our log start overlaps the next AG's metadata, fail. */ ++ if (!xfs_verify_fsbno(mp, cfg->logstart)) { ++ fprintf(stderr, ++_("Due to stripe alignment, the internal log start (%lld) cannot be aligned\n" ++ "within an allocation group.\n"), ++ (long long) cfg->logstart); ++ usage(); ++ } ++ + /* round up/down the log size now */ + align_log_size(cfg, sunit); + + /* check the aligned log still fits in an AG. */ +- if (cfg->logblocks > cfg->agsize - XFS_FSB_TO_AGBNO(mp, cfg->logstart)) { ++ logend = cfg->logstart + cfg->logblocks - 1; ++ if (XFS_FSB_TO_AGNO(mp, cfg->logstart) != XFS_FSB_TO_AGNO(mp, logend) || ++ !xfs_verify_fsbno(mp, logend)) { + fprintf(stderr, + _("Due to stripe alignment, the internal log size (%lld) is too large.\n" + "Must fit within an allocation group.\n"), +-- +2.17.0 + diff --git a/SOURCES/xfsprogs-5.1.0-xfsprogs-Fix-uninitialized-cfg-lsunit.patch b/SOURCES/xfsprogs-5.1.0-xfsprogs-Fix-uninitialized-cfg-lsunit.patch new file mode 100755 index 0000000..49f2d34 --- /dev/null +++ b/SOURCES/xfsprogs-5.1.0-xfsprogs-Fix-uninitialized-cfg-lsunit.patch @@ -0,0 +1,42 @@ +From 59cf967983f6aaff4ce33a50135ae57032ebd8f2 Mon Sep 17 00:00:00 2001 +From: Allison Collins +Date: Wed, 10 Jul 2019 11:38:04 -0400 +Subject: [PATCH] xfsprogs: Fix uninitialized cfg->lsunit + +While investigating another mkfs bug, noticed that cfg->lsunit is sometimes +left uninitialized when it should not. This is because calc_stripe_factors +in some cases needs cfg->loginternal to be set first. This is done in +validate_logdev. So move calc_stripe_factors below validate_logdev while +parsing configs. + +Signed-off-by: Allison Collins +Reviewed-by: Darrick J. Wong +Reviewed-by: Carlos Maiolino +Signed-off-by: Eric Sandeen +--- + 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 79377b12..65cf1e0f 100644 +--- a/mkfs/xfs_mkfs.c ++++ b/mkfs/xfs_mkfs.c +@@ -4007,7 +4007,6 @@ main( + cfg.rtblocks = calc_dev_size(cli.rtsize, &cfg, &ropts, R_SIZE, "rt"); + + validate_rtextsize(&cfg, &cli, &ft); +- calc_stripe_factors(&cfg, &cli, &ft); + + /* + * Open and validate the device configurations +@@ -4017,6 +4016,7 @@ main( + validate_datadev(&cfg, &cli); + validate_logdev(&cfg, &cli, &logfile); + validate_rtdev(&cfg, &cli, &rtfile); ++ calc_stripe_factors(&cfg, &cli, &ft); + + /* + * At this point when know exactly what size all the devices are, +-- +2.17.0 + diff --git a/SOURCES/xfsprogs-5.10.0-libfrog-convert-cvttime-to-return-time64_t.patch b/SOURCES/xfsprogs-5.10.0-libfrog-convert-cvttime-to-return-time64_t.patch new file mode 100755 index 0000000..dd94f67 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-libfrog-convert-cvttime-to-return-time64_t.patch @@ -0,0 +1,81 @@ +From bf6d4cf988176ad7efd0089830bfbf200a5e0196 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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; diff --git a/SOURCES/xfsprogs-5.10.0-libfrog-list-the-bigtime-feature-when-reporting-geom.patch b/SOURCES/xfsprogs-5.10.0-libfrog-list-the-bigtime-feature-when-reporting-geom.patch new file mode 100755 index 0000000..fbd34a4 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-libfrog-list-the-bigtime-feature-when-reporting-geom.patch @@ -0,0 +1,61 @@ +From 0160c1490d4b49889c9ed01a39f760cba762eac5 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-libxfs-create-a-real-struct-timespec64.patch b/SOURCES/xfsprogs-5.10.0-libxfs-create-a-real-struct-timespec64.patch new file mode 100755 index 0000000..8ab33aa --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-libxfs-create-a-real-struct-timespec64.patch @@ -0,0 +1,89 @@ +From ec24f6fa05f695af02b4e0fca5bc27cb1cab49b7 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Amir Goldstein +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-libxfs-refactor-NSEC_PER_SEC.patch b/SOURCES/xfsprogs-5.10.0-libxfs-refactor-NSEC_PER_SEC.patch new file mode 100755 index 0000000..f098b26 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-libxfs-refactor-NSEC_PER_SEC.patch @@ -0,0 +1,53 @@ +From c0e580154e1469f1bcef132b1a7585409f66e1e5 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Amir Goldstein +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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) + { diff --git a/SOURCES/xfsprogs-5.10.0-mkfs-enable-the-inode-btree-counter-feature.patch b/SOURCES/xfsprogs-5.10.0-mkfs-enable-the-inode-btree-counter-feature.patch new file mode 100755 index 0000000..83711f9 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-mkfs-enable-the-inode-btree-counter-feature.patch @@ -0,0 +1,139 @@ +From 9eb0d6eb9066daa621e710139c8c8d50fedbabcf Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Brian Foster +Signed-off-by: Eric Sandeen +--- + +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, diff --git a/SOURCES/xfsprogs-5.10.0-mkfs-format-bigtime-filesystems.patch b/SOURCES/xfsprogs-5.10.0-mkfs-format-bigtime-filesystems.patch new file mode 100755 index 0000000..f0a0272 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-mkfs-format-bigtime-filesystems.patch @@ -0,0 +1,130 @@ +From e9601810beb7d5b36a5fbd03c593cf63f685bfff Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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, + }, + }; + diff --git a/SOURCES/xfsprogs-5.10.0-xfs-enable-big-timestamps.patch b/SOURCES/xfsprogs-5.10.0-xfs-enable-big-timestamps.patch new file mode 100755 index 0000000..08f0f42 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-enable-big-timestamps.patch @@ -0,0 +1,32 @@ +From cac80700d88a32c1835cb37f982e98ddd73021e5 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Amir Goldstein +Reviewed-by: Allison Collins +Reviewed-by: Christoph Hellwig +Reviewed-by: Gao Xiang +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs-enable-new-inode-btree-counters-feature.patch b/SOURCES/xfsprogs-5.10.0-xfs-enable-new-inode-btree-counters-feature.patch new file mode 100755 index 0000000..0113578 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-enable-new-inode-btree-counters-feature.patch @@ -0,0 +1,28 @@ +From 46da703382fa31bb02049a4131602f8a40002dbb Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Brian Foster +Signed-off-by: Eric Sandeen +--- + +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( diff --git a/SOURCES/xfsprogs-5.10.0-xfs-explicitly-define-inode-timestamp-range.patch b/SOURCES/xfsprogs-5.10.0-xfs-explicitly-define-inode-timestamp-range.patch new file mode 100755 index 0000000..3722d97 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-explicitly-define-inode-timestamp-range.patch @@ -0,0 +1,74 @@ +From 18e3b8c234fac67c6c96e9ff34f0ab4598220fa1 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Amir Goldstein +Reviewed-by: Christoph Hellwig +Reviewed-by: Allison Collins +Reviewed-by: Gao Xiang +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs-move-xfs_log_dinode_to_disk-to-the-log-recovery-.patch b/SOURCES/xfsprogs-5.10.0-xfs-move-xfs_log_dinode_to_disk-to-the-log-recovery-.patch new file mode 100755 index 0000000..9b36936 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-move-xfs_log_dinode_to_disk-to-the-log-recovery-.patch @@ -0,0 +1,94 @@ +From acaa814953273827f380262ba900f0d50a95bee2 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Allison Collins +Reviewed-by: Gao Xiang +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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); + diff --git a/SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_ictimestamp_t.patch b/SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_ictimestamp_t.patch new file mode 100755 index 0000000..5c9939e --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_ictimestamp_t.patch @@ -0,0 +1,101 @@ +From fc3e21db4a30d0d81158938cabba0fb59fc57ad8 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Gao Xiang +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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 *); diff --git a/SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_timestamp_t.patch b/SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_timestamp_t.patch new file mode 100755 index 0000000..dd18260 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-redefine-xfs_timestamp_t.patch @@ -0,0 +1,196 @@ +From a252aadfc977473e0851acf0d529c930c6e8e181 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Gao Xiang +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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; + diff --git a/SOURCES/xfsprogs-5.10.0-xfs-refactor-default-quota-grace-period-setting-code.patch b/SOURCES/xfsprogs-5.10.0-xfs-refactor-default-quota-grace-period-setting-code.patch new file mode 100755 index 0000000..2ce2617 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-refactor-default-quota-grace-period-setting-code.patch @@ -0,0 +1,49 @@ +From abc0f20536e3bc1505f575f452c55585c34f6e06 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Amir Goldstein +Reviewed-by: Christoph Hellwig +Reviewed-by: Allison Collins +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-expiration-timer-modification.patch b/SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-expiration-timer-modification.patch new file mode 100755 index 0000000..afce3b3 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-expiration-timer-modification.patch @@ -0,0 +1,54 @@ +From 94c5482a7e0cbb6fd289745a4b5f49a133a4f5e8 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Allison Collins +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-timestamp-coding.patch b/SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-timestamp-coding.patch new file mode 100755 index 0000000..4e59c4b --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-refactor-quota-timestamp-coding.patch @@ -0,0 +1,58 @@ +From 68879320b482e73e6ce202a8e680c8ab7e6a2af4 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Amir Goldstein +Reviewed-by: Christoph Hellwig +Reviewed-by: Allison Collins +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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__ */ diff --git a/SOURCES/xfsprogs-5.10.0-xfs-store-inode-btree-block-counts-in-AGI-header.patch b/SOURCES/xfsprogs-5.10.0-xfs-store-inode-btree-block-counts-in-AGI-header.patch new file mode 100755 index 0000000..eb2289e --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-store-inode-btree-block-counts-in-AGI-header.patch @@ -0,0 +1,159 @@ +From 177c81e25b763c90f9815b1f4055d9d5c515a845 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Brian Foster +Signed-off-by: Eric Sandeen +--- + +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); + + /* diff --git a/SOURCES/xfsprogs-5.10.0-xfs-use-the-finobt-block-counts-to-speed-up-mount-ti.patch b/SOURCES/xfsprogs-5.10.0-xfs-use-the-finobt-block-counts-to-speed-up-mount-ti.patch new file mode 100755 index 0000000..d4ae969 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-use-the-finobt-block-counts-to-speed-up-mount-ti.patch @@ -0,0 +1,61 @@ +From eb2c6897f36d560f84ed5124b246f2759c470f11 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Brian Foster +Signed-off-by: Eric Sandeen +--- + +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; + diff --git a/SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-inode-timestamps-to-deal-with-y2038.patch b/SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-inode-timestamps-to-deal-with-y2038.patch new file mode 100755 index 0000000..7b056fa --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-inode-timestamps-to-deal-with-y2038.patch @@ -0,0 +1,371 @@ +From e7e3beb95efd751f227a0ced4c83fc5b88582e2e Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Gao Xiang +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-quota-expiration-timestamps-to-hand.patch b/SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-quota-expiration-timestamps-to-hand.patch new file mode 100755 index 0000000..2ccd791 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs-widen-ondisk-quota-expiration-timestamps-to-hand.patch @@ -0,0 +1,170 @@ +From 06963ef0d4ff9a6736f699d1ca8ef5a0c194799b Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Allison Collins +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs_db-refactor-quota-timer-printing.patch b/SOURCES/xfsprogs-5.10.0-xfs_db-refactor-quota-timer-printing.patch new file mode 100755 index 0000000..3770f7c --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_db-refactor-quota-timer-printing.patch @@ -0,0 +1,122 @@ +From a9a32fcb9176c82aed6d85f209e7279b76c8b55f Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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, diff --git a/SOURCES/xfsprogs-5.10.0-xfs_db-refactor-timestamp-printing.patch b/SOURCES/xfsprogs-5.10.0-xfs_db-refactor-timestamp-printing.patch new file mode 100755 index 0000000..6d97e8e --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_db-refactor-timestamp-printing.patch @@ -0,0 +1,176 @@ +From 300422226c423222e78d82d54b09d0ae27c7d4af Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs_db-report-bigtime-format-timestamps.patch b/SOURCES/xfsprogs-5.10.0-xfs_db-report-bigtime-format-timestamps.patch new file mode 100755 index 0000000..b64f560 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_db-report-bigtime-format-timestamps.patch @@ -0,0 +1,122 @@ +From 344f38a9e5d0f938dae337c8c769853e6368d480 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Eric Sandeen +Signed-off-by: Eric Sandeen +--- + +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; + } + diff --git a/SOURCES/xfsprogs-5.10.0-xfs_db-support-displaying-inode-btree-block-counts-i.patch b/SOURCES/xfsprogs-5.10.0-xfs_db-support-displaying-inode-btree-block-counts-i.patch new file mode 100755 index 0000000..5497948 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_db-support-displaying-inode-btree-block-counts-i.patch @@ -0,0 +1,39 @@ +From 13b8917251601e06660ed6ebe6bdeafa4c431ca3 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Brian Foster +Signed-off-by: Eric Sandeen +--- + +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; + } + diff --git a/SOURCES/xfsprogs-5.10.0-xfs_db-support-printing-time-limits.patch b/SOURCES/xfsprogs-5.10.0-xfs_db-support-printing-time-limits.patch new file mode 100755 index 0000000..386eabc --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_db-support-printing-time-limits.patch @@ -0,0 +1,245 @@ +From 4893718570dac172f639cc5e8687e782c4f759ee Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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 ++ */ ++#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 diff --git a/SOURCES/xfsprogs-5.10.0-xfs_quota-convert-time_to_string-to-use-time64_t.patch b/SOURCES/xfsprogs-5.10.0-xfs_quota-convert-time_to_string-to-use-time64_t.patch new file mode 100755 index 0000000..f79f2d8 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_quota-convert-time_to_string-to-use-time64_t.patch @@ -0,0 +1,199 @@ +From 219285adf56da85171fa90f42714341484750856 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Eric Sandeen +Signed-off-by: Eric Sandeen +--- + +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) { diff --git a/SOURCES/xfsprogs-5.10.0-xfs_quota-document-how-the-default-quota-is-stored.patch b/SOURCES/xfsprogs-5.10.0-xfs_quota-document-how-the-default-quota-is-stored.patch new file mode 100755 index 0000000..bfb71e3 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_quota-document-how-the-default-quota-is-stored.patch @@ -0,0 +1,35 @@ +From 0d7b09ac95e4cde766a534fdb7ea8dd46451ad53 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Fri, 4 Dec 2020 12:17:12 -0500 +Subject: [PATCH] xfs_quota: document how the default quota is stored + +Nowhere in the man page is the default quota described; what it +does or where it is stored. Add some brief information about this. + +Signed-off-by: Eric Sandeen +Reviewed-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + man/man8/xfs_quota.8 | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/man/man8/xfs_quota.8 b/man/man8/xfs_quota.8 +index dd0479cd..6ead7ee9 100644 +--- a/man/man8/xfs_quota.8 ++++ b/man/man8/xfs_quota.8 +@@ -178,6 +178,12 @@ to a file on + where the user's quota has not been exceeded. + Then after rectifying the quota situation, the file can be moved back to the + filesystem it belongs on. ++.SS Default Quotas ++The XFS quota subsystem allows a default quota to be enforced ++for any user, group or project which does not have a quota limit ++explicitly set. ++These limits are stored in and displayed as ID 0's limits, although they ++do not actually limit ID 0. + .SH USER COMMANDS + .TP + .B print +-- +2.29.2 + diff --git a/SOURCES/xfsprogs-5.10.0-xfs_quota-support-editing-and-reporting-quotas-with-.patch b/SOURCES/xfsprogs-5.10.0-xfs_quota-support-editing-and-reporting-quotas-with-.patch new file mode 100755 index 0000000..aa672f4 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_quota-support-editing-and-reporting-quotas-with-.patch @@ -0,0 +1,236 @@ +From f3eb31d9c005558ce975e2806f8dc73b0ecbd7f7 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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; diff --git a/SOURCES/xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_geometry.patch b/SOURCES/xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_geometry.patch new file mode 100755 index 0000000..5a07f04 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_geometry.patch @@ -0,0 +1,92 @@ +xfs_repair: Use proper min/max values in compute_level_geometry + +When compute_level_geometry was added it exclusively uses +m_alloc_mnr/m_alloc_mxr but the rmap btree should be using +m_rmap_mnr/m_rmap_mxr. Pass those in directly to fix the +problem. + +Signed-off-by: Eric Sandeen +--- + +diff --git a/repair/phase5.c b/repair/phase5.c +index 0b8a55ff..dff342c8 100644 +--- a/repair/phase5.c ++++ b/repair/phase5.c +@@ -355,12 +355,12 @@ compute_level_geometry( + struct bt_stat_level *lptr, + uint64_t nr_this_level, + int slack, +- bool leaf) ++ uint maxrecs, ++ uint minrecs) + { +- unsigned int maxrecs = mp->m_alloc_mxr[!leaf]; + unsigned int desired_npb; + +- desired_npb = max(mp->m_alloc_mnr[!leaf], maxrecs - slack); ++ desired_npb = max(minrecs, maxrecs - slack); + lptr->num_recs_tot = nr_this_level; + lptr->num_blocks = max(1ULL, nr_this_level / desired_npb); + +@@ -410,7 +410,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, + * of the tree and set up the cursor for the leaf level + * (note that the same code is duplicated further down) + */ +- compute_level_geometry(mp, lptr, num_extents, 2, true); ++ compute_level_geometry(mp, lptr, num_extents, 2, ++ mp->m_alloc_mxr[0], mp->m_alloc_mnr[0]); + level = 1; + + #ifdef XR_BLD_FREE_TRACE +@@ -429,7 +430,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, + lptr = &btree_curs->level[level]; + + compute_level_geometry(mp, lptr, +- p_lptr->num_blocks, 0, false); ++ p_lptr->num_blocks, 0, ++ mp->m_alloc_mxr[1], mp->m_alloc_mnr[1]); + #ifdef XR_BLD_FREE_TRACE + fprintf(stderr, "%s %d %d %d %d %d\n", __func__, + level, +@@ -509,7 +511,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, + * of the number of extents changing + */ + old_blocks = btree_curs->level[0].num_blocks; +- compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, true); ++ compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, ++ mp->m_alloc_mxr[0], mp->m_alloc_mnr[0]); + extra_blocks = 0; + + if (old_blocks != btree_curs->level[0].num_blocks) { +@@ -578,7 +581,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, + lptr = &btree_curs->level[level++]; + + compute_level_geometry(mp, lptr, +- p_lptr->num_blocks, 0, false); ++ p_lptr->num_blocks, 0, ++ mp->m_alloc_mxr[1], mp->m_alloc_mnr[1]); + } + ASSERT(level < XFS_BTREE_MAXLEVELS); + ASSERT(lptr->num_blocks == 1); +@@ -1399,7 +1403,8 @@ init_rmapbt_cursor( + * metadata AG entries without too many splits. + */ + compute_level_geometry(mp, lptr, num_recs, +- num_recs > mp->m_rmap_mxr[0] ? 10 : 0, true); ++ num_recs > mp->m_rmap_mxr[0] ? 10 : 0, ++ mp->m_rmap_mxr[0], mp->m_rmap_mnr[0]); + blocks_allocated = lptr->num_blocks; + level = 1; + +@@ -1408,7 +1413,8 @@ init_rmapbt_cursor( + lptr = &btree_curs->level[level++]; + + compute_level_geometry(mp, lptr, +- p_lptr->num_blocks, 0, false); ++ p_lptr->num_blocks, 0, ++ mp->m_rmap_mxr[1], mp->m_rmap_mnr[1]); + blocks_allocated += lptr->num_blocks; + } + ASSERT(level < XFS_BTREE_MAXLEVELS); + + diff --git a/SOURCES/xfsprogs-5.10.0-xfs_repair-check-inode-btree-block-counters-in-AGI.patch b/SOURCES/xfsprogs-5.10.0-xfs_repair-check-inode-btree-block-counters-in-AGI.patch new file mode 100755 index 0000000..65bd45b --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_repair-check-inode-btree-block-counters-in-AGI.patch @@ -0,0 +1,98 @@ +From 62c713cb0c7791717c0b2a663ff0cc72842fe6c7 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Eric Sandeen +Signed-off-by: Eric Sandeen +--- + +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); diff --git a/SOURCES/xfsprogs-5.10.0-xfs_repair-regenerate-inode-btree-block-counters-in-.patch b/SOURCES/xfsprogs-5.10.0-xfs_repair-regenerate-inode-btree-block-counters-in-.patch new file mode 100755 index 0000000..8ff4435 --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_repair-regenerate-inode-btree-block-counters-in-.patch @@ -0,0 +1,29 @@ +From 086250dc5707ee6fcfb1ee8499e7af092904a7a6 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Brian Foster +Signed-off-by: Eric Sandeen +--- + +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); + } + diff --git a/SOURCES/xfsprogs-5.10.0-xfs_repair-support-bigtime-timestamp-checking.patch b/SOURCES/xfsprogs-5.10.0-xfs_repair-support-bigtime-timestamp-checking.patch new file mode 100755 index 0000000..7a10f3a --- /dev/null +++ b/SOURCES/xfsprogs-5.10.0-xfs_repair-support-bigtime-timestamp-checking.patch @@ -0,0 +1,81 @@ +From 37c7dda1c20bfd2cc73679275bab2dd43e0ad9b8 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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: diff --git a/SOURCES/xfsprogs-5.11.0-mkfs-fix-wrong-inobtcount-usage-error-output.patch b/SOURCES/xfsprogs-5.11.0-mkfs-fix-wrong-inobtcount-usage-error-output.patch new file mode 100755 index 0000000..75c9be1 --- /dev/null +++ b/SOURCES/xfsprogs-5.11.0-mkfs-fix-wrong-inobtcount-usage-error-output.patch @@ -0,0 +1,38 @@ +From 2c40c5a72b3cd0c4599bc84a7a8b09a496d46db3 Mon Sep 17 00:00:00 2001 +From: Zorro Lang +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 +Reviewed-by: Eric Sandeen +Signed-off-by: Eric Sandeen +--- + + 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 + diff --git a/SOURCES/xfsprogs-5.12.0-libfrog-report-inobtcount-in-geometry.patch b/SOURCES/xfsprogs-5.12.0-libfrog-report-inobtcount-in-geometry.patch new file mode 100755 index 0000000..1c110f8 --- /dev/null +++ b/SOURCES/xfsprogs-5.12.0-libfrog-report-inobtcount-in-geometry.patch @@ -0,0 +1,53 @@ +From dcad5c60c59bfcdf4e27dc552b94591eced0a452 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + 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 + diff --git a/SOURCES/xfsprogs-5.12.0-libxfs-copy-crtime-correctly-now-that-it-s-timespec6.patch b/SOURCES/xfsprogs-5.12.0-libxfs-copy-crtime-correctly-now-that-it-s-timespec6.patch new file mode 100755 index 0000000..10cc10b --- /dev/null +++ b/SOURCES/xfsprogs-5.12.0-libxfs-copy-crtime-correctly-now-that-it-s-timespec6.patch @@ -0,0 +1,29 @@ +From d625f74125863304d111f5c6a0817a115f8e502d Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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; + } + diff --git a/SOURCES/xfsprogs-5.12.0-libxfs-expose-inobtcount-in-xfs-geometry.patch b/SOURCES/xfsprogs-5.12.0-libxfs-expose-inobtcount-in-xfs-geometry.patch new file mode 100755 index 0000000..3148da7 --- /dev/null +++ b/SOURCES/xfsprogs-5.12.0-libxfs-expose-inobtcount-in-xfs-geometry.patch @@ -0,0 +1,42 @@ +From bdeb014153934e1d98787a9609a7532baf6a5c37 Mon Sep 17 00:00:00 2001 +From: Zorro Lang +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + +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 diff --git a/SOURCES/xfsprogs-5.13.0-xfs-remove-the-unused-xfs_icdinode_has_bigtime-helpe.patch b/SOURCES/xfsprogs-5.13.0-xfs-remove-the-unused-xfs_icdinode_has_bigtime-helpe.patch new file mode 100755 index 0000000..cbb000d --- /dev/null +++ b/SOURCES/xfsprogs-5.13.0-xfs-remove-the-unused-xfs_icdinode_has_bigtime-helpe.patch @@ -0,0 +1,29 @@ +From 5b9782c9317b7ac0ff942dffb667bad8502f0932 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + +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. diff --git a/SOURCES/xfsprogs-5.13.0-xfs-rename-struct-xfs_legacy_ictimestamp.patch b/SOURCES/xfsprogs-5.13.0-xfs-rename-struct-xfs_legacy_ictimestamp.patch new file mode 100755 index 0000000..0aafb47 --- /dev/null +++ b/SOURCES/xfsprogs-5.13.0-xfs-rename-struct-xfs_legacy_ictimestamp.patch @@ -0,0 +1,46 @@ +From 59301887102cc0415c8350a5e9562fe4beb083b6 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + +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; + } + diff --git a/SOURCES/xfsprogs-5.13.0-xfs-rename-xfs_ictimestamp_t.patch b/SOURCES/xfsprogs-5.13.0-xfs-rename-xfs_ictimestamp_t.patch new file mode 100755 index 0000000..1eff1ae --- /dev/null +++ b/SOURCES/xfsprogs-5.13.0-xfs-rename-xfs_ictimestamp_t.patch @@ -0,0 +1,77 @@ +From 27bb0efa5e615a9162f5bc3e228bdb7c337faa4c Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +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 +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + +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 *); diff --git a/SOURCES/xfsprogs-5.3.0-xfs_growfs-allow-mounted-device-node-as-argument.patch b/SOURCES/xfsprogs-5.3.0-xfs_growfs-allow-mounted-device-node-as-argument.patch new file mode 100755 index 0000000..abf76d8 --- /dev/null +++ b/SOURCES/xfsprogs-5.3.0-xfs_growfs-allow-mounted-device-node-as-argument.patch @@ -0,0 +1,70 @@ +From 7e8275f8939988f18f9a4a596381ca215fde2270 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Mon, 4 Nov 2019 15:35:49 -0500 +Subject: [PATCH] xfs_growfs: allow mounted device node as argument + +Up until: + + b97815a0 xfs_growfs: ensure target path is an active xfs mountpoint + +xfs_growfs actually accepted a mounted block device name as the +primary argument, because it could be found in the mount table. + +It turns out that Ansible was making use of this undocumented behavior, +and it's trivial to allow it, so put it back in place and document +it this time. + +Signed-off-by: Eric Sandeen +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + growfs/xfs_growfs.c | 3 +++ + man/man8/xfs_growfs.8 | 10 +++++++++- + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c +index eab15984..6c62833b 100644 +--- a/growfs/xfs_growfs.c ++++ b/growfs/xfs_growfs.c +@@ -141,6 +141,9 @@ main(int argc, char **argv) + } + + fs = fs_table_lookup_mount(rpath); ++ if (!fs) ++ fs = fs_table_lookup_blkdev(rpath); ++ + if (!fs) { + fprintf(stderr, _("%s: %s is not a mounted XFS filesystem\n"), + progname, argv[optind]); +diff --git a/man/man8/xfs_growfs.8 b/man/man8/xfs_growfs.8 +index 7e6a387c..60a88189 100644 +--- a/man/man8/xfs_growfs.8 ++++ b/man/man8/xfs_growfs.8 +@@ -35,7 +35,12 @@ xfs_growfs \- expand an XFS filesystem + .B \-R + .I size + ] ++[ + .I mount-point ++| ++.I block-device ++] ++ + .br + .B xfs_growfs \-V + .SH DESCRIPTION +@@ -45,7 +50,10 @@ expands an existing XFS filesystem (see + The + .I mount-point + argument is the pathname of the directory where the filesystem +-is mounted. The filesystem must be mounted to be grown (see ++is mounted. The ++.I block-device ++argument is the device name of a mounted XFS filesystem. ++The filesystem must be mounted to be grown (see + .BR mount (8)). + The existing contents of the filesystem are undisturbed, and the added space + becomes available for additional file storage. +-- +2.17.0 + diff --git a/SOURCES/xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch b/SOURCES/xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch new file mode 100755 index 0000000..56d959a --- /dev/null +++ b/SOURCES/xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch @@ -0,0 +1,109 @@ +From 7e8a6edb4d1ba0079152eb477abbbc1dfb1ebb7e Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Fri, 13 Dec 2019 16:21:26 -0500 +Subject: [PATCH] mkfs: Break block discard into chunks of 2 GB + +Some users are not happy about the BLKDISCARD taking too long and at the +same time not being informed about that - so they think that the command +actually hung. + +This commit changes code so that progress reporting is possible and also +typing the ^C will cancel the ongoing BLKDISCARD. + +Signed-off-by: Pavel Reichl +Reviewed-by: Darrick J. Wong +Reviewed-by: Dave Chinner +Signed-off-by: Eric Sandeen +--- + mkfs/xfs_mkfs.c | 50 ++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 37 insertions(+), 13 deletions(-) + +diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c +index 18338a61..4bfdebf6 100644 +--- a/mkfs/xfs_mkfs.c ++++ b/mkfs/xfs_mkfs.c +@@ -1240,17 +1240,40 @@ done: + } + + static void +-discard_blocks(dev_t dev, uint64_t nsectors) ++discard_blocks(dev_t dev, uint64_t nsectors, int quiet) + { +- int fd; ++ int fd; ++ uint64_t offset = 0; ++ /* Discard the device 2G at a time */ ++ const uint64_t step = 2ULL << 30; ++ const uint64_t count = BBTOB(nsectors); + +- /* +- * We intentionally ignore errors from the discard ioctl. It is +- * not necessary for the mkfs functionality but just an optimization. +- */ + fd = libxfs_device_to_fd(dev); +- if (fd > 0) +- platform_discard_blocks(fd, 0, nsectors << 9); ++ if (fd <= 0) ++ return; ++ if (!quiet) { ++ printf("Discarding blocks..."); ++ fflush(stdout); ++ } ++ ++ /* The block discarding happens in smaller batches so it can be ++ * interrupted prematurely ++ */ ++ while (offset < count) { ++ uint64_t tmp_step = min(step, count - offset); ++ ++ /* ++ * We intentionally ignore errors from the discard ioctl. It is ++ * not necessary for the mkfs functionality but just an ++ * optimization. However we should stop on error. ++ */ ++ if (platform_discard_blocks(fd, offset, tmp_step)) ++ return; ++ ++ offset += tmp_step; ++ } ++ if (!quiet) ++ printf("Done.\n"); + } + + static __attribute__((noreturn)) void +@@ -2507,18 +2530,19 @@ open_devices( + + static void + discard_devices( +- struct libxfs_xinit *xi) ++ struct libxfs_xinit *xi, ++ int quiet) + { + /* + * This function has to be called after libxfs has been initialized. + */ + + if (!xi->disfile) +- discard_blocks(xi->ddev, xi->dsize); ++ discard_blocks(xi->ddev, xi->dsize, quiet); + if (xi->rtdev && !xi->risfile) +- discard_blocks(xi->rtdev, xi->rtsize); ++ discard_blocks(xi->rtdev, xi->rtsize, quiet); + if (xi->logdev && xi->logdev != xi->ddev && !xi->lisfile) +- discard_blocks(xi->logdev, xi->logBBsize); ++ discard_blocks(xi->logdev, xi->logBBsize, quiet); + } + + static void +@@ -3749,7 +3773,7 @@ main( + * All values have been validated, discard the old device layout. + */ + if (discard && !dry_run) +- discard_devices(&xi); ++ discard_devices(&xi, quiet); + + /* + * we need the libxfs buffer cache from here on in. +-- +2.17.0 + diff --git a/SOURCES/xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch b/SOURCES/xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch new file mode 100755 index 0000000..97c6402 --- /dev/null +++ b/SOURCES/xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch @@ -0,0 +1,56 @@ +From 2383d7c5cf20efcff75cb29ca3e02cfbe1bf2209 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Tue, 17 Dec 2019 16:52:39 -0500 +Subject: [PATCH] mkfs: tidy up discard notifications + +Only notify user of discard operations if the first one succeeds, +and be sure to print a trailing newline if we stop early. + +Signed-off-by: Eric Sandeen +Reviewed-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + mkfs/xfs_mkfs.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c +index 4bfdebf6..606f79da 100644 +--- a/mkfs/xfs_mkfs.c ++++ b/mkfs/xfs_mkfs.c +@@ -1251,10 +1251,6 @@ discard_blocks(dev_t dev, uint64_t nsectors, int quiet) + fd = libxfs_device_to_fd(dev); + if (fd <= 0) + return; +- if (!quiet) { +- printf("Discarding blocks..."); +- fflush(stdout); +- } + + /* The block discarding happens in smaller batches so it can be + * interrupted prematurely +@@ -1267,12 +1263,20 @@ discard_blocks(dev_t dev, uint64_t nsectors, int quiet) + * not necessary for the mkfs functionality but just an + * optimization. However we should stop on error. + */ +- if (platform_discard_blocks(fd, offset, tmp_step)) ++ if (platform_discard_blocks(fd, offset, tmp_step) == 0) { ++ if (offset == 0 && !quiet) { ++ printf("Discarding blocks..."); ++ fflush(stdout); ++ } ++ } else { ++ if (offset > 0 && !quiet) ++ printf("\n"); + return; ++ } + + offset += tmp_step; + } +- if (!quiet) ++ if (offset > 0 && !quiet) + printf("Done.\n"); + } + +-- +2.17.0 + diff --git a/SOURCES/xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch b/SOURCES/xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch new file mode 100755 index 0000000..a7b613f --- /dev/null +++ b/SOURCES/xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch @@ -0,0 +1,112 @@ +From 9d6023a856a1c4f84415dff59b0d5459cc8768db Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Thu, 27 Feb 2020 15:05:48 -0500 +Subject: [PATCH] libxfs: use FALLOC_FL_ZERO_RANGE in libxfs_device_zero + +I had a request from someone who cared about mkfs speed over +a slower network block device to look into using faster zeroing +methods, particularly for the log, during mkfs. + +Using FALLOC_FL_ZERO_RANGE is faster in this case than writing +a bunch of zeros across a wire. + +Signed-off-by: Eric Sandeen +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + include/builddefs.in | 3 +++ + include/linux.h | 22 ++++++++++++++++++++++ + libxfs/rdwr.c | 15 +++++++++++---- + 3 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/include/builddefs.in b/include/builddefs.in +index 4700b52..1dd27f7 100644 +--- a/include/builddefs.in ++++ b/include/builddefs.in +@@ -144,6 +144,9 @@ endif + ifeq ($(HAVE_GETFSMAP),yes) + PCFLAGS+= -DHAVE_GETFSMAP + endif ++ifeq ($(HAVE_FALLOCATE),yes) ++PCFLAGS += -DHAVE_FALLOCATE ++endif + + LIBICU_LIBS = @libicu_LIBS@ + LIBICU_CFLAGS = @libicu_CFLAGS@ +diff --git a/include/linux.h b/include/linux.h +index 8f3c32b..57726bb 100644 +--- a/include/linux.h ++++ b/include/linux.h +@@ -20,6 +20,10 @@ + #include + #include + #include ++#include ++#if defined(HAVE_FALLOCATE) ++#include ++#endif + #ifdef OVERRIDE_SYSTEM_FSXATTR + # define fsxattr sys_fsxattr + #endif +@@ -164,6 +168,24 @@ static inline void platform_mntent_close(struct mntent_cursor * cursor) + endmntent(cursor->mtabp); + } + ++#if defined(FALLOC_FL_ZERO_RANGE) ++static inline int ++platform_zero_range( ++ int fd, ++ xfs_off_t start, ++ size_t len) ++{ ++ int ret; ++ ++ ret = fallocate(fd, FALLOC_FL_ZERO_RANGE, start, len); ++ if (!ret) ++ return 0; ++ return -errno; ++} ++#else ++#define platform_zero_range(fd, s, l) (-EOPNOTSUPP) ++#endif ++ + /* + * Check whether we have to define FS_IOC_FS[GS]ETXATTR ourselves. These + * are a copy of the definitions moved to linux/uapi/fs.h in the 4.5 kernel, +diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c +index 0d9d720..e2d9d79 100644 +--- a/libxfs/rdwr.c ++++ b/libxfs/rdwr.c +@@ -61,8 +61,18 @@ libxfs_device_zero(struct xfs_buftarg *btp, xfs_daddr_t start, uint len) + { + xfs_off_t start_offset, end_offset, offset; + ssize_t zsize, bytes; ++ size_t len_bytes; + char *z; +- int fd; ++ int error, fd; ++ ++ fd = libxfs_device_to_fd(btp->dev); ++ start_offset = LIBXFS_BBTOOFF64(start); ++ ++ /* try to use special zeroing methods, fall back to writes if needed */ ++ len_bytes = LIBXFS_BBTOOFF64(len); ++ error = platform_zero_range(fd, start_offset, len_bytes); ++ if (!error) ++ return 0; + + zsize = min(BDSTRAT_SIZE, BBTOB(len)); + if ((z = memalign(libxfs_device_alignment(), zsize)) == NULL) { +@@ -73,9 +83,6 @@ libxfs_device_zero(struct xfs_buftarg *btp, xfs_daddr_t start, uint len) + } + memset(z, 0, zsize); + +- fd = libxfs_device_to_fd(btp->dev); +- start_offset = LIBXFS_BBTOOFF64(start); +- + if ((lseek(fd, start_offset, SEEK_SET)) < 0) { + fprintf(stderr, _("%s: %s seek to offset %llu failed: %s\n"), + progname, __FUNCTION__, +-- +2.9.5 + diff --git a/SOURCES/xfsprogs-5.5.0-xfs-use-a-struct-timespec64-for-the-in-core-crtime.patch b/SOURCES/xfsprogs-5.5.0-xfs-use-a-struct-timespec64-for-the-in-core-crtime.patch new file mode 100755 index 0000000..7856f2b --- /dev/null +++ b/SOURCES/xfsprogs-5.5.0-xfs-use-a-struct-timespec64-for-the-in-core-crtime.patch @@ -0,0 +1,123 @@ +From cb49e9a41477791af390a397c97da28da31fb81d Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +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 +Reviewed-by: Darrick J. Wong +[darrick: fix a minor indenting problem in xfs_trans_ichgtime] +Signed-off-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + +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 */ + }; + + /* diff --git a/SOURCES/xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch b/SOURCES/xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch new file mode 100755 index 0000000..92a2149 --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch @@ -0,0 +1,227 @@ +From 36dc471cc9bb17868b79cf8dea8151b207387539 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Tue, 26 May 2020 14:36:26 -0400 +Subject: [PATCH] xfs_quota: allow individual timer extension + +The only grace period which can be set via xfs_quota today is for id 0, +i.e. the default grace period for all users. However, setting an +individual grace period is useful; for example: + + Alice has a soft quota of 100 inodes, and a hard quota of 200 inodes + Alice uses 150 inodes, and enters a short grace period + Alice really needs to use those 150 inodes past the grace period + The administrator extends Alice's grace period until next Monday + +vfs quota users such as ext4 can do this today, with setquota -T + +xfs_quota can now accept an optional user id or name (symmetric with +how warn limits are specified), in which case that user's grace period +is extended to expire the given amount of time from now(). + +To maintain compatibility with old command lines, if none of +[-d|id|name] are specified, default limits are set as before. + +(kernelspace requires updates to enable all this as well.) + +Signed-off-by: Eric Sandeen +Reviewed-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + man/man8/xfs_quota.8 | 36 +++++++++++++++++-- + quota/edit.c | 83 +++++++++++++++++++++++++++++++++++++------- + 2 files changed, 104 insertions(+), 15 deletions(-) + +Index: xfsprogs-5.0.0/man/man8/xfs_quota.8 +=================================================================== +--- xfsprogs-5.0.0.orig/man/man8/xfs_quota.8 ++++ xfsprogs-5.0.0/man/man8/xfs_quota.8 +@@ -460,14 +460,46 @@ must be specified. + .B \-bir + ] + .I value ++[ ++.B -d ++| ++.I id ++| ++.I name ++] + .br + Allows the quota enforcement timeout (i.e. the amount of time allowed + to pass before the soft limits are enforced as the hard limits) to + be modified. The current timeout setting can be displayed using the + .B state +-command. The value argument is a number of seconds, but units of +-\&'minutes', 'hours', 'days', and 'weeks' are also understood ++command. ++.br ++When setting the default timer via the ++.B \-d ++option, or for ++.B id ++0, or if no argument is given after ++.I value ++the ++.I value ++argument is a number of seconds indicating the relative amount of time after ++soft limits are exceeded, before hard limits are enforced. ++.br ++When setting any other individual timer by ++.I id ++or ++.I name, ++the ++.I value ++is the number of seconds from now, at which time the hard limits will be enforced. ++This allows extending the grace time of an individual user who has exceeded soft ++limits. ++.br ++For ++.I value, ++units of \&'minutes', 'hours', 'days', and 'weeks' are also understood + (as are their abbreviations 'm', 'h', 'd', and 'w'). ++.br + .HP + .B warn + [ +Index: xfsprogs-5.0.0/quota/edit.c +=================================================================== +--- xfsprogs-5.0.0.orig/quota/edit.c ++++ xfsprogs-5.0.0/quota/edit.c +@@ -419,6 +419,7 @@ restore_f( + + static void + set_timer( ++ uint32_t id, + uint type, + uint mask, + char *dev, +@@ -427,14 +428,43 @@ set_timer( + fs_disk_quota_t d; + + memset(&d, 0, sizeof(d)); ++ ++ /* ++ * If id is specified we are extending grace time by value ++ * Otherwise we are setting the default grace time ++ */ ++ if (id) { ++ time_t now; ++ ++ /* Get quota to find out whether user is past soft limits */ ++ if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0) { ++ exitcode = 1; ++ fprintf(stderr, _("%s: cannot get quota: %s\n"), ++ progname, strerror(errno)); ++ return; ++ } ++ ++ time(&now); ++ ++ /* 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; ++ if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit) ++ d.d_itimer = now + value; ++ if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit) ++ d.d_rtbtimer = now + value; ++ } else { ++ d.d_btimer = value; ++ d.d_itimer = value; ++ d.d_rtbtimer = value; ++ } ++ + d.d_version = FS_DQUOT_VERSION; + d.d_flags = type; + d.d_fieldmask = mask; +- d.d_itimer = value; +- d.d_btimer = value; +- d.d_rtbtimer = value; ++ d.d_id = id; + +- if (xfsquotactl(XFS_SETQLIM, dev, type, 0, (void *)&d) < 0) { ++ if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) { + exitcode = 1; + fprintf(stderr, _("%s: cannot set timer: %s\n"), + progname, strerror(errno)); +@@ -447,10 +477,15 @@ timer_f( + char **argv) + { + uint value; +- int c, type = 0, mask = 0; ++ char *name = NULL; ++ uint32_t id = 0; ++ int c, flags = 0, type = 0, mask = 0; + +- while ((c = getopt(argc, argv, "bgipru")) != EOF) { ++ while ((c = getopt(argc, argv, "bdgipru")) != EOF) { + switch (c) { ++ case 'd': ++ flags |= DEFAULTS_FLAG; ++ break; + case 'b': + mask |= FS_DQ_BTIMER; + break; +@@ -474,23 +509,45 @@ timer_f( + } + } + +- if (argc != optind + 1) ++ /* ++ * Older versions of the command did not accept -d|id|name, ++ * so in that case we assume we're setting default timer, ++ * and the last arg is the timer value. ++ * ++ * Otherwise, if the defaults flag is set, we expect 1 more arg for ++ * timer value ; if not, 2 more args: 1 for value, one for id/name. ++ */ ++ if (!(flags & DEFAULTS_FLAG) && (argc == optind + 1)) { ++ value = cvttime(argv[optind++]); ++ } else if (flags & DEFAULTS_FLAG) { ++ if (argc != optind + 1) ++ return command_usage(&timer_cmd); ++ value = cvttime(argv[optind++]); ++ } else if (argc == optind + 2) { ++ value = cvttime(argv[optind++]); ++ name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++]; ++ } else + return command_usage(&timer_cmd); + +- value = cvttime(argv[optind++]); + ++ /* if none of -bir specified, set them all */ + if (!mask) + mask = FS_DQ_TIMER_MASK; + + if (!type) { + type = XFS_USER_QUOTA; + } else if (type != XFS_GROUP_QUOTA && +- type != XFS_PROJ_QUOTA && +- type != XFS_USER_QUOTA) { ++ type != XFS_PROJ_QUOTA && ++ type != XFS_USER_QUOTA) { + return command_usage(&timer_cmd); + } + +- set_timer(type, mask, fs_path->fs_name, value); ++ if (name) ++ id = id_from_string(name, type); ++ ++ if (id >= 0) ++ set_timer(id, type, mask, fs_path->fs_name, value); ++ + return 0; + } + +@@ -616,9 +673,9 @@ edit_init(void) + + timer_cmd.name = "timer"; + timer_cmd.cfunc = timer_f; +- timer_cmd.argmin = 2; ++ timer_cmd.argmin = 1; + timer_cmd.argmax = -1; +- timer_cmd.args = _("[-bir] [-g|-p|-u] value"); ++ timer_cmd.args = _("[-bir] [-g|-p|-u] value [-d|id|name]"); + timer_cmd.oneline = _("set quota enforcement timeouts"); + timer_cmd.help = timer_help; + timer_cmd.flags = CMD_FLAG_FOREIGN_OK; diff --git a/SOURCES/xfsprogs-5.7.0-xfs_quota-fix-unsigned-int-id-comparisons.patch b/SOURCES/xfsprogs-5.7.0-xfs_quota-fix-unsigned-int-id-comparisons.patch new file mode 100755 index 0000000..33a8860 --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_quota-fix-unsigned-int-id-comparisons.patch @@ -0,0 +1,69 @@ +From eaa5b0b79bcf2eb36f7a5e1a5b7171ad5ced7bac Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Fri, 10 Jul 2020 15:33:36 -0400 +Subject: [PATCH] xfs_quota: fix unsigned int id comparisons + +Fix compiler warnings about unsigned int comparisons by replacing them +with an explicit check for the one possible invalid value (-1U). +id_from_string sets exitcode to nonzero when it sees this value, so the +call sites don't have to do that. + +Coverity-id: 1463855, 1463856, 1463857 +Fixes: 67a73d6139d0 ("xfs_quota: refactor code to generate id from name") +Fixes: 36dc471cc9bb ("xfs_quota: allow individual timer extension") +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + quota/edit.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +Index: xfsprogs-5.0.0/quota/edit.c +=================================================================== +--- xfsprogs-5.0.0.orig/quota/edit.c ++++ xfsprogs-5.0.0/quota/edit.c +@@ -307,11 +307,11 @@ limit_f( + + + id = id_from_string(name, type); +- if (id >= 0) +- set_limits(id, type, mask, fs_path->fs_name, +- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); +- else +- exitcode = -1; ++ if (id == -1) ++ return 0; ++ ++ set_limits(id, type, mask, fs_path->fs_name, ++ &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); + return 0; + } + +@@ -545,9 +545,10 @@ timer_f( + if (name) + id = id_from_string(name, type); + +- if (id >= 0) +- set_timer(id, type, mask, fs_path->fs_name, value); ++ if (id == -1) ++ return 0; + ++ set_timer(id, type, mask, fs_path->fs_name, value); + return 0; + } + +@@ -642,11 +643,10 @@ warn_f( + } + + id = id_from_string(name, type); +- if (id >= 0) +- set_warnings(id, type, mask, fs_path->fs_name, value); +- else +- exitcode = -1; ++ if (id == -1) ++ return 0; + ++ set_warnings(id, type, mask, fs_path->fs_name, value); + return 0; + } + diff --git a/SOURCES/xfsprogs-5.7.0-xfs_quota-refactor-code-to-generate-id-from-name.patch b/SOURCES/xfsprogs-5.7.0-xfs_quota-refactor-code-to-generate-id-from-name.patch new file mode 100755 index 0000000..0223f44 --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_quota-refactor-code-to-generate-id-from-name.patch @@ -0,0 +1,271 @@ +From 67a73d6139d0336eb7ced05bd78a26b57f408187 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Tue, 26 May 2020 14:36:04 -0400 +Subject: [PATCH] xfs_quota: refactor code to generate id from name + +There's boilerplate for setting limits and warnings, where we have +a case statement for each of the 3 quota types, and from there call +3 different functions to configure each of the 3 types, each of which +calls its own version of id to string function... + +Refactor this so that the main function can call a generic id to string +conversion routine, and then call a common action. This save a lot of +LOC. + +I was looking at allowing xfs to bump out individual grace periods like +setquota can do, and this refactoring allows us to add new actions like +that without copying all the boilerplate again. + +Signed-off-by: Eric Sandeen +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + quota/edit.c | 194 +++++++++++++-------------------------------------- + 1 file changed, 49 insertions(+), 145 deletions(-) + +Index: xfsprogs-5.0.0/quota/edit.c +=================================================================== +--- xfsprogs-5.0.0.orig/quota/edit.c ++++ xfsprogs-5.0.0/quota/edit.c +@@ -101,6 +101,40 @@ warn_help(void) + "\n")); + } + ++static uint32_t ++id_from_string( ++ char *name, ++ int type) ++{ ++ uint32_t id = -1; ++ const char *type_name = "unknown type"; ++ ++ switch (type) { ++ case XFS_USER_QUOTA: ++ type_name = "user"; ++ id = uid_from_string(name); ++ break; ++ case XFS_GROUP_QUOTA: ++ type_name = "group"; ++ id = gid_from_string(name); ++ break; ++ case XFS_PROJ_QUOTA: ++ type_name = "project"; ++ id = prid_from_string(name); ++ break; ++ default: ++ ASSERT(0); ++ break; ++ } ++ ++ if (id == -1) { ++ fprintf(stderr, _("%s: invalid %s name: %s\n"), ++ type_name, progname, name); ++ exitcode = 1; ++ } ++ return id; ++} ++ + static void + set_limits( + uint32_t id, +@@ -135,75 +169,6 @@ set_limits( + } + } + +-static void +-set_user_limits( +- char *name, +- uint type, +- uint mask, +- uint64_t *bsoft, +- uint64_t *bhard, +- uint64_t *isoft, +- uint64_t *ihard, +- uint64_t *rtbsoft, +- uint64_t *rtbhard) +-{ +- uid_t uid = uid_from_string(name); +- +- if (uid == -1) { +- exitcode = 1; +- fprintf(stderr, _("%s: invalid user name: %s\n"), +- progname, name); +- } else +- set_limits(uid, type, mask, fs_path->fs_name, +- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard); +-} +- +-static void +-set_group_limits( +- char *name, +- uint type, +- uint mask, +- uint64_t *bsoft, +- uint64_t *bhard, +- uint64_t *isoft, +- uint64_t *ihard, +- uint64_t *rtbsoft, +- uint64_t *rtbhard) +-{ +- gid_t gid = gid_from_string(name); +- +- if (gid == -1) { +- exitcode = 1; +- fprintf(stderr, _("%s: invalid group name: %s\n"), +- progname, name); +- } else +- set_limits(gid, type, mask, fs_path->fs_name, +- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard); +-} +- +-static void +-set_project_limits( +- char *name, +- uint type, +- uint mask, +- uint64_t *bsoft, +- uint64_t *bhard, +- uint64_t *isoft, +- uint64_t *ihard, +- uint64_t *rtbsoft, +- uint64_t *rtbhard) +-{ +- prid_t prid = prid_from_string(name); +- +- if (prid == -1) { +- exitcode = 1; +- fprintf(stderr, _("%s: invalid project name: %s\n"), +- progname, name); +- } else +- set_limits(prid, type, mask, fs_path->fs_name, +- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard); +-} +- + /* extract number of blocks from an ascii string */ + static int + extractb( +@@ -258,6 +223,7 @@ limit_f( + char **argv) + { + char *name; ++ uint32_t id; + uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard; + int c, type = 0, mask = 0, flags = 0; + uint bsize, ssize, endoptions; +@@ -339,20 +305,13 @@ limit_f( + return command_usage(&limit_cmd); + } + +- switch (type) { +- case XFS_USER_QUOTA: +- set_user_limits(name, type, mask, +- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); +- break; +- case XFS_GROUP_QUOTA: +- set_group_limits(name, type, mask, +- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); +- break; +- case XFS_PROJ_QUOTA: +- set_project_limits(name, type, mask, +- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); +- break; +- } ++ ++ id = id_from_string(name, type); ++ if (id >= 0) ++ set_limits(id, type, mask, fs_path->fs_name, ++ &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard); ++ else ++ exitcode = -1; + return 0; + } + +@@ -561,63 +520,13 @@ set_warnings( + } + } + +-static void +-set_user_warnings( +- char *name, +- uint type, +- uint mask, +- uint value) +-{ +- uid_t uid = uid_from_string(name); +- +- if (uid == -1) { +- exitcode = 1; +- fprintf(stderr, _("%s: invalid user name: %s\n"), +- progname, name); +- } else +- set_warnings(uid, type, mask, fs_path->fs_name, value); +-} +- +-static void +-set_group_warnings( +- char *name, +- uint type, +- uint mask, +- uint value) +-{ +- gid_t gid = gid_from_string(name); +- +- if (gid == -1) { +- exitcode = 1; +- fprintf(stderr, _("%s: invalid group name: %s\n"), +- progname, name); +- } else +- set_warnings(gid, type, mask, fs_path->fs_name, value); +-} +- +-static void +-set_project_warnings( +- char *name, +- uint type, +- uint mask, +- uint value) +-{ +- prid_t prid = prid_from_string(name); +- +- if (prid == -1) { +- exitcode = 1; +- fprintf(stderr, _("%s: invalid project name: %s\n"), +- progname, name); +- } else +- set_warnings(prid, type, mask, fs_path->fs_name, value); +-} +- + static int + warn_f( + int argc, + char **argv) + { + char *name; ++ uint32_t id; + uint value; + int c, flags = 0, type = 0, mask = 0; + +@@ -675,17 +584,12 @@ warn_f( + return command_usage(&warn_cmd); + } + +- switch (type) { +- case XFS_USER_QUOTA: +- set_user_warnings(name, type, mask, value); +- break; +- case XFS_GROUP_QUOTA: +- set_group_warnings(name, type, mask, value); +- break; +- case XFS_PROJ_QUOTA: +- set_project_warnings(name, type, mask, value); +- break; +- } ++ id = id_from_string(name, type); ++ if (id >= 0) ++ set_warnings(id, type, mask, fs_path->fs_name, value); ++ else ++ exitcode = -1; ++ + return 0; + } + diff --git a/SOURCES/xfsprogs-5.7.0-xfs_repair-check-for-AG-btree-records-that-would-wra.patch b/SOURCES/xfsprogs-5.7.0-xfs_repair-check-for-AG-btree-records-that-would-wra.patch new file mode 100755 index 0000000..a0afd5c --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_repair-check-for-AG-btree-records-that-would-wra.patch @@ -0,0 +1,54 @@ +From cae4fd291266c32441c6a7fcca49929fe11c391c Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Fri, 10 Jul 2020 15:35:44 -0400 +Subject: [PATCH] xfs_repair: check for AG btree records that would wrap around + +For AG btree types, make sure that each record's length is not so huge +that integer wraparound would happen. + +Found via xfs/358 fuzzing recs[1].blockcount = ones. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + repair/scan.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/repair/scan.c b/repair/scan.c +index 5c8d8b23..1ddb5763 100644 +--- a/repair/scan.c ++++ b/repair/scan.c +@@ -684,7 +684,8 @@ _("%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), + b, i, name, agno, bno); + continue; + } +- if (len == 0 || !verify_agbno(mp, agno, end - 1)) { ++ if (len == 0 || end <= b || ++ !verify_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); +@@ -1066,7 +1067,8 @@ _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), + b, i, name, agno, bno); + continue; + } +- if (len == 0 || !verify_agbno(mp, agno, end - 1)) { ++ if (len == 0 || end <= b || ++ !verify_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); +@@ -1353,7 +1355,8 @@ _("leftover CoW extent has invalid startblock in record %u of %s btree block %u/ + b, i, name, agno, bno); + continue; + } +- if (len == 0 || !verify_agbno(mp, agno, end - 1)) { ++ if (len == 0 || end <= agb || ++ !verify_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); +-- +2.29.2 + diff --git a/SOURCES/xfsprogs-5.7.0-xfs_repair-complain-about-bad-interior-btree-pointer.patch b/SOURCES/xfsprogs-5.7.0-xfs_repair-complain-about-bad-interior-btree-pointer.patch new file mode 100755 index 0000000..62255ce --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_repair-complain-about-bad-interior-btree-pointer.patch @@ -0,0 +1,124 @@ +From 320cc3b263542e692c4978fb327efa591892ab37 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Fri, 10 Jul 2020 15:35:45 -0400 +Subject: [PATCH] xfs_repair: complain about bad interior btree pointers + +Actually complain about garbage btree node pointers, don't just silently +ignore them. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + libxfs/libxfs_api_defs.h | 1 + + repair/scan.c | 55 +++++++++++++++++++++++++++++----------- + 2 files changed, 41 insertions(+), 15 deletions(-) + +Index: xfsprogs-5.0.0/libxfs/libxfs_api_defs.h +=================================================================== +--- xfsprogs-5.0.0.orig/libxfs/libxfs_api_defs.h ++++ xfsprogs-5.0.0/libxfs/libxfs_api_defs.h +@@ -118,6 +118,7 @@ + #define xfs_symlink_blocks libxfs_symlink_blocks + #define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok + ++#define xfs_verify_agbno libxfs_verify_agbno + #define xfs_verify_cksum libxfs_verify_cksum + #define xfs_dinode_verify libxfs_dinode_verify + +Index: xfsprogs-5.0.0/repair/scan.c +=================================================================== +--- xfsprogs-5.0.0.orig/repair/scan.c ++++ xfsprogs-5.0.0/repair/scan.c +@@ -743,6 +743,14 @@ _("%s freespace btree block claimed (sta + for (i = 0; i < numrecs; i++) { + xfs_agblock_t agbno = be32_to_cpu(pp[i]); + ++ if (!libxfs_verify_agbno(mp, agno, agbno)) { ++ do_warn( ++ _("bad btree pointer (%u) in %sbt block %u/%u\n"), ++ agbno, name, agno, bno); ++ suspect++; ++ return; ++ } ++ + /* + * XXX - put sibling detection right here. + * we know our sibling chain is good. So as we go, +@@ -752,10 +760,8 @@ _("%s freespace btree block claimed (sta + * pointer mismatch, try and extract as much data + * as possible. + */ +- if (agbno != 0 && verify_agbno(mp, agno, agbno)) { +- scan_sbtree(agbno, level, agno, suspect, scan_allocbt, +- 0, magic, priv, ops); +- } ++ scan_sbtree(agbno, level, agno, suspect, scan_allocbt, 0, ++ magic, priv, ops); + } + } + +@@ -1196,10 +1202,16 @@ advance: + continue; + } + +- if (agbno != 0 && verify_agbno(mp, agno, agbno)) { +- scan_sbtree(agbno, level, agno, suspect, scan_rmapbt, 0, +- magic, priv, ops); ++ if (!libxfs_verify_agbno(mp, agno, agbno)) { ++ do_warn( ++ _("bad btree pointer (%u) in %sbt block %u/%u\n"), ++ agbno, name, agno, bno); ++ suspect++; ++ return; + } ++ ++ scan_sbtree(agbno, level, agno, suspect, scan_rmapbt, 0, magic, ++ priv, ops); + } + + out: +@@ -1416,10 +1428,16 @@ _("extent (%u/%u) len %u claimed, state + for (i = 0; i < numrecs; i++) { + xfs_agblock_t agbno = be32_to_cpu(pp[i]); + +- if (agbno != 0 && verify_agbno(mp, agno, agbno)) { +- scan_sbtree(agbno, level, agno, suspect, scan_refcbt, 0, +- magic, priv, ops); ++ if (!libxfs_verify_agbno(mp, agno, agbno)) { ++ do_warn( ++ _("bad btree pointer (%u) in %sbt block %u/%u\n"), ++ agbno, name, agno, bno); ++ suspect++; ++ return; + } ++ ++ scan_sbtree(agbno, level, agno, suspect, scan_refcbt, 0, magic, ++ priv, ops); + } + out: + if (suspect) +@@ -2083,11 +2101,18 @@ _("inode btree block claimed (state %d), + } + + for (i = 0; i < numrecs; i++) { +- if (be32_to_cpu(pp[i]) != 0 && verify_agbno(mp, agno, +- be32_to_cpu(pp[i]))) +- scan_sbtree(be32_to_cpu(pp[i]), level, agno, +- suspect, scan_inobt, 0, magic, priv, +- ops); ++ xfs_agblock_t agbno = be32_to_cpu(pp[i]); ++ ++ if (!libxfs_verify_agbno(mp, agno, agbno)) { ++ do_warn( ++ _("bad btree pointer (%u) in %sbt block %u/%u\n"), ++ agbno, name, agno, bno); ++ suspect++; ++ return; ++ } ++ ++ scan_sbtree(be32_to_cpu(pp[i]), level, agno, suspect, ++ scan_inobt, 0, magic, priv, ops); + } + } + diff --git a/SOURCES/xfsprogs-5.7.0-xfs_repair-convert-to-libxfs_verify_agbno.patch b/SOURCES/xfsprogs-5.7.0-xfs_repair-convert-to-libxfs_verify_agbno.patch new file mode 100755 index 0000000..1787328 --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_repair-convert-to-libxfs_verify_agbno.patch @@ -0,0 +1,209 @@ +From dcd6c2e1490ba5c59c14ca8ea843ca36048888b8 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Fri, 10 Jul 2020 15:35:45 -0400 +Subject: [PATCH] xfs_repair: convert to libxfs_verify_agbno + +Convert the homegrown verify_agbno callers to use the libxfs function, +as needed. In some places we drop the "bno != 0" checks because those +conditionals are checking btree roots; btree roots should never be +zero if the corresponding feature bit is set; and repair skips the if +clause entirely if the feature bit is disabled. + +In effect, this strengthens repair to validate that AG btree pointers +neither point to the AG headers nor past the end of the AG. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + libxfs/libxfs_api_defs.h | 1 + + repair/dinode.c | 11 ----------- + repair/dinode.h | 5 ----- + repair/scan.c | 36 +++++++++++++++++++++++------------- + 4 files changed, 24 insertions(+), 29 deletions(-) + +Index: xfsprogs-5.0.0/libxfs/libxfs_api_defs.h +=================================================================== +--- xfsprogs-5.0.0.orig/libxfs/libxfs_api_defs.h ++++ xfsprogs-5.0.0/libxfs/libxfs_api_defs.h +@@ -121,6 +121,7 @@ + #define xfs_verify_agbno libxfs_verify_agbno + #define xfs_verify_cksum libxfs_verify_cksum + #define xfs_dinode_verify libxfs_dinode_verify ++#define xfs_ag_block_count libxfs_ag_block_count + + #define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable + #define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs +Index: xfsprogs-5.0.0/repair/dinode.c +=================================================================== +--- xfsprogs-5.0.0.orig/repair/dinode.c ++++ xfsprogs-5.0.0/repair/dinode.c +@@ -284,17 +284,6 @@ verify_dfsbno_range(xfs_mount_t *mp, + return (XR_DFSBNORANGE_VALID); + } + +-int +-verify_agbno(xfs_mount_t *mp, +- xfs_agnumber_t agno, +- xfs_agblock_t agbno) +-{ +- xfs_sb_t *sbp = &mp->m_sb;; +- +- /* range check ag #, ag block. range-checking offset is pointless */ +- return verify_ag_bno(sbp, agno, agbno) == 0; +-} +- + static int + process_rt_rec( + xfs_mount_t *mp, +Index: xfsprogs-5.0.0/repair/dinode.h +=================================================================== +--- xfsprogs-5.0.0.orig/repair/dinode.h ++++ xfsprogs-5.0.0/repair/dinode.h +@@ -10,11 +10,6 @@ struct blkmap; + struct prefetch_args; + + int +-verify_agbno(xfs_mount_t *mp, +- xfs_agnumber_t agno, +- xfs_agblock_t agbno); +- +-int + verify_dfsbno(xfs_mount_t *mp, + xfs_fsblock_t fsbno); + +Index: xfsprogs-5.0.0/repair/scan.c +=================================================================== +--- xfsprogs-5.0.0.orig/repair/scan.c ++++ xfsprogs-5.0.0/repair/scan.c +@@ -642,14 +642,14 @@ _("%s freespace btree block claimed (sta + len = be32_to_cpu(rp[i].ar_blockcount); + end = b + len; + +- if (b == 0 || !verify_agbno(mp, agno, b)) { ++ if (!libxfs_verify_agbno(mp, agno, b)) { + do_warn( + _("invalid start block %u in record %u of %s btree block %u/%u\n"), + b, i, name, agno, bno); + continue; + } + if (len == 0 || end <= b || +- !verify_agbno(mp, agno, end - 1)) { ++ !libxfs_verify_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); +@@ -914,6 +914,16 @@ rmap_in_order( + return offset > lastoffset; + } + ++static inline bool ++verify_rmap_agbno( ++ struct xfs_mount *mp, ++ xfs_agnumber_t agno, ++ xfs_agblock_t agbno) ++{ ++ return agbno < libxfs_ag_block_count(mp, agno); ++} ++ ++ + static void + scan_rmapbt( + struct xfs_btree_block *block, +@@ -1031,14 +1041,14 @@ _("%s rmap btree block claimed (state %d + end = key.rm_startblock + key.rm_blockcount; + + /* Make sure agbno & len make sense. */ +- if (!verify_agbno(mp, agno, b)) { ++ if (!verify_rmap_agbno(mp, agno, b)) { + do_warn( + _("invalid start block %u in record %u of %s btree block %u/%u\n"), + b, i, name, agno, bno); + continue; + } + if (len == 0 || end <= b || +- !verify_agbno(mp, agno, end - 1)) { ++ !verify_rmap_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); +@@ -1325,14 +1335,14 @@ _("leftover CoW extent has invalid start + } + end = agb + len; + +- if (!verify_agbno(mp, agno, agb)) { ++ if (!libxfs_verify_agbno(mp, agno, agb)) { + do_warn( + _("invalid start block %u in record %u of %s btree block %u/%u\n"), + b, i, name, agno, bno); + continue; + } + if (len == 0 || end <= agb || +- !verify_agbno(mp, agno, end - 1)) { ++ !libxfs_verify_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); +@@ -2145,7 +2155,7 @@ scan_agfl( + { + struct agfl_state *as = priv; + +- if (verify_agbno(mp, as->agno, bno)) ++ if (libxfs_verify_agbno(mp, as->agno, bno)) + set_bmap(as->agno, bno, XR_E_FREE); + else + do_warn(_("bad agbno %u in agfl, agno %d\n"), +@@ -2217,7 +2227,7 @@ validate_agf( + uint32_t magic; + + bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]); +- if (bno != 0 && verify_agbno(mp, agno, bno)) { ++ if (libxfs_verify_agbno(mp, agno, bno)) { + magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTB_CRC_MAGIC + : XFS_ABTB_MAGIC; + scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]), +@@ -2229,7 +2239,7 @@ validate_agf( + } + + bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]); +- if (bno != 0 && verify_agbno(mp, agno, bno)) { ++ if (libxfs_verify_agbno(mp, agno, bno)) { + magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTC_CRC_MAGIC + : XFS_ABTC_MAGIC; + scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]), +@@ -2249,7 +2259,7 @@ validate_agf( + priv.last_rec.rm_owner = XFS_RMAP_OWN_UNKNOWN; + priv.nr_blocks = 0; + bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); +- if (bno != 0 && verify_agbno(mp, agno, bno)) { ++ if (libxfs_verify_agbno(mp, agno, bno)) { + scan_sbtree(bno, + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]), + agno, 0, scan_rmapbt, 1, XFS_RMAP_CRC_MAGIC, +@@ -2267,7 +2277,7 @@ validate_agf( + + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + bno = be32_to_cpu(agf->agf_refcount_root); +- if (bno != 0 && verify_agbno(mp, agno, bno)) { ++ if (libxfs_verify_agbno(mp, agno, bno)) { + struct refc_priv priv; + + memset(&priv, 0, sizeof(priv)); +@@ -2315,7 +2325,7 @@ validate_agi( + uint32_t magic; + + bno = be32_to_cpu(agi->agi_root); +- if (bno != 0 && verify_agbno(mp, agno, bno)) { ++ if (libxfs_verify_agbno(mp, agno, bno)) { + magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC + : XFS_IBT_MAGIC; + scan_sbtree(bno, be32_to_cpu(agi->agi_level), +@@ -2328,7 +2338,7 @@ validate_agi( + + if (xfs_sb_version_hasfinobt(&mp->m_sb)) { + bno = be32_to_cpu(agi->agi_free_root); +- if (bno != 0 && verify_agbno(mp, agno, bno)) { ++ if (libxfs_verify_agbno(mp, agno, bno)) { + 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), diff --git a/SOURCES/xfsprogs-5.7.0-xfs_repair-fix-rebuilding-btree-block-less-than-minr.patch b/SOURCES/xfsprogs-5.7.0-xfs_repair-fix-rebuilding-btree-block-less-than-minr.patch new file mode 100755 index 0000000..9192518 --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_repair-fix-rebuilding-btree-block-less-than-minr.patch @@ -0,0 +1,290 @@ +From 6df28d12d7760701c9d11e659e374665c5ffd0b9 Mon Sep 17 00:00:00 2001 +From: Gao Xiang +Date: Fri, 10 Jul 2020 15:32:36 -0400 +Subject: [PATCH] xfs_repair: fix rebuilding btree block less than minrecs + +In production, we found that sometimes xfs_repair phase 5 +rebuilds freespace node block with pointers less than minrecs +and if we trigger xfs_repair again it would report such +the following message: + +bad btree nrecs (39, min=40, max=80) in btbno block 0/7882 + +The background is that xfs_repair starts to rebuild AGFL +after the freespace btree is settled in phase 5 so we may +need to leave necessary room in advance for each btree +leaves in order to avoid freespace btree split and then +result in AGFL rebuild fails. The old mathematics uses +ceil(num_extents / maxrecs) to decide the number of node +blocks. That would be fine without leaving extra space +since minrecs = maxrecs / 2 but if some slack was decreased +from maxrecs, the result would be larger than what is +expected and cause num_recs_pb less than minrecs, i.e: + +num_extents = 79, adj_maxrecs = 80 - 2 (slack) = 78 + +so we'd get + +num_blocks = ceil(79 / 78) = 2, +num_recs_pb = 79 / 2 = 39, which is less than +minrecs = 80 / 2 = 40 + +OTOH, btree bulk loading code behaves in a different way. +As in xfs_btree_bload_level_geometry it wrote + +num_blocks = floor(num_extents / maxrecs) + +which will never go below minrecs. And when it goes above +maxrecs, just increment num_blocks and recalculate so we +can get the reasonable results. + +Later, btree bulk loader will replace the current repair code. +But we may still want to look for a backportable solution +for stable versions. Hence, keep the same logic to avoid +the freespace as well as rmap btree minrecs underflow for now. + +Cc: "Darrick J. Wong" +Cc: Dave Chinner +Cc: Eric Sandeen +Fixes: 9851fd79bfb1 ("repair: AGFL rebuild fails if btree split required") +Signed-off-by: Gao Xiang +Reviewed-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + repair/phase5.c | 152 ++++++++++++++++++++---------------------------- + 1 file changed, 63 insertions(+), 89 deletions(-) + +Index: xfsprogs-5.0.0/repair/phase5.c +=================================================================== +--- xfsprogs-5.0.0.orig/repair/phase5.c ++++ xfsprogs-5.0.0/repair/phase5.c +@@ -346,11 +346,32 @@ finish_cursor(bt_status_t *curs) + * failure at runtime. Hence leave a couple of records slack space in + * each block to allow immediate modification of the tree without + * requiring splits to be done. +- * +- * XXX(hch): any reason we don't just look at mp->m_alloc_mxr? + */ +-#define XR_ALLOC_BLOCK_MAXRECS(mp, level) \ +- (libxfs_allocbt_maxrecs((mp), (mp)->m_sb.sb_blocksize, (level) == 0) - 2) ++static void ++compute_level_geometry( ++ struct xfs_mount *mp, ++ struct bt_stat_level *lptr, ++ uint64_t nr_this_level, ++ int slack, ++ bool leaf) ++{ ++ unsigned int maxrecs = mp->m_alloc_mxr[!leaf]; ++ unsigned int desired_npb; ++ ++ desired_npb = max(mp->m_alloc_mnr[!leaf], maxrecs - slack); ++ lptr->num_recs_tot = nr_this_level; ++ lptr->num_blocks = max(1ULL, nr_this_level / desired_npb); ++ ++ lptr->num_recs_pb = nr_this_level / lptr->num_blocks; ++ lptr->modulo = nr_this_level % lptr->num_blocks; ++ if (lptr->num_recs_pb > maxrecs || ++ (lptr->num_recs_pb == maxrecs && lptr->modulo)) { ++ lptr->num_blocks++; ++ ++ lptr->num_recs_pb = nr_this_level / lptr->num_blocks; ++ lptr->modulo = nr_this_level % lptr->num_blocks; ++ } ++} + + /* + * this calculates a freespace cursor for an ag. +@@ -368,6 +389,7 @@ calculate_freespace_cursor(xfs_mount_t * + int i; + int extents_used; + int extra_blocks; ++ uint64_t old_blocks; + bt_stat_level_t *lptr; + bt_stat_level_t *p_lptr; + extent_tree_node_t *ext_ptr; +@@ -386,10 +408,7 @@ calculate_freespace_cursor(xfs_mount_t * + * of the tree and set up the cursor for the leaf level + * (note that the same code is duplicated further down) + */ +- lptr->num_blocks = howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0)); +- lptr->num_recs_pb = num_extents / lptr->num_blocks; +- lptr->modulo = num_extents % lptr->num_blocks; +- lptr->num_recs_tot = num_extents; ++ compute_level_geometry(mp, lptr, num_extents, 2, true); + level = 1; + + #ifdef XR_BLD_FREE_TRACE +@@ -403,30 +422,23 @@ calculate_freespace_cursor(xfs_mount_t * + * if we need more levels, set them up. # of records + * per level is the # of blocks in the level below it + */ +- if (lptr->num_blocks > 1) { +- for (; btree_curs->level[level - 1].num_blocks > 1 +- && level < XFS_BTREE_MAXLEVELS; +- level++) { +- lptr = &btree_curs->level[level]; +- p_lptr = &btree_curs->level[level - 1]; +- lptr->num_blocks = howmany(p_lptr->num_blocks, +- XR_ALLOC_BLOCK_MAXRECS(mp, level)); +- lptr->modulo = p_lptr->num_blocks +- % lptr->num_blocks; +- lptr->num_recs_pb = p_lptr->num_blocks +- / lptr->num_blocks; +- lptr->num_recs_tot = p_lptr->num_blocks; ++ while (lptr->num_blocks > 1) { ++ p_lptr = lptr; ++ lptr = &btree_curs->level[level]; ++ ++ compute_level_geometry(mp, lptr, ++ p_lptr->num_blocks, 0, false); + #ifdef XR_BLD_FREE_TRACE +- fprintf(stderr, "%s %d %d %d %d %d\n", __func__, +- level, +- lptr->num_blocks, +- lptr->num_recs_pb, +- lptr->modulo, +- lptr->num_recs_tot); ++ fprintf(stderr, "%s %d %d %d %d %d\n", __func__, ++ level, ++ lptr->num_blocks, ++ lptr->num_recs_pb, ++ lptr->modulo, ++ lptr->num_recs_tot); + #endif +- } ++ level++; + } +- ++ ASSERT(level < XFS_BTREE_MAXLEVELS); + ASSERT(lptr->num_blocks == 1); + btree_curs->num_levels = level; + +@@ -494,8 +506,11 @@ calculate_freespace_cursor(xfs_mount_t * + * see if the number of leaf blocks will change as a result + * of the number of extents changing + */ +- if (howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0)) +- != btree_curs->level[0].num_blocks) { ++ old_blocks = btree_curs->level[0].num_blocks; ++ compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, true); ++ extra_blocks = 0; ++ ++ if (old_blocks != btree_curs->level[0].num_blocks) { + /* + * yes -- recalculate the cursor. If the number of + * excess (overallocated) blocks is < xfs_agfl_size/2, we're ok. +@@ -551,31 +566,19 @@ calculate_freespace_cursor(xfs_mount_t * + } + + lptr = &btree_curs->level[0]; +- lptr->num_blocks = howmany(num_extents, +- XR_ALLOC_BLOCK_MAXRECS(mp, 0)); +- lptr->num_recs_pb = num_extents / lptr->num_blocks; +- lptr->modulo = num_extents % lptr->num_blocks; +- lptr->num_recs_tot = num_extents; + level = 1; + + /* + * if we need more levels, set them up + */ +- if (lptr->num_blocks > 1) { +- for (level = 1; btree_curs->level[level-1].num_blocks +- > 1 && level < XFS_BTREE_MAXLEVELS; +- level++) { +- lptr = &btree_curs->level[level]; +- p_lptr = &btree_curs->level[level-1]; +- lptr->num_blocks = howmany(p_lptr->num_blocks, +- XR_ALLOC_BLOCK_MAXRECS(mp, level)); +- lptr->modulo = p_lptr->num_blocks +- % lptr->num_blocks; +- lptr->num_recs_pb = p_lptr->num_blocks +- / lptr->num_blocks; +- lptr->num_recs_tot = p_lptr->num_blocks; +- } ++ while (lptr->num_blocks > 1) { ++ p_lptr = lptr; ++ lptr = &btree_curs->level[level++]; ++ ++ compute_level_geometry(mp, lptr, ++ p_lptr->num_blocks, 0, false); + } ++ ASSERT(level < XFS_BTREE_MAXLEVELS); + ASSERT(lptr->num_blocks == 1); + btree_curs->num_levels = level; + +@@ -589,22 +592,6 @@ calculate_freespace_cursor(xfs_mount_t * + + ASSERT(blocks_allocated_total >= blocks_needed); + extra_blocks = blocks_allocated_total - blocks_needed; +- } else { +- if (extents_used > 0) { +- /* +- * reset the leaf level geometry to account +- * for consumed extents. we can leave the +- * rest of the cursor alone since the number +- * of leaf blocks hasn't changed. +- */ +- lptr = &btree_curs->level[0]; +- +- lptr->num_recs_pb = num_extents / lptr->num_blocks; +- lptr->modulo = num_extents % lptr->num_blocks; +- lptr->num_recs_tot = num_extents; +- } +- +- extra_blocks = 0; + } + + btree_curs->num_tot_blocks = blocks_allocated_pt; +@@ -1335,7 +1322,6 @@ init_rmapbt_cursor( + struct bt_stat_level *lptr; + struct bt_stat_level *p_lptr; + xfs_extlen_t blocks_allocated; +- int maxrecs; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) { + memset(btree_curs, 0, sizeof(struct bt_status)); +@@ -1371,32 +1357,20 @@ init_rmapbt_cursor( + * Leave enough slack in the rmapbt that we can insert the + * metadata AG entries without too many splits. + */ +- maxrecs = mp->m_rmap_mxr[0]; +- if (num_recs > maxrecs) +- maxrecs -= 10; +- blocks_allocated = lptr->num_blocks = howmany(num_recs, maxrecs); +- +- lptr->modulo = num_recs % lptr->num_blocks; +- lptr->num_recs_pb = num_recs / lptr->num_blocks; +- lptr->num_recs_tot = num_recs; ++ compute_level_geometry(mp, lptr, num_recs, ++ num_recs > mp->m_rmap_mxr[0] ? 10 : 0, true); ++ blocks_allocated = lptr->num_blocks; + level = 1; + +- if (lptr->num_blocks > 1) { +- for (; btree_curs->level[level-1].num_blocks > 1 +- && level < XFS_BTREE_MAXLEVELS; +- level++) { +- lptr = &btree_curs->level[level]; +- p_lptr = &btree_curs->level[level - 1]; +- lptr->num_blocks = howmany(p_lptr->num_blocks, +- mp->m_rmap_mxr[1]); +- lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; +- lptr->num_recs_pb = p_lptr->num_blocks +- / lptr->num_blocks; +- lptr->num_recs_tot = p_lptr->num_blocks; +- +- blocks_allocated += lptr->num_blocks; +- } ++ while (lptr->num_blocks > 1) { ++ p_lptr = lptr; ++ lptr = &btree_curs->level[level++]; ++ ++ compute_level_geometry(mp, lptr, ++ p_lptr->num_blocks, 0, false); ++ blocks_allocated += lptr->num_blocks; + } ++ ASSERT(level < XFS_BTREE_MAXLEVELS); + ASSERT(lptr->num_blocks == 1); + btree_curs->num_levels = level; + diff --git a/SOURCES/xfsprogs-5.7.0-xfs_repair-tag-inobt-vs-finobt-errors-properly.patch b/SOURCES/xfsprogs-5.7.0-xfs_repair-tag-inobt-vs-finobt-errors-properly.patch new file mode 100755 index 0000000..82a1e3b --- /dev/null +++ b/SOURCES/xfsprogs-5.7.0-xfs_repair-tag-inobt-vs-finobt-errors-properly.patch @@ -0,0 +1,88 @@ +From 08280b4b6efd317c673c6718a27d77e702d0480d Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Fri, 10 Jul 2020 15:35:45 -0400 +Subject: [PATCH] xfs_repair: tag inobt vs finobt errors properly + +Amend the generic inode btree block scanner function to tag correctly +which tree it's complaining about. Previously, dubious finobt headers +would be attributed to the "inode btree", which is at best ambiguous +and misleading at worst. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + repair/scan.c | 36 ++++++++++++++++++++++++++---------- + 1 file changed, 26 insertions(+), 10 deletions(-) + +Index: xfsprogs-5.0.0/repair/scan.c +=================================================================== +--- xfsprogs-5.0.0.orig/repair/scan.c ++++ xfsprogs-5.0.0/repair/scan.c +@@ -1934,6 +1934,7 @@ scan_inobt( + const struct xfs_buf_ops *ops) + { + struct aghdr_cnts *agcnts = priv; ++ char *name; + int i; + int numrecs; + int state; +@@ -1944,17 +1945,32 @@ scan_inobt( + + hdr_errors = 0; + ++ switch (magic) { ++ case XFS_FIBT_MAGIC: ++ case XFS_FIBT_CRC_MAGIC: ++ name = "fino"; ++ break; ++ case XFS_IBT_MAGIC: ++ case XFS_IBT_CRC_MAGIC: ++ name = "ino"; ++ break; ++ default: ++ name = "(unknown)"; ++ assert(0); ++ break; ++ } ++ + if (be32_to_cpu(block->bb_magic) != magic) { +- do_warn(_("bad magic # %#x in inobt block %d/%d\n"), +- be32_to_cpu(block->bb_magic), agno, bno); ++ do_warn(_("bad magic # %#x in %sbt block %d/%d\n"), ++ be32_to_cpu(block->bb_magic), name, agno, bno); + hdr_errors++; + bad_ino_btree = 1; + if (suspect) + return; + } + if (be16_to_cpu(block->bb_level) != level) { +- do_warn(_("expected level %d got %d in inobt block %d/%d\n"), +- level, be16_to_cpu(block->bb_level), agno, bno); ++ do_warn(_("expected level %d got %d in %sbt block %d/%d\n"), ++ level, be16_to_cpu(block->bb_level), name, agno, bno); + hdr_errors++; + bad_ino_btree = 1; + if (suspect) +@@ -1976,8 +1992,8 @@ scan_inobt( + default: + set_bmap(agno, bno, XR_E_MULT); + do_warn( +-_("inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), +- state, agno, bno, suspect); ++_("%sbt btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), ++ name, state, agno, bno, suspect); + } + + numrecs = be16_to_cpu(block->bb_numrecs); +@@ -1999,8 +2015,8 @@ _("inode btree block claimed (state %d), + + if (hdr_errors) { + bad_ino_btree = 1; +- do_warn(_("dubious inode btree block header %d/%d\n"), +- agno, bno); ++ do_warn(_("dubious %sbt btree block header %d/%d\n"), ++ name, agno, bno); + suspect++; + } + diff --git a/SOURCES/xfsprogs-5.8.0-xfs_db-short-circuit-type_f-if-type-is-unchanged.patch b/SOURCES/xfsprogs-5.8.0-xfs_db-short-circuit-type_f-if-type-is-unchanged.patch new file mode 100755 index 0000000..784ad1e --- /dev/null +++ b/SOURCES/xfsprogs-5.8.0-xfs_db-short-circuit-type_f-if-type-is-unchanged.patch @@ -0,0 +1,31 @@ +From 7b4a7b3f6bce91be45b54fc68e169cb756dc8c74 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Mon, 24 Aug 2020 12:47:47 -0400 +Subject: [PATCH] xfs_db: short circuit type_f if type is unchanged + +There's no reason to go through the type change code if the +type has not been changed. + +Signed-off-by: Eric Sandeen +Reviewed-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + db/type.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/db/type.c b/db/type.c +index 3cb1e868..572ac6d6 100644 +--- a/db/type.c ++++ b/db/type.c +@@ -216,6 +216,8 @@ type_f( + tt = findtyp(argv[1]); + if (tt == NULL) { + dbprintf(_("no such type %s\n"), argv[1]); ++ } else if (iocur_top->typ == tt) { ++ return 0; + } else { + if (iocur_top->typ == NULL) + dbprintf(_("no current object\n")); +-- +2.29.2 + diff --git a/SOURCES/xfsprogs-5.8.0-xfs_quota-command-error-message-improvement.patch b/SOURCES/xfsprogs-5.8.0-xfs_quota-command-error-message-improvement.patch new file mode 100755 index 0000000..eeec56c --- /dev/null +++ b/SOURCES/xfsprogs-5.8.0-xfs_quota-command-error-message-improvement.patch @@ -0,0 +1,76 @@ +From ca42fa70929e88781e7daeee4cf4588adb834661 Mon Sep 17 00:00:00 2001 +From: Bill O'Donnell +Date: Mon, 24 Aug 2020 13:23:23 -0400 +Subject: [PATCH] xfs_quota: command error message improvement + +Make the error messages for rudimentary xfs_quota commands +(off, enable, disable) more user friendly, instead of the +terse sys error outputs. + +Signed-off-by: Bill O'Donnell +Reviewed-by: Darrick J. Wong +Signed-off-by: Eric Sandeen +--- + quota/state.c | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/quota/state.c b/quota/state.c +index 8f9718f1..7a595fc6 100644 +--- a/quota/state.c ++++ b/quota/state.c +@@ -306,8 +306,16 @@ enable_enforcement( + return; + } + dir = mount->fs_name; +- if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) +- perror("XFS_QUOTAON"); ++ if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) { ++ if (errno == EEXIST) ++ fprintf(stderr, ++ _("Quota enforcement already enabled.\n")); ++ else if (errno == EINVAL || errno == ENOSYS) ++ fprintf(stderr, ++ _("Can't enable enforcement when quota off.\n")); ++ else ++ perror("XFS_QUOTAON"); ++ } + else if (flags & VERBOSE_FLAG) + state_quotafile_mount(stdout, type, mount, flags); + } +@@ -328,8 +336,16 @@ disable_enforcement( + return; + } + dir = mount->fs_name; +- if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) +- perror("XFS_QUOTAOFF"); ++ if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { ++ if (errno == EEXIST) ++ fprintf(stderr, ++ _("Quota enforcement already disabled.\n")); ++ else if (errno == EINVAL || errno == ENOSYS) ++ fprintf(stderr, ++ _("Can't disable enforcement when quota off.\n")); ++ else ++ perror("XFS_QUOTAOFF"); ++ } + else if (flags & VERBOSE_FLAG) + state_quotafile_mount(stdout, type, mount, flags); + } +@@ -350,8 +366,12 @@ quotaoff( + return; + } + dir = mount->fs_name; +- if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) +- perror("XFS_QUOTAOFF"); ++ if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { ++ if (errno == EEXIST || errno == ENOSYS) ++ fprintf(stderr, _("Quota already off.\n")); ++ else ++ perror("XFS_QUOTAOFF"); ++ } + else if (flags & VERBOSE_FLAG) + state_quotafile_mount(stdout, type, mount, flags); + } +-- +2.31.1 + diff --git a/SOURCES/xfsprogs-5.8.0-xfs_quota-display-warning-limits-when-printing-quota.patch b/SOURCES/xfsprogs-5.8.0-xfs_quota-display-warning-limits-when-printing-quota.patch new file mode 100755 index 0000000..f9f274b --- /dev/null +++ b/SOURCES/xfsprogs-5.8.0-xfs_quota-display-warning-limits-when-printing-quota.patch @@ -0,0 +1,52 @@ +From 387a96e12a937c1b2ee29a0f2c52245d6a283078 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 24 Aug 2020 13:23:32 -0400 +Subject: [PATCH] xfs_quota: display warning limits when printing quota type + information + +We should dump the default warning limits when we're printing quota +information. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + quota/state.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/quota/state.c b/quota/state.c +index 7a595fc6..1627181d 100644 +--- a/quota/state.c ++++ b/quota/state.c +@@ -130,6 +130,16 @@ state_timelimit( + time_to_string(timelimit, VERBOSE_FLAG | ABSOLUTE_FLAG)); + } + ++static void ++state_warnlimit( ++ FILE *fp, ++ uint form, ++ uint16_t warnlimit) ++{ ++ fprintf(fp, _("%s max warnings: %u\n"), ++ form_to_string(form), warnlimit); ++} ++ + /* + * fs_quota_stat holds a subset of fs_quota_statv; this copies + * the smaller into the larger, leaving any not-present fields +@@ -218,7 +228,11 @@ state_quotafile_mount( + sv.qs_flags & XFS_QUOTA_PDQ_ENFD); + + state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit); ++ state_warnlimit(fp, XFS_BLOCK_QUOTA, sv.qs_bwarnlimit); ++ + state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit); ++ state_warnlimit(fp, XFS_INODE_QUOTA, sv.qs_iwarnlimit); ++ + state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit); + } + +-- +2.31.1 + diff --git a/SOURCES/xfsprogs-5.8.0-xfs_quota-state-command-should-report-ugp-grace-time.patch b/SOURCES/xfsprogs-5.8.0-xfs_quota-state-command-should-report-ugp-grace-time.patch new file mode 100755 index 0000000..750be1b --- /dev/null +++ b/SOURCES/xfsprogs-5.8.0-xfs_quota-state-command-should-report-ugp-grace-time.patch @@ -0,0 +1,141 @@ +From d8a9454608ff97e98fb7de0da28f8d40804d2296 Mon Sep 17 00:00:00 2001 +From: Bill O'Donnell +Date: Mon, 24 Aug 2020 13:23:43 -0400 +Subject: [PATCH] xfs_quota: state command should report ugp grace times + +Since grace periods are now supported for three quota types (ugp), +modify xfs_quota state command to report times for all three. +Add a helper function for stat reporting. + +Signed-off-by: Bill O'Donnell +Reviewed-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + quota/state.c | 96 +++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 67 insertions(+), 29 deletions(-) + +diff --git a/quota/state.c b/quota/state.c +index 1627181d..19d34ed0 100644 +--- a/quota/state.c ++++ b/quota/state.c +@@ -191,49 +191,87 @@ state_stat_to_statv( + } + + static void +-state_quotafile_mount( ++state_quotafile_stat( + FILE *fp, + uint type, +- struct fs_path *mount, ++ struct fs_path *mount, ++ struct fs_quota_statv *sv, ++ struct fs_quota_stat *s, + uint flags) + { +- struct fs_quota_stat s; +- struct fs_quota_statv sv; ++ bool accounting, enforcing; ++ struct fs_qfilestatv *qsv; + char *dev = mount->fs_name; + +- sv.qs_version = FS_QSTATV_VERSION1; +- +- if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)&sv) < 0) { +- if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)&s) < 0) { ++ if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)sv) < 0) { ++ if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)s) < 0) { + if (flags & VERBOSE_FLAG) + fprintf(fp, + _("%s quota are not enabled on %s\n"), + type_to_string(type), dev); + return; + } +- state_stat_to_statv(&s, &sv); ++ state_stat_to_statv(s, sv); ++ } ++ ++ switch(type) { ++ case XFS_USER_QUOTA: ++ qsv = &sv->qs_uquota; ++ accounting = sv->qs_flags & XFS_QUOTA_UDQ_ACCT; ++ enforcing = sv->qs_flags & XFS_QUOTA_UDQ_ENFD; ++ break; ++ case XFS_GROUP_QUOTA: ++ qsv = &sv->qs_gquota; ++ accounting = sv->qs_flags & XFS_QUOTA_GDQ_ACCT; ++ enforcing = sv->qs_flags & XFS_QUOTA_GDQ_ENFD; ++ break; ++ case XFS_PROJ_QUOTA: ++ qsv = &sv->qs_pquota; ++ accounting = sv->qs_flags & XFS_QUOTA_PDQ_ACCT; ++ enforcing = sv->qs_flags & XFS_QUOTA_PDQ_ENFD; ++ break; ++ default: ++ return; + } + +- if (type & XFS_USER_QUOTA) +- state_qfilestat(fp, mount, XFS_USER_QUOTA, &sv.qs_uquota, +- sv.qs_flags & XFS_QUOTA_UDQ_ACCT, +- sv.qs_flags & XFS_QUOTA_UDQ_ENFD); +- if (type & XFS_GROUP_QUOTA) +- state_qfilestat(fp, mount, XFS_GROUP_QUOTA, &sv.qs_gquota, +- sv.qs_flags & XFS_QUOTA_GDQ_ACCT, +- sv.qs_flags & XFS_QUOTA_GDQ_ENFD); +- if (type & XFS_PROJ_QUOTA) +- state_qfilestat(fp, mount, XFS_PROJ_QUOTA, &sv.qs_pquota, +- sv.qs_flags & XFS_QUOTA_PDQ_ACCT, +- sv.qs_flags & XFS_QUOTA_PDQ_ENFD); +- +- state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit); +- state_warnlimit(fp, XFS_BLOCK_QUOTA, sv.qs_bwarnlimit); +- +- state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit); +- state_warnlimit(fp, XFS_INODE_QUOTA, sv.qs_iwarnlimit); +- +- state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit); ++ ++ state_qfilestat(fp, mount, type, qsv, accounting, enforcing); ++ ++ state_timelimit(fp, XFS_BLOCK_QUOTA, sv->qs_btimelimit); ++ state_warnlimit(fp, XFS_BLOCK_QUOTA, sv->qs_bwarnlimit); ++ ++ state_timelimit(fp, XFS_INODE_QUOTA, sv->qs_itimelimit); ++ state_warnlimit(fp, XFS_INODE_QUOTA, sv->qs_iwarnlimit); ++ ++ state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv->qs_rtbtimelimit); ++} ++ ++static void ++state_quotafile_mount( ++ FILE *fp, ++ uint type, ++ struct fs_path *mount, ++ uint flags) ++{ ++ struct fs_quota_stat s; ++ struct fs_quota_statv sv; ++ ++ sv.qs_version = FS_QSTATV_VERSION1; ++ ++ if (type & XFS_USER_QUOTA) { ++ state_quotafile_stat(fp, XFS_USER_QUOTA, mount, ++ &sv, &s, flags); ++ } ++ ++ if (type & XFS_GROUP_QUOTA) { ++ state_quotafile_stat(fp, XFS_GROUP_QUOTA, mount, ++ &sv, &s, flags); ++ } ++ ++ if (type & XFS_PROJ_QUOTA) { ++ state_quotafile_stat(fp, XFS_PROJ_QUOTA, mount, ++ &sv, &s, flags); ++ } + } + + static void +-- +2.31.1 + diff --git a/SOURCES/xfsprogs-5.9.0-mkfs.xfs-fix-ASSERT-on-too-small-device-with-stripe.patch b/SOURCES/xfsprogs-5.9.0-mkfs.xfs-fix-ASSERT-on-too-small-device-with-stripe.patch new file mode 100755 index 0000000..86323d0 --- /dev/null +++ b/SOURCES/xfsprogs-5.9.0-mkfs.xfs-fix-ASSERT-on-too-small-device-with-stripe.patch @@ -0,0 +1,76 @@ +From 97a4059660b27a9b0e3d8cdde5dbef8712685865 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Mon, 28 Sep 2020 17:31:18 -0400 +Subject: [PATCH] mkfs.xfs: fix ASSERT on too-small device with stripe geometry + +When a too-small device is created with stripe geometry, we hit an +assert in align_ag_geometry(): + +mkfs.xfs: xfs_mkfs.c:2834: align_ag_geometry: Assertion `cfg->agcount != 0' failed. + +This is because align_ag_geometry() finds that the size of the last +(only) AG is too small, and attempts to trim it off. Obviously 0 +AGs is invalid, and we hit the ASSERT. + +Reported-by: Zdenek Kabelac +Suggested-by: Dave Chinner +Signed-off-by: Pavel Reichl +Reviewed-by: Christoph Hellwig +Reviewed-by: Carlos Maiolino +Signed-off-by: Eric Sandeen +--- + include/xfs_multidisk.h | 14 +++++++------- + mkfs/xfs_mkfs.c | 6 +++--- + 2 files changed, 10 insertions(+), 10 deletions(-) + +Index: xfsprogs-5.0.0/include/xfs_multidisk.h +=================================================================== +--- xfsprogs-5.0.0.orig/include/xfs_multidisk.h ++++ xfsprogs-5.0.0/include/xfs_multidisk.h +@@ -14,7 +14,6 @@ + #define XFS_DFL_BLOCKSIZE_LOG 12 /* 4096 byte blocks */ + #define XFS_DINODE_DFL_LOG 8 /* 256 byte inodes */ + #define XFS_DINODE_DFL_CRC_LOG 9 /* 512 byte inodes for CRCs */ +-#define XFS_MIN_DATA_BLOCKS 100 + #define XFS_MIN_INODE_PERBLOCK 2 /* min inodes per block */ + #define XFS_DFL_IMAXIMUM_PCT 25 /* max % of space for inodes */ + #define XFS_MIN_REC_DIRSIZE 12 /* 4096 byte dirblocks (V2) */ +@@ -25,13 +24,14 @@ + * accept w/o warnings + */ + +-#define XFS_AG_BYTES(bblog) ((long long)BBSIZE << (bblog)) +-#define XFS_AG_MIN_BYTES ((XFS_AG_BYTES(15))) /* 16 MB */ +-#define XFS_AG_MAX_BYTES ((XFS_AG_BYTES(31))) /* 1 TB */ +-#define XFS_AG_MIN_BLOCKS(blog) (XFS_AG_MIN_BYTES >> (blog)) +-#define XFS_AG_MAX_BLOCKS(blog) ((XFS_AG_MAX_BYTES - 1) >> (blog)) ++#define XFS_AG_BYTES(bblog) ((long long)BBSIZE << (bblog)) ++#define XFS_MIN_DATA_BLOCKS(cfg) (XFS_AG_MIN_BLOCKS((cfg)->blocklog)) ++#define XFS_AG_MIN_BYTES ((XFS_AG_BYTES(15))) /* 16 MB */ ++#define XFS_AG_MAX_BYTES ((XFS_AG_BYTES(31))) /* 1 TB */ ++#define XFS_AG_MIN_BLOCKS(blog) (XFS_AG_MIN_BYTES >> (blog)) ++#define XFS_AG_MAX_BLOCKS(blog) ((XFS_AG_MAX_BYTES - 1) >> (blog)) + +-#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1)) ++#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1)) + + /* + * These values define what we consider a "multi-disk" filesystem. That is, a +Index: xfsprogs-5.0.0/mkfs/xfs_mkfs.c +=================================================================== +--- xfsprogs-5.0.0.orig/mkfs/xfs_mkfs.c ++++ xfsprogs-5.0.0/mkfs/xfs_mkfs.c +@@ -2581,10 +2581,10 @@ _("size %s specified for data subvolume + cfg->dblocks = DTOBT(xi->dsize, cfg->blocklog); + } + +- if (cfg->dblocks < XFS_MIN_DATA_BLOCKS) { ++ if (cfg->dblocks < XFS_MIN_DATA_BLOCKS(cfg)) { + fprintf(stderr, +-_("size %lld of data subvolume is too small, minimum %d blocks\n"), +- (long long)cfg->dblocks, XFS_MIN_DATA_BLOCKS); ++_("size %lld of data subvolume is too small, minimum %lld blocks\n"), ++ (long long)cfg->dblocks, XFS_MIN_DATA_BLOCKS(cfg)); + usage(); + } + diff --git a/SOURCES/xfsprogs-5.9.0-xfs-drop-the-type-parameter-from-xfs_dquot_verify.patch b/SOURCES/xfsprogs-5.9.0-xfs-drop-the-type-parameter-from-xfs_dquot_verify.patch new file mode 100755 index 0000000..0151637 --- /dev/null +++ b/SOURCES/xfsprogs-5.9.0-xfs-drop-the-type-parameter-from-xfs_dquot_verify.patch @@ -0,0 +1,101 @@ +From bce109af5ea0b0d6547d8cd0500560f32532e6bd Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Dave Chinner +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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; diff --git a/SOURCES/xfsprogs-5.9.0-xfs-improve-ondisk-dquot-flags-checking.patch b/SOURCES/xfsprogs-5.9.0-xfs-improve-ondisk-dquot-flags-checking.patch new file mode 100755 index 0000000..1eff078 --- /dev/null +++ b/SOURCES/xfsprogs-5.9.0-xfs-improve-ondisk-dquot-flags-checking.patch @@ -0,0 +1,98 @@ +From 28518f7782310951019d6d28f2a6e9f9fc6e4a1c Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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 +Reviewed-by: Dave Chinner +Reviewed-by: Christoph Hellwig +Signed-off-by: Eric Sandeen +--- + +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" }, \ diff --git a/SPECS/xfsprogs.spec b/SPECS/xfsprogs.spec new file mode 100644 index 0000000..ffe0f61 --- /dev/null +++ b/SPECS/xfsprogs.spec @@ -0,0 +1,387 @@ +Summary: Utilities for managing the XFS filesystem +Name: xfsprogs +Version: 5.0.0 +Release: 10%{?dist} +License: GPL+ and LGPLv2+ +Group: System Environment/Base +URL: https://xfs.wiki.kernel.org +Source0: http://kernel.org/pub/linux/utils/fs/xfs/xfsprogs/%{name}-%{version}.tar.xz +BuildRequires: gcc +BuildRequires: libtool, gettext, libattr-devel, libuuid-devel +BuildRequires: readline-devel, libblkid-devel >= 2.17-0.1.git5e51568 +BuildRequires: lvm2-devel, libicu-devel >= 4.6 +Provides: xfs-cmds +Obsoletes: xfs-cmds <= %{version} +Provides: xfsprogs-qa-devel +Obsoletes: xfsprogs-qa-devel <= %{version} +Conflicts: xfsdump < 3.0.1 + +# reflink is not yet default upstream, but we enabled it as such +Patch0: xfsprogs-4.17.0-reflink-default.patch +Patch1: xfsprogs-5.1.0-mkfs-validate-start-and-end-of-aligned-logs.patch +Patch2: xfsprogs-5.1.0-mkfs-don-t-use-xfs_verify_fsbno-before-m_sb-is-fully.patch +Patch3: xfsprogs-5.1.0-xfsprogs-Fix-uninitialized-cfg-lsunit.patch +Patch4: xfsprogs-5.3.0-xfs_growfs-allow-mounted-device-node-as-argument.patch +Patch5: xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch +Patch6: xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch +Patch7: xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch +Patch8: xfsprogs-5.7.0-xfs_quota-refactor-code-to-generate-id-from-name.patch +Patch9: xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch +Patch10: xfsprogs-5.7.0-xfs_quota-fix-unsigned-int-id-comparisons.patch +Patch11: xfsprogs-5.7.0-xfs_repair-check-for-AG-btree-records-that-would-wra.patch +Patch12: xfsprogs-5.7.0-xfs_repair-tag-inobt-vs-finobt-errors-properly.patch +Patch13: xfsprogs-5.7.0-xfs_repair-complain-about-bad-interior-btree-pointer.patch +Patch14: xfsprogs-5.7.0-xfs_repair-convert-to-libxfs_verify_agbno.patch +Patch15: xfsprogs-5.9.0-mkfs.xfs-fix-ASSERT-on-too-small-device-with-stripe.patch +Patch16: xfsprogs-5.7.0-xfs_repair-fix-rebuilding-btree-block-less-than-minr.patch +Patch17: xfsprogs-5.10.0-xfs_quota-document-how-the-default-quota-is-stored.patch +Patch18: xfsprogs-5.8.0-xfs_db-short-circuit-type_f-if-type-is-unchanged.patch +Patch19: xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_geometry.patch +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. + +XFS is a high performance journaling filesystem which originated +on the SGI IRIX platform. It is completely multi-threaded, can +support large files and large filesystems, extended attributes, +variable block sizes, is extent based, and makes extensive use of +Btrees (directories, extents, free space) to aid both performance +and scalability. + +This implementation is on-disk compatible with the IRIX version +of XFS. + +%package devel +Summary: XFS filesystem-specific headers +Group: Development/Libraries +Requires: xfsprogs = %{version}-%{release}, libuuid-devel + +%description devel +xfsprogs-devel contains the header files needed to develop XFS +filesystem-specific programs. + +You should install xfsprogs-devel if you want to develop XFS +filesystem-specific programs, If you install xfsprogs-devel, you'll +also want to install xfsprogs. + +%prep +%setup -q + +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%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 + +%configure \ + --enable-readline=yes \ + --enable-blkid=yes \ + --enable-lto=no \ + --enable-scrub=no + +# NOTE scrub manpages manually removed below as well + +make V=1 %{?_smp_mflags} + +%install +make DIST_ROOT=$RPM_BUILD_ROOT install install-dev \ + PKG_ROOT_SBIN_DIR=%{_sbindir} PKG_ROOT_LIB_DIR=%{_libdir} + +# nuke .la files, etc +rm -f $RPM_BUILD_ROOT/{%{_lib}/*.{la,a,so},%{_libdir}/*.{la,a}} + +# remove non-versioned docs location +rm -rf $RPM_BUILD_ROOT/%{_datadir}/doc/xfsprogs/ + +# Remove scrub manpages +rm -rf $RPM_BUILD_ROOT/%{_mandir}/man8/xfs_scrub* + +%find_lang %{name} + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files -f %{name}.lang +%doc doc/CHANGES README +%{_libdir}/*.so.* +%{_mandir}/man5/* +%{_mandir}/man8/* +%{_sbindir}/* + +%files devel +%{_mandir}/man2/* +%{_mandir}/man3/* +%dir %{_includedir}/xfs +%{_includedir}/xfs/handle.h +%{_includedir}/xfs/jdm.h +%{_includedir}/xfs/linux.h +%{_includedir}/xfs/xfs.h +%{_includedir}/xfs/xfs_arch.h +%{_includedir}/xfs/xfs_fs.h +%{_includedir}/xfs/xfs_types.h +%{_includedir}/xfs/xfs_format.h +%{_includedir}/xfs/xfs_da_format.h +%{_includedir}/xfs/xfs_log_format.h +%{_includedir}/xfs/xqm.h + +%{_libdir}/*.so + +%changelog +* Thu Dec 09 2021 Bill O'Donnell 5.0.0-10 +- xfsprogs: enable bigtime and inode btree counter features in RHEL8 (#2024201)) + +* Thu Jul 08 2021 Bill O'Donnell 5.0.0-9 +- xfs_quota: state command should report ugp grace time (#1949743) + +* Thu Jan 07 2021 Bill O'Donnell 5.0.0-8 +- xfs_repair: Use proper min/max values in compute_level_geometry (#1910384) + +* Mon Dec 14 2020 Bill O'Donnell 5.0.0-7 +- xfs_quota: document how the default quota is stored (#1850188) +- xfs_db: skip type change if type_f unchanged (#1867474) + +* Wed Dec 09 2020 Bill O'Donnell 5.0.0-6 +- xfs_repair: improve AG btree ptr validation (libxfs_verify_agbno) (#1887288) +- mkfs.xfs: fix ASSERT on too-small device with stripe geometry (#1887401) +- xfs_repair: fix rebuilding btree block less than minrecs (#1759452) + +* Wed Dec 02 2020 Bill O'Donnell 5.0.0-5 +- xfs_quota: allow individual timer extension (#1899204) + +* Wed Jun 03 2020 Eric Sandeen 5.0.0-4 +- mkfs.xfs: inform user about discard, and make interruptable (#1836414) + +* Mon Apr 20 2020 Eric Sandeen 5.0.0-3 +- mkfs.xfs: use faster log zeroing on supported devices (#1755046) + +* Sat Dec 14 2019 Eric Sandeen 5.0.0-2 +- mkfs.xfs: validate log stripe unit alignment (#1632596) +- xfs_growfs: allow mounted device node as argument (#1765217) + +* Tue May 21 2019 Eric Sandeen 5.0.0-1 +- New upstream version (#1712147) +- mkfs.xfs: validate extent size hint parameters (#1683007) +- mkfs.xfs: null-terminate symlinks created via protofile (#1640503) +- xfs_repair: allow '/' in attribute names (#1667354) +- xfs_info: allow device name as parameter (#1679840) +- xfs_quota: fix project inheritance flag handling (#1664105) +- xfs_metadump: handle symlinks correctly (#1693074) +- xfs_db: fix finobt record decoding with sparse inodes (#1690245) + +* Mon Feb 04 2019 Eric Sandeen 4.19.0-2 +- xfs_repair: initialize non-leaf finobt blocks with correct magic (#1670153) + +* Tue Nov 27 2018 Eric Sandeen 4.19.0-1 +- New upstream release (#1652248) +- Note reflink default in mkfs.xfs manpage (#1641698) +- Fix xfs_db sign extension in agi freecount (#1640090) +- Fix xfs_repair hang on large filesystem (#1630674) + +* Tue Sep 25 2018 Eric Sandeen 4.18.0-3 +- Remove experimental xfs_scrub utility (#1623301) + +* Wed Sep 19 2018 Eric Sandeen 4.18.0-2 +- Fix annobin checks (#1630641) + +* Tue Aug 28 2018 Eric Sandeen 4.18.0-1 +- New upstream release (#1623695) + +* Mon Aug 13 2018 Eric Sandeen 4.17.0-4 +- Disable reflink automatically if crcs are disabled (#1600610) + +* Wed Aug 01 2018 Charalampos Stratakis - 4.17.0-3 +- Rebuild for platform-python + +* Thu Jun 28 2018 Eric Sandeen 4.17.0-2 +- Default mkfs to reflink enabled (#1494028) + +* Thu Jun 28 2018 Eric Sandeen 4.17.0-1 +- New upstream release +- Clean up spec file + +* Mon Feb 26 2018 Eric Sandeen 4.15.1-1 +- New upstream release +- Update Polish translation + +* Mon Feb 26 2018 Eric Sandeen 4.15.0-2 +- BuildRequires: gcc + +* Sat Feb 24 2018 Eric Sandeen 4.15.0-1 +- New upstream release +- Adds new xfs_scrub utility and services + +* Fri Feb 09 2018 Fedora Release Engineering - 4.14.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Nov 27 2017 Eric Sandeen 4.14.0-1 +- New upstream release + +* Wed Sep 27 2017 Eric Sandeen 4.13.1-1 +- New upstream release +- Trim ancient changelog + +* Thu Aug 03 2017 Fedora Release Engineering - 4.12.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Sun Jul 30 2017 Florian Weimer - 4.12.0-3 +- Rebuild with binutils fix for ppc64le (#1475636) + +* Thu Jul 27 2017 Fedora Release Engineering - 4.12.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon Jul 24 2017 Eric Sandeen 4.12.0-1 +- New upstream release + +* Fri May 05 2017 Eric Sandeen 4.11.0-1 +- New upstream release + +* Sun Feb 26 2017 Eric Sandeen 4.10.0-1 +- New upstream release + +* Sat Feb 11 2017 Fedora Release Engineering - 4.9.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Jan 12 2017 Igor Gnatenko - 4.9.0-2 +- Rebuild for readline 7.x + +* Thu Jan 05 2017 Eric Sandeen 4.9.0-1 +- New upstream release + +* Tue Oct 18 2016 Eric Sandeen 4.8.0-1 +- New upstream release + +* Tue Sep 06 2016 Eric Sandeen 4.7.0-2 +- Add libattr-devel build dependency to fix xfs_fsr + +* Sun Sep 04 2016 Eric Sandeen 4.7.0-1 +- New upstream release + +* Tue Mar 15 2016 Eric Sandeen 4.5.0-1 +- New upstream release + +* Thu Mar 10 2016 Eric Sandeen 4.3.0-3 +- Fix build w/ new kernels which have [sg]etxattr promotion + +* Fri Feb 05 2016 Fedora Release Engineering - 4.3.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Mon Nov 30 2015 Eric Sandeen 4.3.0-1 +- New upstream release + +* Wed Sep 09 2015 Eric Sandeen 4.2.0-1 +- New upstream release + +* Thu Jul 30 2015 Eric Sandeen 3.2.4-1 +- New upstream release +- Addresses CVE-2012-2150 for xfs_metadump + +* Fri Jun 19 2015 Fedora Release Engineering - 3.2.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed Jun 10 2015 Eric Sandeen 3.2.3-1 +- New upstream release