summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorArchzfs Buildbot2024-01-22 00:20:48 +0000
committerArchzfs Buildbot2024-01-22 00:20:48 +0000
commitf21d3bb07fb356f539c31d45f4b0550521b3c7bf (patch)
treeb0a20c0b060c3a6848a1a5c7786c2e149006be3e
parent2669dd2e6e2872eb8b9fbfc15f44ae500c8894be (diff)
downloadaur-f21d3bb07fb356f539c31d45f4b0550521b3c7bf.tar.gz
Semi-automated update for kernel 6.6.13.hardened1-1 + zfs 2.2.2
-rw-r--r--.SRCINFO8
-rw-r--r--PKGBUILD12
-rw-r--r--linux-6.7-compat.patch885
3 files changed, 898 insertions, 7 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 2a07c292f983..f957ddcfde2f 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,15 +1,17 @@
pkgbase = zfs-linux-hardened
- pkgver = 2.2.2_6.6.11.hardened1.1
+ pkgver = 2.2.2_6.6.13.hardened1.1
pkgrel = 1
url = https://openzfs.org/
arch = x86_64
license = CDDL
- makedepends = linux-hardened-headers=6.6.11.hardened1-1
+ makedepends = linux-hardened-headers=6.6.13.hardened1-1
depends = kmod
depends = zfs-utils=2.2.2
- depends = linux-hardened=6.6.11.hardened1-1
+ depends = linux-hardened=6.6.13.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 = 5afd5ce236dfe0eb96abbe61a61c211623cb4a89c9fbb0be5f9f400a0970719e
pkgname = zfs-linux-hardened
pkgdesc = Kernel modules for the Zettabyte File System.
diff --git a/PKGBUILD b/PKGBUILD
index f5e982095e1d..e688beae10cb 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -18,8 +18,8 @@
pkgbase="zfs-linux-hardened"
pkgname=("zfs-linux-hardened" "zfs-linux-hardened-headers")
_zfsver="2.2.2"
-_kernelver="6.6.11.hardened1-1"
-_kernelver_full="6.6.11.hardened1-1"
+_kernelver="6.6.13.hardened1-1"
+_kernelver_full="6.6.13.hardened1-1"
_extramodules="${_kernelver/.hardened/-hardened}-hardened"
pkgver="${_zfsver}_$(echo ${_kernelver} | sed s/-/./g)"
@@ -27,10 +27,14 @@ 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")
-sha256sums=("76bc0547d9ba31d4b0142e417aaaf9f969072c3cb3c1a5b10c8738f39ed12fc9")
+source=("https://github.com/openzfs/zfs/releases/download/zfs-${_zfsver}/zfs-${_zfsver}.tar.gz" "linux-6.7-compat.patch")
+sha256sums=("76bc0547d9ba31d4b0142e417aaaf9f969072c3cb3c1a5b10c8738f39ed12fc9" "5afd5ce236dfe0eb96abbe61a61c211623cb4a89c9fbb0be5f9f400a0970719e")
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
new file mode 100644
index 000000000000..766ca929cc90
--- /dev/null
+++ b/linux-6.7-compat.patch
@@ -0,0 +1,885 @@
+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