diff --git a/.SRCINFO b/.SRCINFO index a2f1ad5..010d43e 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -1,12 +1,12 @@ pkgbase = zfs-dkms pkgdesc = Kernel modules for the Zettabyte File System. - pkgver = 2.2.2 - pkgrel = 3 + pkgver = 2.2.3 + pkgrel = 1 url = https://openzfs.org/ arch = x86_64 groups = archzfs-dkms license = CDDL - depends = zfs-utils=2.2.2 + depends = zfs-utils=2.2.3 depends = lsb-release depends = dkms provides = zfs @@ -18,9 +18,7 @@ pkgbase = zfs-dkms conflicts = spl conflicts = spl-headers replaces = spl-dkms - 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 + source = https://github.com/openzfs/zfs/releases/download/zfs-2.2.3/zfs-2.2.3.tar.gz + sha256sums = 30a512f34ec5c841b8b2b32cc9c1a03fd49391b26c9164d3fb30573fb5d81ac3 pkgname = zfs-dkms diff --git a/PKGBUILD b/PKGBUILD index a2bef31..97626de 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -8,23 +8,19 @@ pkgname="zfs-dkms" pkgdesc="Kernel modules for the Zettabyte File System." -pkgver=2.2.2 -pkgrel=3 +pkgver=2.2.3 +pkgrel=1 makedepends=() arch=("x86_64") url="https://openzfs.org/" -source=("https://github.com/openzfs/zfs/releases/download/zfs-${pkgver}/zfs-${pkgver}.tar.gz" "linux-6.7-compat.patch") -sha256sums=("76bc0547d9ba31d4b0142e417aaaf9f969072c3cb3c1a5b10c8738f39ed12fc9" "43bca1a6717bfc77d42a4c51656c38674c6be8d7ec46f04c7febcdafd9295916") +source=("https://github.com/openzfs/zfs/releases/download/zfs-${pkgver}/zfs-${pkgver}.tar.gz") +sha256sums=("30a512f34ec5c841b8b2b32cc9c1a03fd49391b26c9164d3fb30573fb5d81ac3") license=("CDDL") depends=("zfs-utils=${pkgver}" "lsb-release" "dkms") provides=("zfs" "zfs-headers" "spl" "spl-headers") groups=("archzfs-dkms") conflicts=("zfs" "zfs-headers" "spl" "spl-headers") replaces=("spl-dkms") -prepare() { - cd "${srcdir}/zfs-${pkgver}" - patch -Np1 -i ${srcdir}/linux-6.7-compat.patch -} build() { cd "${srcdir}/zfs-${pkgver}" diff --git a/linux-6.7-compat.patch b/linux-6.7-compat.patch deleted file mode 100644 index e054706..0000000 --- a/linux-6.7-compat.patch +++ /dev/null @@ -1,966 +0,0 @@ -From 35d4d9df7041b25b966f660de7b5f92b57cc64b7 Mon Sep 17 00:00:00 2001 -From: Rob Norris -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 -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 - ], [ - 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 -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 -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 -+ ],[ -+ struct inode ip; -+ -+ memset(&ip, 0, sizeof(ip)); -+ inode_get_atime(&ip); -+ ]) -+ ZFS_LINUX_TEST_SRC([inode_get_mtime], [ -+ #include -+ ],[ -+ struct inode ip; -+ -+ memset(&ip, 0, sizeof(ip)); -+ inode_get_mtime(&ip); -+ ]) -+ -+ ZFS_LINUX_TEST_SRC([inode_set_atime_to_ts], [ -+ #include -+ ],[ -+ 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 -+ ],[ -+ 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 -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 -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 -+ 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 -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 -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 -+ 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 . -+ * 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 . -+ * -+ * Solaris Porting Layer (SPL) Shrinker Implementation. -+ */ -+ -+#include -+#include -+ -+#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 -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 -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 -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 -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)); - } -