summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorArchzfs Buildbot2024-02-23 17:52:25 +0000
committerArchzfs Buildbot2024-02-23 17:52:25 +0000
commitade2f78966f5334a2ce6e11f19e46afd49be1952 (patch)
tree8f7d8c113c5d71f1d44c85f8fb2d1118df3819a4
parentdcadca87f1e1c45085a14b1163954cd5b07a4913 (diff)
downloadaur-ade2f78966f5334a2ce6e11f19e46afd49be1952.tar.gz
Semi-automated update for kernel 6.7.5.hardened1-1 + zfs 2.2.3
-rw-r--r--.SRCINFO14
-rw-r--r--PKGBUILD14
-rw-r--r--linux-6.7-compat.patch966
3 files changed, 11 insertions, 983 deletions
diff --git a/.SRCINFO b/.SRCINFO
index ea2fc1f198c8..9feb356c42fd 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,17 +1,15 @@
pkgbase = zfs-linux-hardened
- pkgver = 2.2.2_6.7.4.hardened1.1
+ pkgver = 2.2.3_6.7.5.hardened1.1
pkgrel = 1
url = https://openzfs.org/
arch = x86_64
license = CDDL
- makedepends = linux-hardened-headers=6.7.4.hardened1-1
+ makedepends = linux-hardened-headers=6.7.5.hardened1-1
depends = kmod
- depends = zfs-utils=2.2.2
- depends = linux-hardened=6.7.4.hardened1-1
- source = https://github.com/openzfs/zfs/releases/download/zfs-2.2.2/zfs-2.2.2.tar.gz
- source = linux-6.7-compat.patch
- sha256sums = 76bc0547d9ba31d4b0142e417aaaf9f969072c3cb3c1a5b10c8738f39ed12fc9
- sha256sums = 43bca1a6717bfc77d42a4c51656c38674c6be8d7ec46f04c7febcdafd9295916
+ depends = zfs-utils=2.2.3
+ depends = linux-hardened=6.7.5.hardened1-1
+ source = https://github.com/openzfs/zfs/releases/download/zfs-2.2.3/zfs-2.2.3.tar.gz
+ sha256sums = 30a512f34ec5c841b8b2b32cc9c1a03fd49391b26c9164d3fb30573fb5d81ac3
pkgname = zfs-linux-hardened
pkgdesc = Kernel modules for the Zettabyte File System.
diff --git a/PKGBUILD b/PKGBUILD
index 4df5e6be609a..0abbeab8e117 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -17,9 +17,9 @@
#
pkgbase="zfs-linux-hardened"
pkgname=("zfs-linux-hardened" "zfs-linux-hardened-headers")
-_zfsver="2.2.2"
-_kernelver="6.7.4.hardened1-1"
-_kernelver_full="6.7.4.hardened1-1"
+_zfsver="2.2.3"
+_kernelver="6.7.5.hardened1-1"
+_kernelver_full="6.7.5.hardened1-1"
_extramodules="${_kernelver/.hardened/-hardened}-hardened"
pkgver="${_zfsver}_$(echo ${_kernelver} | sed s/-/./g)"
@@ -27,14 +27,10 @@ pkgrel=1
makedepends=("linux-hardened-headers=${_kernelver}")
arch=("x86_64")
url="https://openzfs.org/"
-source=("https://github.com/openzfs/zfs/releases/download/zfs-${_zfsver}/zfs-${_zfsver}.tar.gz" "linux-6.7-compat.patch")
-sha256sums=("76bc0547d9ba31d4b0142e417aaaf9f969072c3cb3c1a5b10c8738f39ed12fc9" "43bca1a6717bfc77d42a4c51656c38674c6be8d7ec46f04c7febcdafd9295916")
+source=("https://github.com/openzfs/zfs/releases/download/zfs-${_zfsver}/zfs-${_zfsver}.tar.gz")
+sha256sums=("30a512f34ec5c841b8b2b32cc9c1a03fd49391b26c9164d3fb30573fb5d81ac3")
license=("CDDL")
depends=("kmod" "zfs-utils=${_zfsver}" "linux-hardened=${_kernelver}")
-prepare() {
- cd "${srcdir}/zfs-${_zfsver}"
- patch -Np1 -i ${srcdir}/linux-6.7-compat.patch
-}
build() {
cd "${srcdir}/zfs-${_zfsver}"
diff --git a/linux-6.7-compat.patch b/linux-6.7-compat.patch
deleted file mode 100644
index e05470626d20..000000000000
--- a/linux-6.7-compat.patch
+++ /dev/null
@@ -1,966 +0,0 @@
-From 35d4d9df7041b25b966f660de7b5f92b57cc64b7 Mon Sep 17 00:00:00 2001
-From: Rob Norris <robn@despairlabs.com>
-Date: Sat, 16 Dec 2023 18:01:45 +1100
-Subject: [PATCH 1/4] linux 6.7 compat: simplify current_time() check
-
-6.7 changed the names of the time members in struct inode, so we can't
-assign back to it because we don't know its name. In practice this
-doesn't matter though - if we're missing current_time(), then we must be
-on <4.9, and we know our fallback will need to return timespec.
-
-Signed-off-by: Rob Norris <robn@despairlabs.com>
-Sponsored-by: https://github.com/sponsors/robn
----
- config/kernel-current-time.m4 | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/config/kernel-current-time.m4 b/config/kernel-current-time.m4
-index 3ceb5f63efa9..ab7d9c5cedba 100644
---- a/config/kernel-current-time.m4
-+++ b/config/kernel-current-time.m4
-@@ -2,12 +2,15 @@ dnl #
- dnl # 4.9, current_time() added
- dnl # 4.18, return type changed from timespec to timespec64
- dnl #
-+dnl # Note that we don't care about the return type in this check. If we have
-+dnl # to implement a fallback, we'll know we're <4.9, which was timespec.
-+dnl #
- AC_DEFUN([ZFS_AC_KERNEL_SRC_CURRENT_TIME], [
- ZFS_LINUX_TEST_SRC([current_time], [
- #include <linux/fs.h>
- ], [
- struct inode ip __attribute__ ((unused));
-- ip.i_atime = current_time(&ip);
-+ (void) current_time(&ip);
- ])
- ])
-
-
-From 82d0e42313aedc17447e4481822c38824a9e0d6c Mon Sep 17 00:00:00 2001
-From: Rob Norris <robn@despairlabs.com>
-Date: Sat, 16 Dec 2023 22:31:32 +1100
-Subject: [PATCH 2/4] linux 6.7 compat: use inode atime/mtime accessors
-
-6.6 made i_ctime inaccessible; 6.7 has done the same for i_atime and
-i_mtime. This extends the method used for ctime in b37f29341 to atime
-and mtime as well.
-
-Signed-off-by: Rob Norris <robn@despairlabs.com>
-Sponsored-by: https://github.com/sponsors/robn
----
- config/kernel-inode-times.m4 | 78 ++++++++++++++++++++++++++++++
- include/os/linux/zfs/sys/zpl.h | 20 ++++++++
- module/os/linux/zfs/zfs_ctldir.c | 4 +-
- module/os/linux/zfs/zfs_vnops_os.c | 33 ++++++++-----
- module/os/linux/zfs/zfs_znode.c | 45 +++++++++--------
- module/os/linux/zfs/zpl_inode.c | 3 +-
- 6 files changed, 148 insertions(+), 35 deletions(-)
-
-diff --git a/config/kernel-inode-times.m4 b/config/kernel-inode-times.m4
-index aae95abf1720..4d861596ed0b 100644
---- a/config/kernel-inode-times.m4
-+++ b/config/kernel-inode-times.m4
-@@ -52,6 +52,48 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_TIMES], [
- memset(&ip, 0, sizeof(ip));
- inode_set_ctime_to_ts(&ip, ts);
- ])
-+
-+ dnl #
-+ dnl # 6.7 API change
-+ dnl # i_atime/i_mtime no longer directly accessible, must use
-+ dnl # inode_get_mtime(ip), inode_set_mtime*(ip) to
-+ dnl # read/write.
-+ dnl #
-+ ZFS_LINUX_TEST_SRC([inode_get_atime], [
-+ #include <linux/fs.h>
-+ ],[
-+ struct inode ip;
-+
-+ memset(&ip, 0, sizeof(ip));
-+ inode_get_atime(&ip);
-+ ])
-+ ZFS_LINUX_TEST_SRC([inode_get_mtime], [
-+ #include <linux/fs.h>
-+ ],[
-+ struct inode ip;
-+
-+ memset(&ip, 0, sizeof(ip));
-+ inode_get_mtime(&ip);
-+ ])
-+
-+ ZFS_LINUX_TEST_SRC([inode_set_atime_to_ts], [
-+ #include <linux/fs.h>
-+ ],[
-+ struct inode ip;
-+ struct timespec64 ts = {0};
-+
-+ memset(&ip, 0, sizeof(ip));
-+ inode_set_atime_to_ts(&ip, ts);
-+ ])
-+ ZFS_LINUX_TEST_SRC([inode_set_mtime_to_ts], [
-+ #include <linux/fs.h>
-+ ],[
-+ struct inode ip;
-+ struct timespec64 ts = {0};
-+
-+ memset(&ip, 0, sizeof(ip));
-+ inode_set_mtime_to_ts(&ip, ts);
-+ ])
- ])
-
- AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
-@@ -90,4 +132,40 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
- ],[
- AC_MSG_RESULT(no)
- ])
-+
-+ AC_MSG_CHECKING([whether inode_get_atime() exists])
-+ ZFS_LINUX_TEST_RESULT([inode_get_atime], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_INODE_GET_ATIME, 1,
-+ [inode_get_atime() exists in linux/fs.h])
-+ ],[
-+ AC_MSG_RESULT(no)
-+ ])
-+
-+ AC_MSG_CHECKING([whether inode_set_atime_to_ts() exists])
-+ ZFS_LINUX_TEST_RESULT([inode_set_atime_to_ts], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_INODE_SET_ATIME_TO_TS, 1,
-+ [inode_set_atime_to_ts() exists in linux/fs.h])
-+ ],[
-+ AC_MSG_RESULT(no)
-+ ])
-+
-+ AC_MSG_CHECKING([whether inode_get_mtime() exists])
-+ ZFS_LINUX_TEST_RESULT([inode_get_mtime], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_INODE_GET_MTIME, 1,
-+ [inode_get_mtime() exists in linux/fs.h])
-+ ],[
-+ AC_MSG_RESULT(no)
-+ ])
-+
-+ AC_MSG_CHECKING([whether inode_set_mtime_to_ts() exists])
-+ ZFS_LINUX_TEST_RESULT([inode_set_mtime_to_ts], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_INODE_SET_MTIME_TO_TS, 1,
-+ [inode_set_mtime_to_ts() exists in linux/fs.h])
-+ ],[
-+ AC_MSG_RESULT(no)
-+ ])
- ])
-diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h
-index 9b729be6d74d..91a4751fffb0 100644
---- a/include/os/linux/zfs/sys/zpl.h
-+++ b/include/os/linux/zfs/sys/zpl.h
-@@ -273,5 +273,25 @@ extern long zpl_ioctl_fideduperange(struct file *filp, void *arg);
- #else
- #define zpl_inode_set_ctime_to_ts(ip, ts) (ip->i_ctime = ts)
- #endif
-+#ifdef HAVE_INODE_GET_ATIME
-+#define zpl_inode_get_atime(ip) inode_get_atime(ip)
-+#else
-+#define zpl_inode_get_atime(ip) (ip->i_atime)
-+#endif
-+#ifdef HAVE_INODE_SET_ATIME_TO_TS
-+#define zpl_inode_set_atime_to_ts(ip, ts) inode_set_atime_to_ts(ip, ts)
-+#else
-+#define zpl_inode_set_atime_to_ts(ip, ts) (ip->i_atime = ts)
-+#endif
-+#ifdef HAVE_INODE_GET_MTIME
-+#define zpl_inode_get_mtime(ip) inode_get_mtime(ip)
-+#else
-+#define zpl_inode_get_mtime(ip) (ip->i_mtime)
-+#endif
-+#ifdef HAVE_INODE_SET_MTIME_TO_TS
-+#define zpl_inode_set_mtime_to_ts(ip, ts) inode_set_mtime_to_ts(ip, ts)
-+#else
-+#define zpl_inode_set_mtime_to_ts(ip, ts) (ip->i_mtime = ts)
-+#endif
-
- #endif /* _SYS_ZPL_H */
-diff --git a/module/os/linux/zfs/zfs_ctldir.c b/module/os/linux/zfs/zfs_ctldir.c
-index 94e25fa0ae8f..54ed70d0394f 100644
---- a/module/os/linux/zfs/zfs_ctldir.c
-+++ b/module/os/linux/zfs/zfs_ctldir.c
-@@ -520,8 +520,8 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
- ip->i_uid = SUID_TO_KUID(0);
- ip->i_gid = SGID_TO_KGID(0);
- ip->i_blkbits = SPA_MINBLOCKSHIFT;
-- ip->i_atime = now;
-- ip->i_mtime = now;
-+ zpl_inode_set_atime_to_ts(ip, now);
-+ zpl_inode_set_mtime_to_ts(ip, now);
- zpl_inode_set_ctime_to_ts(ip, now);
- ip->i_fop = fops;
- ip->i_op = ops;
-diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c
-index e990f7055f8a..10162f62cda2 100644
---- a/module/os/linux/zfs/zfs_vnops_os.c
-+++ b/module/os/linux/zfs/zfs_vnops_os.c
-@@ -2438,15 +2438,17 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
-
- if ((mask & ATTR_ATIME) || zp->z_atime_dirty) {
- zp->z_atime_dirty = B_FALSE;
-- ZFS_TIME_ENCODE(&ip->i_atime, atime);
-+ inode_timespec_t tmp_atime;
-+ ZFS_TIME_ENCODE(&tmp_atime, atime);
-+ zpl_inode_set_atime_to_ts(ZTOI(zp), tmp_atime);
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
- &atime, sizeof (atime));
- }
-
- if (mask & (ATTR_MTIME | ATTR_SIZE)) {
- ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
-- ZTOI(zp)->i_mtime = zpl_inode_timestamp_truncate(
-- vap->va_mtime, ZTOI(zp));
-+ zpl_inode_set_mtime_to_ts(ZTOI(zp),
-+ zpl_inode_timestamp_truncate(vap->va_mtime, ZTOI(zp)));
-
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL,
- mtime, sizeof (mtime));
-@@ -3660,7 +3662,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
- caddr_t va;
- int err = 0;
- uint64_t mtime[2], ctime[2];
-- inode_timespec_t tmp_ctime;
-+ inode_timespec_t tmp_ts;
- sa_bulk_attr_t bulk[3];
- int cnt = 0;
- struct address_space *mapping;
-@@ -3824,9 +3826,10 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
- &zp->z_pflags, 8);
-
- /* Preserve the mtime and ctime provided by the inode */
-- ZFS_TIME_ENCODE(&ip->i_mtime, mtime);
-- tmp_ctime = zpl_inode_get_ctime(ip);
-- ZFS_TIME_ENCODE(&tmp_ctime, ctime);
-+ tmp_ts = zpl_inode_get_mtime(ip);
-+ ZFS_TIME_ENCODE(&tmp_ts, mtime);
-+ tmp_ts = zpl_inode_get_ctime(ip);
-+ ZFS_TIME_ENCODE(&tmp_ts, ctime);
- zp->z_atime_dirty = B_FALSE;
- zp->z_seq++;
-
-@@ -3880,7 +3883,7 @@ zfs_dirty_inode(struct inode *ip, int flags)
- zfsvfs_t *zfsvfs = ITOZSB(ip);
- dmu_tx_t *tx;
- uint64_t mode, atime[2], mtime[2], ctime[2];
-- inode_timespec_t tmp_ctime;
-+ inode_timespec_t tmp_ts;
- sa_bulk_attr_t bulk[4];
- int error = 0;
- int cnt = 0;
-@@ -3925,10 +3928,12 @@ zfs_dirty_inode(struct inode *ip, int flags)
- SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
-
- /* Preserve the mode, mtime and ctime provided by the inode */
-- ZFS_TIME_ENCODE(&ip->i_atime, atime);
-- ZFS_TIME_ENCODE(&ip->i_mtime, mtime);
-- tmp_ctime = zpl_inode_get_ctime(ip);
-- ZFS_TIME_ENCODE(&tmp_ctime, ctime);
-+ tmp_ts = zpl_inode_get_atime(ip);
-+ ZFS_TIME_ENCODE(&tmp_ts, atime);
-+ tmp_ts = zpl_inode_get_mtime(ip);
-+ ZFS_TIME_ENCODE(&tmp_ts, mtime);
-+ tmp_ts = zpl_inode_get_ctime(ip);
-+ ZFS_TIME_ENCODE(&tmp_ts, ctime);
- mode = ip->i_mode;
-
- zp->z_mode = mode;
-@@ -3971,7 +3976,9 @@ zfs_inactive(struct inode *ip)
- if (error) {
- dmu_tx_abort(tx);
- } else {
-- ZFS_TIME_ENCODE(&ip->i_atime, atime);
-+ inode_timespec_t tmp_atime;
-+ tmp_atime = zpl_inode_get_atime(ip);
-+ ZFS_TIME_ENCODE(&tmp_atime, atime);
- mutex_enter(&zp->z_lock);
- (void) sa_update(zp->z_sa_hdl, SA_ZPL_ATIME(zfsvfs),
- (void *)&atime, sizeof (atime), tx);
-diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c
-index f71026da83cb..b99df188c64b 100644
---- a/module/os/linux/zfs/zfs_znode.c
-+++ b/module/os/linux/zfs/zfs_znode.c
-@@ -542,7 +542,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
- uint64_t links;
- uint64_t z_uid, z_gid;
- uint64_t atime[2], mtime[2], ctime[2], btime[2];
-- inode_timespec_t tmp_ctime;
-+ inode_timespec_t tmp_ts;
- uint64_t projid = ZFS_DEFAULT_PROJID;
- sa_bulk_attr_t bulk[12];
- int count = 0;
-@@ -614,10 +614,12 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
- if (zp->z_pflags & ZFS_XATTR)
- zp->z_xattr_parent = parent;
-
-- ZFS_TIME_DECODE(&ip->i_atime, atime);
-- ZFS_TIME_DECODE(&ip->i_mtime, mtime);
-- ZFS_TIME_DECODE(&tmp_ctime, ctime);
-- zpl_inode_set_ctime_to_ts(ip, tmp_ctime);
-+ ZFS_TIME_DECODE(&tmp_ts, atime);
-+ zpl_inode_set_atime_to_ts(ip, tmp_ts);
-+ ZFS_TIME_DECODE(&tmp_ts, mtime);
-+ zpl_inode_set_mtime_to_ts(ip, tmp_ts);
-+ ZFS_TIME_DECODE(&tmp_ts, ctime);
-+ zpl_inode_set_ctime_to_ts(ip, tmp_ts);
- ZFS_TIME_DECODE(&zp->z_btime, btime);
-
- ip->i_ino = zp->z_id;
-@@ -1197,7 +1199,7 @@ zfs_rezget(znode_t *zp)
- uint64_t gen;
- uint64_t z_uid, z_gid;
- uint64_t atime[2], mtime[2], ctime[2], btime[2];
-- inode_timespec_t tmp_ctime;
-+ inode_timespec_t tmp_ts;
- uint64_t projid = ZFS_DEFAULT_PROJID;
- znode_hold_t *zh;
-
-@@ -1290,10 +1292,12 @@ zfs_rezget(znode_t *zp)
- zfs_uid_write(ZTOI(zp), z_uid);
- zfs_gid_write(ZTOI(zp), z_gid);
-
-- ZFS_TIME_DECODE(&ZTOI(zp)->i_atime, atime);
-- ZFS_TIME_DECODE(&ZTOI(zp)->i_mtime, mtime);
-- ZFS_TIME_DECODE(&tmp_ctime, ctime);
-- zpl_inode_set_ctime_to_ts(ZTOI(zp), tmp_ctime);
-+ ZFS_TIME_DECODE(&tmp_ts, atime);
-+ zpl_inode_set_atime_to_ts(ZTOI(zp), tmp_ts);
-+ ZFS_TIME_DECODE(&tmp_ts, mtime);
-+ zpl_inode_set_mtime_to_ts(ZTOI(zp), tmp_ts);
-+ ZFS_TIME_DECODE(&tmp_ts, ctime);
-+ zpl_inode_set_ctime_to_ts(ZTOI(zp), tmp_ts);
- ZFS_TIME_DECODE(&zp->z_btime, btime);
-
- if ((uint32_t)gen != ZTOI(zp)->i_generation) {
-@@ -1401,22 +1405,24 @@ zfs_zinactive(znode_t *zp)
- boolean_t
- zfs_relatime_need_update(const struct inode *ip)
- {
-- inode_timespec_t now, tmp_ctime;
-+ inode_timespec_t now, tmp_atime, tmp_ts;
-
- gethrestime(&now);
-+ tmp_atime = zpl_inode_get_atime(ip);
- /*
- * In relatime mode, only update the atime if the previous atime
- * is earlier than either the ctime or mtime or if at least a day
- * has passed since the last update of atime.
- */
-- if (zfs_compare_timespec(&ip->i_mtime, &ip->i_atime) >= 0)
-+ tmp_ts = zpl_inode_get_mtime(ip);
-+ if (zfs_compare_timespec(&tmp_ts, &tmp_atime) >= 0)
- return (B_TRUE);
-
-- tmp_ctime = zpl_inode_get_ctime(ip);
-- if (zfs_compare_timespec(&tmp_ctime, &ip->i_atime) >= 0)
-+ tmp_ts = zpl_inode_get_ctime(ip);
-+ if (zfs_compare_timespec(&tmp_ts, &tmp_atime) >= 0)
- return (B_TRUE);
-
-- if ((hrtime_t)now.tv_sec - (hrtime_t)ip->i_atime.tv_sec >= 24*60*60)
-+ if ((hrtime_t)now.tv_sec - (hrtime_t)tmp_atime.tv_sec >= 24*60*60)
- return (B_TRUE);
-
- return (B_FALSE);
-@@ -1439,7 +1445,7 @@ void
- zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
- uint64_t ctime[2])
- {
-- inode_timespec_t now, tmp_ctime;
-+ inode_timespec_t now, tmp_ts;
-
- gethrestime(&now);
-
-@@ -1447,7 +1453,8 @@ zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
-
- if (flag & ATTR_MTIME) {
- ZFS_TIME_ENCODE(&now, mtime);
-- ZFS_TIME_DECODE(&(ZTOI(zp)->i_mtime), mtime);
-+ ZFS_TIME_DECODE(&tmp_ts, mtime);
-+ zpl_inode_set_mtime_to_ts(ZTOI(zp), tmp_ts);
- if (ZTOZSB(zp)->z_use_fuids) {
- zp->z_pflags |= (ZFS_ARCHIVE |
- ZFS_AV_MODIFIED);
-@@ -1456,8 +1463,8 @@ zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
-
- if (flag & ATTR_CTIME) {
- ZFS_TIME_ENCODE(&now, ctime);
-- ZFS_TIME_DECODE(&tmp_ctime, ctime);
-- zpl_inode_set_ctime_to_ts(ZTOI(zp), tmp_ctime);
-+ ZFS_TIME_DECODE(&tmp_ts, ctime);
-+ zpl_inode_set_ctime_to_ts(ZTOI(zp), tmp_ts);
- if (ZTOZSB(zp)->z_use_fuids)
- zp->z_pflags |= ZFS_ARCHIVE;
- }
-diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c
-index 96f65b9e94e2..ad1753f7a071 100644
---- a/module/os/linux/zfs/zpl_inode.c
-+++ b/module/os/linux/zfs/zpl_inode.c
-@@ -526,7 +526,8 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
- vap->va_ctime = ia->ia_ctime;
-
- if (vap->va_mask & ATTR_ATIME)
-- ip->i_atime = zpl_inode_timestamp_truncate(ia->ia_atime, ip);
-+ zpl_inode_set_atime_to_ts(ip,
-+ zpl_inode_timestamp_truncate(ia->ia_atime, ip));
-
- cookie = spl_fstrans_mark();
- #ifdef HAVE_USERNS_IOPS_SETATTR
-
-From d7ebc6a92c45f5a62510f25b5544ad2ef7333c2c Mon Sep 17 00:00:00 2001
-From: Rob Norris <robn@despairlabs.com>
-Date: Sat, 16 Dec 2023 17:39:07 +1100
-Subject: [PATCH 3/4] linux 6.7 compat: handle superblock shrinker member
- change
-
-In 6.7 the superblock shrinker member s_shrink has changed from being an
-embedded struct to a pointer. Detect this, and don't take a reference if
-it already is one.
-
-Signed-off-by: Rob Norris <robn@despairlabs.com>
-Sponsored-by: https://github.com/sponsors/robn
----
- config/kernel-shrink.m4 | 35 +++++++++++++++++++++++++++++++-
- module/os/linux/zfs/zfs_vfsops.c | 10 +++++++--
- 2 files changed, 42 insertions(+), 3 deletions(-)
-
-diff --git a/config/kernel-shrink.m4 b/config/kernel-shrink.m4
-index 0c702153e8c4..1c5f753d411c 100644
---- a/config/kernel-shrink.m4
-+++ b/config/kernel-shrink.m4
-@@ -19,12 +19,44 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK], [
- ],[])
- ])
-
-+dnl #
-+dnl # 6.7 API change
-+dnl # s_shrink is now a pointer.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK_PTR], [
-+ ZFS_LINUX_TEST_SRC([super_block_s_shrink_ptr], [
-+ #include <linux/fs.h>
-+ unsigned long shrinker_cb(struct shrinker *shrink,
-+ struct shrink_control *sc) { return 0; }
-+ static struct shrinker shrinker = {
-+ .count_objects = shrinker_cb,
-+ .scan_objects = shrinker_cb,
-+ .seeks = DEFAULT_SEEKS,
-+ };
-+ static const struct super_block
-+ sb __attribute__ ((unused)) = {
-+ .s_shrink = &shrinker,
-+ };
-+ ],[])
-+])
-+
- AC_DEFUN([ZFS_AC_KERNEL_SUPER_BLOCK_S_SHRINK], [
- AC_MSG_CHECKING([whether super_block has s_shrink])
- ZFS_LINUX_TEST_RESULT([super_block_s_shrink], [
- AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_SUPER_BLOCK_S_SHRINK, 1,
-+ [have super_block s_shrink])
- ],[
-- ZFS_LINUX_TEST_ERROR([sb->s_shrink()])
-+ AC_MSG_RESULT(no)
-+ AC_MSG_CHECKING([whether super_block has s_shrink pointer])
-+ ZFS_LINUX_TEST_RESULT([super_block_s_shrink_ptr], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_SUPER_BLOCK_S_SHRINK_PTR, 1,
-+ [have super_block s_shrink pointer])
-+ ],[
-+ AC_MSG_RESULT(no)
-+ ZFS_LINUX_TEST_ERROR([sb->s_shrink()])
-+ ])
- ])
- ])
-
-@@ -174,6 +206,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT], [
-
- AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER], [
- ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK
-+ ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK_PTR
- ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_HAS_NID
- ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK
- ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_STRUCT
-diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c
-index 2792bc027213..2015c20d7340 100644
---- a/module/os/linux/zfs/zfs_vfsops.c
-+++ b/module/os/linux/zfs/zfs_vfsops.c
-@@ -1240,12 +1240,18 @@ zfs_prune_aliases(zfsvfs_t *zfsvfs, unsigned long nr_to_scan)
- * and inode caches. This can occur when the ARC needs to free meta data
- * blocks but can't because they are all pinned by entries in these caches.
- */
-+#if defined(HAVE_SUPER_BLOCK_S_SHRINK)
-+#define S_SHRINK(sb) (&(sb)->s_shrink)
-+#elif defined(HAVE_SUPER_BLOCK_S_SHRINK_PTR)
-+#define S_SHRINK(sb) ((sb)->s_shrink)
-+#endif
-+
- int
- zfs_prune(struct super_block *sb, unsigned long nr_to_scan, int *objects)
- {
- zfsvfs_t *zfsvfs = sb->s_fs_info;
- int error = 0;
-- struct shrinker *shrinker = &sb->s_shrink;
-+ struct shrinker *shrinker = S_SHRINK(sb);
- struct shrink_control sc = {
- .nr_to_scan = nr_to_scan,
- .gfp_mask = GFP_KERNEL,
-@@ -1257,7 +1263,7 @@ zfs_prune(struct super_block *sb, unsigned long nr_to_scan, int *objects)
- #if defined(HAVE_SPLIT_SHRINKER_CALLBACK) && \
- defined(SHRINK_CONTROL_HAS_NID) && \
- defined(SHRINKER_NUMA_AWARE)
-- if (sb->s_shrink.flags & SHRINKER_NUMA_AWARE) {
-+ if (shrinker->flags & SHRINKER_NUMA_AWARE) {
- *objects = 0;
- for_each_online_node(sc.nid) {
- *objects += (*shrinker->scan_objects)(shrinker, &sc);
-
-From e0cc696208e903cb00fe23bf7f5dc235c6995122 Mon Sep 17 00:00:00 2001
-From: Rob Norris <robn@despairlabs.com>
-Date: Sun, 17 Dec 2023 00:36:21 +1100
-Subject: [PATCH 4/4] linux 6.7 compat: rework shrinker setup for heap
- allocations
-
-6.7 changes the shrinker API such that shrinkers must be allocated
-dynamically by the kernel. To accomodate this, this commit reworks
-spl_register_shrinker() to do something similar against earlier kernels.
-
-Signed-off-by: Rob Norris <robn@despairlabs.com>
-Sponsored-by: https://github.com/sponsors/robn
----
- config/kernel-shrink.m4 | 52 +++++++++++--
- include/os/linux/spl/sys/shrinker.h | 66 +++++-----------
- module/Kbuild.in | 1 +
- module/os/linux/spl/spl-shrinker.c | 115 ++++++++++++++++++++++++++++
- module/os/linux/zfs/arc_os.c | 11 ++-
- 5 files changed, 189 insertions(+), 56 deletions(-)
- create mode 100644 module/os/linux/spl/spl-shrinker.c
-
-diff --git a/config/kernel-shrink.m4 b/config/kernel-shrink.m4
-index 1c5f753d411c..4a529c43b5b0 100644
---- a/config/kernel-shrink.m4
-+++ b/config/kernel-shrink.m4
-@@ -128,6 +128,25 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK], [
- ])
- ])
-
-+dnl #
-+dnl # 6.7 API change
-+dnl # register_shrinker has been replaced by shrinker_register.
-+dnl #
-+AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_REGISTER], [
-+ ZFS_LINUX_TEST_SRC([shrinker_register], [
-+ #include <linux/shrinker.h>
-+ unsigned long shrinker_cb(struct shrinker *shrink,
-+ struct shrink_control *sc) { return 0; }
-+ ],[
-+ struct shrinker cache_shrinker = {
-+ .count_objects = shrinker_cb,
-+ .scan_objects = shrinker_cb,
-+ .seeks = DEFAULT_SEEKS,
-+ };
-+ shrinker_register(&cache_shrinker);
-+ ])
-+])
-+
- AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
- dnl #
- dnl # 6.0 API change
-@@ -165,14 +184,36 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
- dnl # cs->shrink() is logically split in to
- dnl # cs->count_objects() and cs->scan_objects()
- dnl #
-- AC_MSG_CHECKING([if cs->count_objects callback exists])
-+ AC_MSG_CHECKING(
-+ [whether cs->count_objects callback exists])
- ZFS_LINUX_TEST_RESULT(
-- [shrinker_cb_shrink_control_split],[
-- AC_MSG_RESULT(yes)
-- AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK, 1,
-- [cs->count_objects exists])
-+ [shrinker_cb_shrink_control_split],[
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK, 1,
-+ [cs->count_objects exists])
- ],[
-+ AC_MSG_RESULT(no)
-+
-+ AC_MSG_CHECKING(
-+ [whether shrinker_register exists])
-+ ZFS_LINUX_TEST_RESULT([shrinker_register], [
-+ AC_MSG_RESULT(yes)
-+ AC_DEFINE(HAVE_SHRINKER_REGISTER, 1,
-+ [shrinker_register exists])
-+
-+ dnl # We assume that the split shrinker
-+ dnl # callback exists if
-+ dnl # shrinker_register() exists,
-+ dnl # because the latter is a much more
-+ dnl # recent addition, and the macro
-+ dnl # test for shrinker_register() only
-+ dnl # works if the callback is split
-+ AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK,
-+ 1, [cs->count_objects exists])
-+ ],[
-+ AC_MSG_RESULT(no)
- ZFS_LINUX_TEST_ERROR([shrinker])
-+ ])
- ])
- ])
- ])
-@@ -211,6 +252,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER], [
- ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK
- ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_STRUCT
- ZFS_AC_KERNEL_SRC_REGISTER_SHRINKER_VARARG
-+ ZFS_AC_KERNEL_SRC_SHRINKER_REGISTER
- ])
-
- AC_DEFUN([ZFS_AC_KERNEL_SHRINKER], [
-diff --git a/include/os/linux/spl/sys/shrinker.h b/include/os/linux/spl/sys/shrinker.h
-index d472754be4f4..bca4c850694a 100644
---- a/include/os/linux/spl/sys/shrinker.h
-+++ b/include/os/linux/spl/sys/shrinker.h
-@@ -29,12 +29,13 @@
-
- /*
- * Due to frequent changes in the shrinker API the following
-- * compatibility wrappers should be used. They are as follows:
-+ * compatibility wrapper should be used.
- *
-- * SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost);
-+ * shrinker = spl_register_shrinker(name, countfunc, scanfunc, seek_cost);
-+ * spl_unregister_shrinker(shrinker);
- *
-- * SPL_SHRINKER_DECLARE is used to declare a shrinker with the name varname,
-- * which is passed to spl_register_shrinker()/spl_unregister_shrinker().
-+ * spl_register_shrinker is used to create and register a shrinker with the
-+ * given name.
- * The countfunc returns the number of free-able objects.
- * The scanfunc returns the number of objects that were freed.
- * The callbacks can return SHRINK_STOP if further calls can't make any more
-@@ -57,57 +58,28 @@
- * ...scan objects in the cache and reclaim them...
- * }
- *
-- * SPL_SHRINKER_DECLARE(my_shrinker, my_count, my_scan, DEFAULT_SEEKS);
-+ * static struct shrinker *my_shrinker;
- *
- * void my_init_func(void) {
-- * spl_register_shrinker(&my_shrinker);
-+ * my_shrinker = spl_register_shrinker("my-shrinker",
-+ * my_count, my_scan, DEFAULT_SEEKS);
-+ * }
-+ *
-+ * void my_fini_func(void) {
-+ * spl_unregister_shrinker(my_shrinker);
- * }
- */
-
--#ifdef HAVE_REGISTER_SHRINKER_VARARG
--#define spl_register_shrinker(x) register_shrinker(x, "zfs-arc-shrinker")
--#else
--#define spl_register_shrinker(x) register_shrinker(x)
--#endif
--#define spl_unregister_shrinker(x) unregister_shrinker(x)
-+typedef unsigned long (*spl_shrinker_cb)
-+ (struct shrinker *, struct shrink_control *);
-
--/*
-- * Linux 3.0 to 3.11 Shrinker API Compatibility.
-- */
--#if defined(HAVE_SINGLE_SHRINKER_CALLBACK)
--#define SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost) \
--static int \
--__ ## varname ## _wrapper(struct shrinker *shrink, struct shrink_control *sc)\
--{ \
-- if (sc->nr_to_scan != 0) { \
-- (void) scanfunc(shrink, sc); \
-- } \
-- return (countfunc(shrink, sc)); \
--} \
-- \
--static struct shrinker varname = { \
-- .shrink = __ ## varname ## _wrapper, \
-- .seeks = seek_cost, \
--}
-+struct shrinker *spl_register_shrinker(const char *name,
-+ spl_shrinker_cb countfunc, spl_shrinker_cb scanfunc, int seek_cost);
-+void spl_unregister_shrinker(struct shrinker *);
-
-+#ifndef SHRINK_STOP
-+/* 3.0-3.11 compatibility */
- #define SHRINK_STOP (-1)
--
--/*
-- * Linux 3.12 and later Shrinker API Compatibility.
-- */
--#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
--#define SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost) \
--static struct shrinker varname = { \
-- .count_objects = countfunc, \
-- .scan_objects = scanfunc, \
-- .seeks = seek_cost, \
--}
--
--#else
--/*
-- * Linux 2.x to 2.6.22, or a newer shrinker API has been introduced.
-- */
--#error "Unknown shrinker callback"
- #endif
-
- #endif /* SPL_SHRINKER_H */
-diff --git a/module/Kbuild.in b/module/Kbuild.in
-index e34b9fab9efc..fb22bfe733c0 100644
---- a/module/Kbuild.in
-+++ b/module/Kbuild.in
-@@ -79,6 +79,7 @@ SPL_OBJS := \
- spl-kstat.o \
- spl-proc.o \
- spl-procfs-list.o \
-+ spl-shrinker.o \
- spl-taskq.o \
- spl-thread.o \
- spl-trace.o \
-diff --git a/module/os/linux/spl/spl-shrinker.c b/module/os/linux/spl/spl-shrinker.c
-new file mode 100644
-index 000000000000..d5c8da471cbb
---- /dev/null
-+++ b/module/os/linux/spl/spl-shrinker.c
-@@ -0,0 +1,115 @@
-+/*
-+ * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
-+ * Copyright (C) 2007 The Regents of the University of California.
-+ * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
-+ * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
-+ * UCRL-CODE-235197
-+ *
-+ * This file is part of the SPL, Solaris Porting Layer.
-+ *
-+ * The SPL is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * The SPL is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+ * for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along
-+ * with the SPL. If not, see <http://www.gnu.org/licenses/>.
-+ *
-+ * Solaris Porting Layer (SPL) Shrinker Implementation.
-+ */
-+
-+#include <sys/kmem.h>
-+#include <sys/shrinker.h>
-+
-+#ifdef HAVE_SINGLE_SHRINKER_CALLBACK
-+/* 3.0-3.11: single shrink() callback, which we wrap to carry both functions */
-+struct spl_shrinker_wrap {
-+ struct shrinker shrinker;
-+ spl_shrinker_cb countfunc;
-+ spl_shrinker_cb scanfunc;
-+};
-+
-+static int
-+spl_shrinker_single_cb(struct shrinker *shrinker, struct shrink_control *sc)
-+{
-+ struct spl_shrinker_wrap *sw = (struct spl_shrinker_wrap *)shrinker;
-+
-+ if (sc->nr_to_scan != 0)
-+ (void) sw->scanfunc(&sw->shrinker, sc);
-+ return (sw->countfunc(&sw->shrinker, sc));
-+}
-+#endif
-+
-+struct shrinker *
-+spl_register_shrinker(const char *name, spl_shrinker_cb countfunc,
-+ spl_shrinker_cb scanfunc, int seek_cost)
-+{
-+ struct shrinker *shrinker;
-+
-+ /* allocate shrinker */
-+#if defined(HAVE_SHRINKER_REGISTER)
-+ /* 6.7: kernel will allocate the shrinker for us */
-+ shrinker = shrinker_alloc(0, name);
-+#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
-+ /* 3.12-6.6: we allocate the shrinker */
-+ shrinker = kmem_zalloc(sizeof (struct shrinker), KM_SLEEP);
-+#elif defined(HAVE_SINGLE_SHRINKER_CALLBACK)
-+ /* 3.0-3.11: allocate a wrapper */
-+ struct spl_shrinker_wrap *sw =
-+ kmem_zalloc(sizeof (struct spl_shrinker_wrap), KM_SLEEP);
-+ shrinker = &sw->shrinker;
-+#else
-+ /* 2.x-2.6.22, or a newer shrinker API has been introduced. */
-+#error "Unknown shrinker API"
-+#endif
-+
-+ if (shrinker == NULL)
-+ return (NULL);
-+
-+ /* set callbacks */
-+#ifdef HAVE_SINGLE_SHRINKER_CALLBACK
-+ sw->countfunc = countfunc;
-+ sw->scanfunc = scanfunc;
-+ shrinker->shrink = spl_shrinker_single_cb;
-+#else
-+ shrinker->count_objects = countfunc;
-+ shrinker->scan_objects = scanfunc;
-+#endif
-+
-+ /* set params */
-+ shrinker->seeks = seek_cost;
-+
-+ /* register with kernel */
-+#if defined(HAVE_SHRINKER_REGISTER)
-+ shrinker_register(shrinker);
-+#elif defined(HAVE_REGISTER_SHRINKER_VARARG)
-+ register_shrinker(shrinker, name);
-+#else
-+ register_shrinker(shrinker);
-+#endif
-+
-+ return (shrinker);
-+}
-+EXPORT_SYMBOL(spl_register_shrinker);
-+
-+void
-+spl_unregister_shrinker(struct shrinker *shrinker)
-+{
-+#if defined(HAVE_SHRINKER_REGISTER)
-+ shrinker_free(shrinker);
-+#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
-+ unregister_shrinker(shrinker);
-+ kmem_free(shrinker, sizeof (struct shrinker));
-+#elif defined(HAVE_SINGLE_SHRINKER_CALLBACK)
-+ unregister_shrinker(shrinker);
-+ kmem_free(shrinker, sizeof (struct spl_shrinker_wrap));
-+#else
-+#error "Unknown shrinker API"
-+#endif
-+}
-+EXPORT_SYMBOL(spl_unregister_shrinker);
-diff --git a/module/os/linux/zfs/arc_os.c b/module/os/linux/zfs/arc_os.c
-index 55cdbba5b5eb..02dd80c06062 100644
---- a/module/os/linux/zfs/arc_os.c
-+++ b/module/os/linux/zfs/arc_os.c
-@@ -253,8 +253,7 @@ arc_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
- return (sc->nr_to_scan);
- }
-
--SPL_SHRINKER_DECLARE(arc_shrinker,
-- arc_shrinker_count, arc_shrinker_scan, DEFAULT_SEEKS);
-+static struct shrinker *arc_shrinker = NULL;
-
- int
- arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg)
-@@ -357,14 +356,18 @@ arc_lowmem_init(void)
- * reclaim from the arc. This is done to prevent kswapd from
- * swapping out pages when it is preferable to shrink the arc.
- */
-- spl_register_shrinker(&arc_shrinker);
-+ arc_shrinker = spl_register_shrinker("zfs-arc-shrinker",
-+ arc_shrinker_count, arc_shrinker_scan, DEFAULT_SEEKS);
-+ VERIFY(arc_shrinker);
-+
- arc_set_sys_free(allmem);
- }
-
- void
- arc_lowmem_fini(void)
- {
-- spl_unregister_shrinker(&arc_shrinker);
-+ spl_unregister_shrinker(arc_shrinker);
-+ arc_shrinker = NULL;
- }
-
- int
-
-
- From 49b2dee41a483ebc187ab2b42a6250242298b71b Mon Sep 17 00:00:00 2001
-From: Rob Norris <robn@despairlabs.com>
-Date: Mon, 15 Jan 2024 09:01:39 +1100
-Subject: [PATCH 1/2] tests/ctime: ensure times change by the right amount
-
-Previously, we only checked if the times changed at all, which missed a
-bug where the atime was being set to an undefined value.
-
-Now ensure the times change by two seconds (or thereabouts), ensuring we
-catch cases where we set the time to something bonkers
-
-Signed-off-by: Rob Norris <robn@despairlabs.com>
-Sponsored-by: https://despairlabs.com/sponsor/
----
- tests/zfs-tests/cmd/ctime.c | 14 +++++++++++---
- 1 file changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/tests/zfs-tests/cmd/ctime.c b/tests/zfs-tests/cmd/ctime.c
-index 0f5d81aea613..5ff1cea8a869 100644
---- a/tests/zfs-tests/cmd/ctime.c
-+++ b/tests/zfs-tests/cmd/ctime.c
-@@ -362,12 +362,20 @@ main(void)
- return (1);
- }
-
-- if (t1 == t2) {
-- (void) fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n",
-+
-+ /*
-+ * Ideally, time change would be exactly two seconds, but allow
-+ * a little slack in case of scheduling delays or similar.
-+ */
-+ long delta = (long)t2 - (long)t1;
-+ if (delta < 2 || delta > 4) {
-+ (void) fprintf(stderr,
-+ "%s: BAD time change: t1(%ld), t2(%ld)\n",
- timetest_table[i].name, (long)t1, (long)t2);
- return (1);
- } else {
-- (void) fprintf(stderr, "%s: t1(%ld) != t2(%ld)\n",
-+ (void) fprintf(stderr,
-+ "%s: good time change: t1(%ld), t2(%ld)\n",
- timetest_table[i].name, (long)t1, (long)t2);
- }
- }
-
-From 34c12f76f46ba91ff2a7cd8d2855524844e0cadc Mon Sep 17 00:00:00 2001
-From: Rob Norris <robn@despairlabs.com>
-Date: Sun, 14 Jan 2024 13:46:06 +1100
-Subject: [PATCH 2/2] zfs_setattr: fix atime update
-
-In db4fc559c I messed up and changed this bit of code to set the inode
-atime to an uninitialised value, when actually it was just supposed to
-loading the atime from the inode to be stored in the SA. This changes it
-to what it should have been.
-
-Signed-off-by: Rob Norris <robn@despairlabs.com>
-Sponsored-by: https://despairlabs.com/sponsor/
-Fixes: #15762
----
- module/os/linux/zfs/zfs_vnops_os.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c
-index 2a766a585b70..b7b89b8afc56 100644
---- a/module/os/linux/zfs/zfs_vnops_os.c
-+++ b/module/os/linux/zfs/zfs_vnops_os.c
-@@ -2439,9 +2439,8 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
-
- if ((mask & ATTR_ATIME) || zp->z_atime_dirty) {
- zp->z_atime_dirty = B_FALSE;
-- inode_timespec_t tmp_atime;
-+ inode_timespec_t tmp_atime = zpl_inode_get_atime(ip);
- ZFS_TIME_ENCODE(&tmp_atime, atime);
-- zpl_inode_set_atime_to_ts(ZTOI(zp), tmp_atime);
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
- &atime, sizeof (atime));
- }
-