mirror of https://github.com/archzfs/zfs-dkms
parent
7522777e12
commit
55e12298c3
@ -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
|
||||
|
@ -0,0 +1,236 @@ |
||||
From ee1848356f32e31f001ca96cc68e06a445f72108 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
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 <hutter2@llnl.gov>
|
||||
Reviewed-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
|
||||
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
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 <linux/rwsem.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
-/* 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 <sys/rwlock.h>
|
||||
-#include <linux/module.h>
|
||||
-
|
||||
-#if defined(CONFIG_PREEMPT_RT_FULL)
|
||||
-
|
||||
-#include <linux/rtmutex.h>
|
||||
-#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) { }
|
@ -0,0 +1,155 @@ |
||||
From d4b15200e75a37da053589aa2ddff06872302ac2 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
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 <hutter2@llnl.gov>
|
||||
Reviewed-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
|
||||
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
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);
|
Loading…
Reference in new issue