diff --git a/.SRCINFO b/.SRCINFO index 5f17f5a..f7274fd 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -1,8 +1,8 @@ pkgbase = zfs-dkms pkgdesc = Kernel modules for the Zettabyte File System. pkgver = 0.8.1 - pkgrel = 1 - url = http://zfsonlinux.org/ + pkgrel = 3 + url = https://zfsonlinux.org/ arch = x86_64 groups = archzfs-dkms license = CDDL @@ -19,7 +19,13 @@ pkgbase = zfs-dkms conflicts = spl-headers replaces = spl-dkms source = https://github.com/zfsonlinux/zfs/releases/download/zfs-0.8.1/zfs-0.8.1.tar.gz + source = linux-5.3-compat-rw_semaphore-owner.patch + source = linux-5.3-compat-retire-rw_tryupgrade.patch + source = linux-5.3-compat-Makefile-subdir-m-no-longer-supported.patch sha256sums = 0af79fde44b7b8ecb94d5166ce2e4fff7409c20ed874c2d759db92909e6c2799 + sha256sums = c65c950abda42fb91fb99c6c916a50720a522c53e01a872f9310a4719bae9e2a + sha256sums = 19f798a29c00874874751880f1146c5849b8ebdb6233d8ae923f9fdd4661de19 + sha256sums = 6c4627875dd1724f64a196ea584812c99635897dc31cb23641f308770289059a pkgname = zfs-dkms diff --git a/PKGBUILD b/PKGBUILD index ebeae6a..c666be6 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -9,18 +9,30 @@ pkgname="zfs-dkms" pkgdesc="Kernel modules for the Zettabyte File System." pkgver=0.8.1 -pkgrel=1 +pkgrel=3 makedepends=() arch=("x86_64") -url="http://zfsonlinux.org/" -source=("https://github.com/zfsonlinux/zfs/releases/download/zfs-${pkgver}/zfs-${pkgver}.tar.gz") -sha256sums=("0af79fde44b7b8ecb94d5166ce2e4fff7409c20ed874c2d759db92909e6c2799") +url="https://zfsonlinux.org/" +source=("https://github.com/zfsonlinux/zfs/releases/download/zfs-${pkgver}/zfs-${pkgver}.tar.gz" + "linux-5.3-compat-rw_semaphore-owner.patch" + "linux-5.3-compat-retire-rw_tryupgrade.patch" + "linux-5.3-compat-Makefile-subdir-m-no-longer-supported.patch") +sha256sums=("0af79fde44b7b8ecb94d5166ce2e4fff7409c20ed874c2d759db92909e6c2799" + "c65c950abda42fb91fb99c6c916a50720a522c53e01a872f9310a4719bae9e2a" + "19f798a29c00874874751880f1146c5849b8ebdb6233d8ae923f9fdd4661de19" + "6c4627875dd1724f64a196ea584812c99635897dc31cb23641f308770289059a") 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-5.3-compat-rw_semaphore-owner.patch + patch -Np1 -i ${srcdir}/linux-5.3-compat-retire-rw_tryupgrade.patch + patch -Np1 -i ${srcdir}/linux-5.3-compat-Makefile-subdir-m-no-longer-supported.patch +} build() { cd "${srcdir}/zfs-${pkgver}" diff --git a/linux-5.3-compat-Makefile-subdir-m-no-longer-supported.patch b/linux-5.3-compat-Makefile-subdir-m-no-longer-supported.patch new file mode 100644 index 0000000..4569fb8 --- /dev/null +++ b/linux-5.3-compat-Makefile-subdir-m-no-longer-supported.patch @@ -0,0 +1,41 @@ +diff --unified --recursive --text a/module/Makefile.in b/module/Makefile.in +--- a/module/Makefile.in 2019-06-12 20:09:52.908943339 -0400 ++++ b/module/Makefile.in 2019-09-21 12:50:08.568119182 -0400 +@@ -1,11 +1,11 @@ +-subdir-m += avl +-subdir-m += icp +-subdir-m += lua +-subdir-m += nvpair +-subdir-m += spl +-subdir-m += unicode +-subdir-m += zcommon +-subdir-m += zfs ++obj-m += avl/ ++obj-m += icp/ ++obj-m += lua/ ++obj-m += nvpair/ ++obj-m += spl/ ++obj-m += unicode/ ++obj-m += zcommon/ ++obj-m += zfs/ + + INSTALL_MOD_DIR ?= extra + +@@ -60,13 +60,13 @@ + modules_uninstall: + @# Uninstall the kernel modules + kmoddir=$(DESTDIR)$(INSTALL_MOD_PATH)/lib/modules/@LINUX_VERSION@ +- list='$(subdir-m)'; for subdir in $$list; do \ +- $(RM) -R $$kmoddir/$(INSTALL_MOD_DIR)/$$subdir; \ ++ list='$(obj-m)'; for objdir in $$list; do \ ++ $(RM) -R $$kmoddir/$(INSTALL_MOD_DIR)/$$objdir; \ + done + + distdir: +- list='$(subdir-m)'; for subdir in $$list; do \ +- (cd @top_srcdir@/module && find $$subdir -name '*.c' -o -name '*.h' -o -name '*.S' |\ ++ list='$(obj-m)'; for objdir in $$list; do \ ++ (cd @top_srcdir@/module && find $$objdir -name '*.c' -o -name '*.h' -o -name '*.S' |\ + xargs cp --parents -t $$distdir); \ + done + diff --git a/linux-5.3-compat-retire-rw_tryupgrade.patch b/linux-5.3-compat-retire-rw_tryupgrade.patch new file mode 100644 index 0000000..253c358 --- /dev/null +++ b/linux-5.3-compat-retire-rw_tryupgrade.patch @@ -0,0 +1,236 @@ +From ee1848356f32e31f001ca96cc68e06a445f72108 Mon Sep 17 00:00:00 2001 +From: Brian Behlendorf +Date: Fri, 12 Jul 2019 14:06:36 -0700 +Subject: [PATCH] Linux 5.3 compat: retire rw_tryupgrade() + +The Linux kernel's rwsem's have never provided an interface to +allow a reader to be upgraded to a writer. Historically, this +functionality has been implemented by a SPL wrapper function. +However, this approach depends on internal knowledge of the +rw_semaphore and is therefore rather brittle. + +Since the ZFS code must always be able to fallback to rw_exit() +and rw_enter() when an rw_tryupgrade() fails; this functionality +isn't critical. Furthermore, the only potentially performance +sensitive consumer is dmu_zfetch() and no decrease in performance +was observed with this change applied. See the PR comments for +additional testing details. + +Therefore, it is being retired to make the build more robust and +to simplify the rwlock implementation. + +Reviewed-by: Tony Hutter +Reviewed-by: Tomohiro Kusumi +Signed-off-by: Brian Behlendorf +Closes #9029 +--- + include/spl/sys/rwlock.h | 60 +++-------------------- + module/spl/spl-rwlock.c | 101 --------------------------------------- + 2 files changed, 7 insertions(+), 154 deletions(-) + +diff --git a/include/spl/sys/rwlock.h b/include/spl/sys/rwlock.h +index 5e052b532a4..89e02fa8f04 100644 +--- a/include/spl/sys/rwlock.h ++++ b/include/spl/sys/rwlock.h +@@ -29,43 +29,6 @@ + #include + #include + +-/* Linux kernel compatibility */ +-#if defined(CONFIG_PREEMPT_RT_FULL) +-#define SPL_RWSEM_SINGLE_READER_VALUE (1) +-#define SPL_RWSEM_SINGLE_WRITER_VALUE (0) +-#elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK) +-#define SPL_RWSEM_SINGLE_READER_VALUE (1) +-#define SPL_RWSEM_SINGLE_WRITER_VALUE (-1) +-#elif defined(RWSEM_ACTIVE_MASK) +-#define SPL_RWSEM_SINGLE_READER_VALUE (RWSEM_ACTIVE_READ_BIAS) +-#define SPL_RWSEM_SINGLE_WRITER_VALUE (RWSEM_ACTIVE_WRITE_BIAS) +-#endif +- +-/* Linux 3.16 changed activity to count for rwsem-spinlock */ +-#if defined(CONFIG_PREEMPT_RT_FULL) +-#define RWSEM_COUNT(sem) sem->read_depth +-#elif defined(HAVE_RWSEM_ACTIVITY) +-#define RWSEM_COUNT(sem) sem->activity +-/* Linux 4.8 changed count to an atomic_long_t for !rwsem-spinlock */ +-#elif defined(HAVE_RWSEM_ATOMIC_LONG_COUNT) +-#define RWSEM_COUNT(sem) atomic_long_read(&(sem)->count) +-#else +-#define RWSEM_COUNT(sem) sem->count +-#endif +- +-#if defined(RWSEM_SPINLOCK_IS_RAW) +-#define spl_rwsem_lock_irqsave(lk, fl) raw_spin_lock_irqsave(lk, fl) +-#define spl_rwsem_unlock_irqrestore(lk, fl) \ +- raw_spin_unlock_irqrestore(lk, fl) +-#define spl_rwsem_trylock_irqsave(lk, fl) raw_spin_trylock_irqsave(lk, fl) +-#else +-#define spl_rwsem_lock_irqsave(lk, fl) spin_lock_irqsave(lk, fl) +-#define spl_rwsem_unlock_irqrestore(lk, fl) spin_unlock_irqrestore(lk, fl) +-#define spl_rwsem_trylock_irqsave(lk, fl) spin_trylock_irqsave(lk, fl) +-#endif /* RWSEM_SPINLOCK_IS_RAW */ +- +-#define spl_rwsem_is_locked(rwsem) rwsem_is_locked(rwsem) +- + typedef enum { + RW_DRIVER = 2, + RW_DEFAULT = 4, +@@ -133,7 +96,7 @@ spl_rw_lockdep_on_maybe(krwlock_t *rwp) \ + static inline int + RW_LOCK_HELD(krwlock_t *rwp) + { +- return (spl_rwsem_is_locked(SEM(rwp))); ++ return (rwsem_is_locked(SEM(rwp))); + } + + static inline int +@@ -170,6 +133,12 @@ RW_READ_HELD(krwlock_t *rwp) + */ + #define rw_destroy(rwp) ((void) 0) + ++/* ++ * Upgrading a rwsem from a reader to a writer is not supported by the ++ * Linux kernel. The lock must be dropped and reacquired as a writer. ++ */ ++#define rw_tryupgrade(rwp) RW_WRITE_HELD(rwp) ++ + #define rw_tryenter(rwp, rw) \ + ({ \ + int _rc_ = 0; \ +@@ -228,24 +197,9 @@ RW_READ_HELD(krwlock_t *rwp) + spl_rw_lockdep_on_maybe(rwp); \ + }) + +-#define rw_tryupgrade(rwp) \ +-({ \ +- int _rc_ = 0; \ +- \ +- if (RW_WRITE_HELD(rwp)) { \ +- _rc_ = 1; \ +- } else { \ +- spl_rw_lockdep_off_maybe(rwp); \ +- if ((_rc_ = rwsem_tryupgrade(SEM(rwp)))) \ +- spl_rw_set_owner(rwp); \ +- spl_rw_lockdep_on_maybe(rwp); \ +- } \ +- _rc_; \ +-}) + /* END CSTYLED */ + + int spl_rw_init(void); + void spl_rw_fini(void); +-int rwsem_tryupgrade(struct rw_semaphore *rwsem); + + #endif /* _SPL_RWLOCK_H */ +diff --git a/module/spl/spl-rwlock.c b/module/spl/spl-rwlock.c +index 886e16924e6..10f7c38db4e 100644 +--- a/module/spl/spl-rwlock.c ++++ b/module/spl/spl-rwlock.c +@@ -24,106 +24,5 @@ + * Solaris Porting Layer (SPL) Reader/Writer Lock Implementation. + */ + +-#include +-#include +- +-#if defined(CONFIG_PREEMPT_RT_FULL) +- +-#include +-#define RT_MUTEX_OWNER_MASKALL 1UL +- +-static int +-__rwsem_tryupgrade(struct rw_semaphore *rwsem) +-{ +-#if defined(READER_BIAS) && defined(WRITER_BIAS) +- /* +- * After the 4.9.20-rt16 kernel the realtime patch series lifted the +- * single reader restriction. While this could be accommodated by +- * adding additional compatibility code assume the rwsem can never +- * be upgraded. All caller must already cleanly handle this case. +- */ +- return (0); +-#else +- ASSERT((struct task_struct *) +- ((unsigned long)rwsem->lock.owner & ~RT_MUTEX_OWNER_MASKALL) == +- current); +- +- /* +- * Prior to 4.9.20-rt16 kernel the realtime patch series, rwsem is +- * implemented as a single mutex held by readers and writers alike. +- * However, this implementation would prevent a thread from taking +- * a read lock twice, as the mutex would already be locked on +- * the second attempt. Therefore the implementation allows a +- * single thread to take a rwsem as read lock multiple times +- * tracking that nesting as read_depth counter. +- */ +- if (rwsem->read_depth <= 1) { +- /* +- * In case, the current thread has not taken the lock +- * more than once as read lock, we can allow an +- * upgrade to a write lock. rwsem_rt.h implements +- * write locks as read_depth == 0. +- */ +- rwsem->read_depth = 0; +- return (1); +- } +- return (0); +-#endif +-} +-#elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK) +-static int +-__rwsem_tryupgrade(struct rw_semaphore *rwsem) +-{ +- int ret = 0; +- unsigned long flags; +- spl_rwsem_lock_irqsave(&rwsem->wait_lock, flags); +- if (RWSEM_COUNT(rwsem) == SPL_RWSEM_SINGLE_READER_VALUE && +- list_empty(&rwsem->wait_list)) { +- ret = 1; +- RWSEM_COUNT(rwsem) = SPL_RWSEM_SINGLE_WRITER_VALUE; +- } +- spl_rwsem_unlock_irqrestore(&rwsem->wait_lock, flags); +- return (ret); +-} +-#elif defined(RWSEM_ACTIVE_MASK) +-#if defined(HAVE_RWSEM_ATOMIC_LONG_COUNT) +-static int +-__rwsem_tryupgrade(struct rw_semaphore *rwsem) +-{ +- long val; +- val = atomic_long_cmpxchg(&rwsem->count, SPL_RWSEM_SINGLE_READER_VALUE, +- SPL_RWSEM_SINGLE_WRITER_VALUE); +- return (val == SPL_RWSEM_SINGLE_READER_VALUE); +-} +-#else +-static int +-__rwsem_tryupgrade(struct rw_semaphore *rwsem) +-{ +- typeof(rwsem->count) val; +- val = cmpxchg(&rwsem->count, SPL_RWSEM_SINGLE_READER_VALUE, +- SPL_RWSEM_SINGLE_WRITER_VALUE); +- return (val == SPL_RWSEM_SINGLE_READER_VALUE); +-} +-#endif +-#else +-static int +-__rwsem_tryupgrade(struct rw_semaphore *rwsem) +-{ +- return (0); +-} +-#endif +- +-int +-rwsem_tryupgrade(struct rw_semaphore *rwsem) +-{ +- if (__rwsem_tryupgrade(rwsem)) { +- rwsem_release(&rwsem->dep_map, 1, _RET_IP_); +- rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_); +- return (1); +- } +- return (0); +-} +-EXPORT_SYMBOL(rwsem_tryupgrade); +- + int spl_rw_init(void) { return 0; } + void spl_rw_fini(void) { } diff --git a/linux-5.3-compat-rw_semaphore-owner.patch b/linux-5.3-compat-rw_semaphore-owner.patch new file mode 100644 index 0000000..3a46359 --- /dev/null +++ b/linux-5.3-compat-rw_semaphore-owner.patch @@ -0,0 +1,155 @@ +From d4b15200e75a37da053589aa2ddff06872302ac2 Mon Sep 17 00:00:00 2001 +From: Brian Behlendorf +Date: Fri, 12 Jul 2019 13:27:24 -0700 +Subject: [PATCH] Linux 5.3 compat: rw_semaphore owner + +Commit https://github.com/torvalds/linux/commit/94a9717b updated the +rwsem's owner field to contain additional flags describing the rwsem's +state. Rather then update the wrappers to mask out these bits, the +code no longer relies on the owner stored by the kernel. This does +increase the size of a krwlock_t but it makes the implementation +less sensitive to future kernel changes. + +Reviewed-by: Tony Hutter +Reviewed-by: Tomohiro Kusumi +Signed-off-by: Brian Behlendorf +Closes #9029 +--- + include/spl/sys/rwlock.h | 68 +++------------------------------------- + module/spl/spl-rwlock.c | 3 -- + 2 files changed, 5 insertions(+), 66 deletions(-) + +diff --git a/include/spl/sys/rwlock.h b/include/spl/sys/rwlock.h +index 408defac20d..5e052b532a4 100644 +--- a/include/spl/sys/rwlock.h ++++ b/include/spl/sys/rwlock.h +@@ -78,15 +78,9 @@ typedef enum { + RW_READER = 2 + } krw_t; + +-/* +- * If CONFIG_RWSEM_SPIN_ON_OWNER is defined, rw_semaphore will have an owner +- * field, so we don't need our own. +- */ + typedef struct { + struct rw_semaphore rw_rwlock; +-#ifndef CONFIG_RWSEM_SPIN_ON_OWNER + kthread_t *rw_owner; +-#endif + #ifdef CONFIG_LOCKDEP + krw_type_t rw_type; + #endif /* CONFIG_LOCKDEP */ +@@ -97,31 +91,19 @@ typedef struct { + static inline void + spl_rw_set_owner(krwlock_t *rwp) + { +-/* +- * If CONFIG_RWSEM_SPIN_ON_OWNER is defined, down_write, up_write, +- * downgrade_write and __init_rwsem will set/clear owner for us. +- */ +-#ifndef CONFIG_RWSEM_SPIN_ON_OWNER + rwp->rw_owner = current; +-#endif + } + + static inline void + spl_rw_clear_owner(krwlock_t *rwp) + { +-#ifndef CONFIG_RWSEM_SPIN_ON_OWNER + rwp->rw_owner = NULL; +-#endif + } + + static inline kthread_t * + rw_owner(krwlock_t *rwp) + { +-#ifdef CONFIG_RWSEM_SPIN_ON_OWNER +- return (SEM(rwp)->owner); +-#else + return (rwp->rw_owner); +-#endif + } + + #ifdef CONFIG_LOCKDEP +@@ -148,62 +130,22 @@ spl_rw_lockdep_on_maybe(krwlock_t *rwp) \ + #define spl_rw_lockdep_on_maybe(rwp) + #endif /* CONFIG_LOCKDEP */ + +- + static inline int +-RW_WRITE_HELD(krwlock_t *rwp) ++RW_LOCK_HELD(krwlock_t *rwp) + { +- return (rw_owner(rwp) == current); ++ return (spl_rwsem_is_locked(SEM(rwp))); + } + + static inline int +-RW_LOCK_HELD(krwlock_t *rwp) ++RW_WRITE_HELD(krwlock_t *rwp) + { +- return (spl_rwsem_is_locked(SEM(rwp))); ++ return (rw_owner(rwp) == current); + } + + static inline int + RW_READ_HELD(krwlock_t *rwp) + { +- if (!RW_LOCK_HELD(rwp)) +- return (0); +- +- /* +- * rw_semaphore cheat sheet: +- * +- * < 3.16: +- * There's no rw_semaphore.owner, so use rwp.owner instead. +- * If rwp.owner == NULL then it's a reader +- * +- * 3.16 - 4.7: +- * rw_semaphore.owner added (https://lwn.net/Articles/596656/) +- * and CONFIG_RWSEM_SPIN_ON_OWNER introduced. +- * If rw_semaphore.owner == NULL then it's a reader +- * +- * 4.8 - 4.16.16: +- * RWSEM_READER_OWNED added as an internal #define. +- * (https://lore.kernel.org/patchwork/patch/678590/) +- * If rw_semaphore.owner == 1 then it's a reader +- * +- * 4.16.17 - 4.19: +- * RWSEM_OWNER_UNKNOWN introduced as ((struct task_struct *)-1L) +- * (https://do-db2.lkml.org/lkml/2018/5/15/985) +- * If rw_semaphore.owner == 1 then it's a reader. +- * +- * 4.20+: +- * RWSEM_OWNER_UNKNOWN changed to ((struct task_struct *)-2L) +- * (https://lkml.org/lkml/2018/9/6/986) +- * If rw_semaphore.owner & 1 then it's a reader, and also the reader's +- * task_struct may be embedded in rw_semaphore->owner. +- */ +-#if defined(CONFIG_RWSEM_SPIN_ON_OWNER) && defined(RWSEM_OWNER_UNKNOWN) +- if (RWSEM_OWNER_UNKNOWN == (struct task_struct *)-2L) { +- /* 4.20+ kernels with CONFIG_RWSEM_SPIN_ON_OWNER */ +- return ((unsigned long) SEM(rwp)->owner & 1); +- } +-#endif +- +- /* < 4.20 kernel or !CONFIG_RWSEM_SPIN_ON_OWNER */ +- return (rw_owner(rwp) == NULL || (unsigned long) rw_owner(rwp) == 1); ++ return (RW_LOCK_HELD(rwp) && rw_owner(rwp) == NULL); + } + + /* +diff --git a/module/spl/spl-rwlock.c b/module/spl/spl-rwlock.c +index 86727ed1957..886e16924e6 100644 +--- a/module/spl/spl-rwlock.c ++++ b/module/spl/spl-rwlock.c +@@ -119,9 +119,6 @@ rwsem_tryupgrade(struct rw_semaphore *rwsem) + if (__rwsem_tryupgrade(rwsem)) { + rwsem_release(&rwsem->dep_map, 1, _RET_IP_); + rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_); +-#ifdef CONFIG_RWSEM_SPIN_ON_OWNER +- rwsem->owner = current; +-#endif + return (1); + } + return (0);