1 From 041205afee7e151a0ac10c9b5314186cf65417dc Mon Sep 17 00:00:00 2001
2 From: Brian Behlendorf <behlendorf1@llnl.gov>
3 Date: Fri, 12 Jul 2019 13:27:24 -0700
4 Subject: [PATCH] Linux 5.3 compat: rw_semaphore owner
6 Commit https://github.com/torvalds/linux/commit/94a9717b updated the
7 rwsem's owner field to contain additional flags describing the rwsem's
8 state. Rather then update the wrappers to mask out these bits, the
9 code no longer relies on the owner stored by the kernel. This does
10 increase the size of a krwlock_t but it makes the implementation
11 less sensitive to future kernel changes.
13 Reviewed-by: Tony Hutter <hutter2@llnl.gov>
14 Reviewed-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
15 Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
18 include/spl/sys/rwlock.h | 68 +++-------------------------------------
19 module/spl/spl-rwlock.c | 3 --
20 2 files changed, 5 insertions(+), 66 deletions(-)
22 diff --git a/include/spl/sys/rwlock.h b/include/spl/sys/rwlock.h
23 index 408defac20d..5e052b532a4 100644
24 --- a/include/spl/sys/rwlock.h
25 +++ b/include/spl/sys/rwlock.h
26 @@ -78,15 +78,9 @@ typedef enum {
31 - * If CONFIG_RWSEM_SPIN_ON_OWNER is defined, rw_semaphore will have an owner
32 - * field, so we don't need our own.
35 struct rw_semaphore rw_rwlock;
36 -#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
41 #endif /* CONFIG_LOCKDEP */
42 @@ -97,31 +91,19 @@ typedef struct {
44 spl_rw_set_owner(krwlock_t *rwp)
47 - * If CONFIG_RWSEM_SPIN_ON_OWNER is defined, down_write, up_write,
48 - * downgrade_write and __init_rwsem will set/clear owner for us.
50 -#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
51 rwp->rw_owner = current;
56 spl_rw_clear_owner(krwlock_t *rwp)
58 -#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
63 static inline kthread_t *
64 rw_owner(krwlock_t *rwp)
66 -#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
67 - return (SEM(rwp)->owner);
69 return (rwp->rw_owner);
74 @@ -148,62 +130,22 @@ spl_rw_lockdep_on_maybe(krwlock_t *rwp) \
75 #define spl_rw_lockdep_on_maybe(rwp)
76 #endif /* CONFIG_LOCKDEP */
80 -RW_WRITE_HELD(krwlock_t *rwp)
81 +RW_LOCK_HELD(krwlock_t *rwp)
83 - return (rw_owner(rwp) == current);
84 + return (spl_rwsem_is_locked(SEM(rwp)));
88 -RW_LOCK_HELD(krwlock_t *rwp)
89 +RW_WRITE_HELD(krwlock_t *rwp)
91 - return (spl_rwsem_is_locked(SEM(rwp)));
92 + return (rw_owner(rwp) == current);
96 RW_READ_HELD(krwlock_t *rwp)
98 - if (!RW_LOCK_HELD(rwp))
102 - * rw_semaphore cheat sheet:
105 - * There's no rw_semaphore.owner, so use rwp.owner instead.
106 - * If rwp.owner == NULL then it's a reader
109 - * rw_semaphore.owner added (https://lwn.net/Articles/596656/)
110 - * and CONFIG_RWSEM_SPIN_ON_OWNER introduced.
111 - * If rw_semaphore.owner == NULL then it's a reader
114 - * RWSEM_READER_OWNED added as an internal #define.
115 - * (https://lore.kernel.org/patchwork/patch/678590/)
116 - * If rw_semaphore.owner == 1 then it's a reader
119 - * RWSEM_OWNER_UNKNOWN introduced as ((struct task_struct *)-1L)
120 - * (https://do-db2.lkml.org/lkml/2018/5/15/985)
121 - * If rw_semaphore.owner == 1 then it's a reader.
124 - * RWSEM_OWNER_UNKNOWN changed to ((struct task_struct *)-2L)
125 - * (https://lkml.org/lkml/2018/9/6/986)
126 - * If rw_semaphore.owner & 1 then it's a reader, and also the reader's
127 - * task_struct may be embedded in rw_semaphore->owner.
129 -#if defined(CONFIG_RWSEM_SPIN_ON_OWNER) && defined(RWSEM_OWNER_UNKNOWN)
130 - if (RWSEM_OWNER_UNKNOWN == (struct task_struct *)-2L) {
131 - /* 4.20+ kernels with CONFIG_RWSEM_SPIN_ON_OWNER */
132 - return ((unsigned long) SEM(rwp)->owner & 1);
136 - /* < 4.20 kernel or !CONFIG_RWSEM_SPIN_ON_OWNER */
137 - return (rw_owner(rwp) == NULL || (unsigned long) rw_owner(rwp) == 1);
138 + return (RW_LOCK_HELD(rwp) && rw_owner(rwp) == NULL);
142 diff --git a/module/spl/spl-rwlock.c b/module/spl/spl-rwlock.c
143 index 86727ed1957..886e16924e6 100644
144 --- a/module/spl/spl-rwlock.c
145 +++ b/module/spl/spl-rwlock.c
146 @@ -119,9 +119,6 @@ rwsem_tryupgrade(struct rw_semaphore *rwsem)
147 if (__rwsem_tryupgrade(rwsem)) {
148 rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
149 rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
150 -#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
151 - rwsem->owner = current;
156 From e7a99dab2b065ac2f8736a65d1b226d21754d771 Mon Sep 17 00:00:00 2001
157 From: Brian Behlendorf <behlendorf1@llnl.gov>
158 Date: Fri, 12 Jul 2019 14:06:36 -0700
159 Subject: [PATCH] Linux 5.3 compat: retire rw_tryupgrade()
161 The Linux kernel's rwsem's have never provided an interface to
162 allow a reader to be upgraded to a writer. Historically, this
163 functionality has been implemented by a SPL wrapper function.
164 However, this approach depends on internal knowledge of the
165 rw_semaphore and is therefore rather brittle.
167 Since the ZFS code must always be able to fallback to rw_exit()
168 and rw_enter() when an rw_tryupgrade() fails; this functionality
169 isn't critical. Furthermore, the only potentially performance
170 sensitive consumer is dmu_zfetch() and no decrease in performance
171 was observed with this change applied. See the PR comments for
172 additional testing details.
174 Therefore, it is being retired to make the build more robust and
175 to simplify the rwlock implementation.
177 Reviewed-by: Tony Hutter <hutter2@llnl.gov>
178 Reviewed-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
179 Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
182 include/spl/sys/rwlock.h | 60 +++--------------------
183 module/spl/spl-rwlock.c | 101 ---------------------------------------
184 2 files changed, 7 insertions(+), 154 deletions(-)
186 diff --git a/include/spl/sys/rwlock.h b/include/spl/sys/rwlock.h
187 index 5e052b532a4..89e02fa8f04 100644
188 --- a/include/spl/sys/rwlock.h
189 +++ b/include/spl/sys/rwlock.h
191 #include <linux/rwsem.h>
192 #include <linux/sched.h>
194 -/* Linux kernel compatibility */
195 -#if defined(CONFIG_PREEMPT_RT_FULL)
196 -#define SPL_RWSEM_SINGLE_READER_VALUE (1)
197 -#define SPL_RWSEM_SINGLE_WRITER_VALUE (0)
198 -#elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK)
199 -#define SPL_RWSEM_SINGLE_READER_VALUE (1)
200 -#define SPL_RWSEM_SINGLE_WRITER_VALUE (-1)
201 -#elif defined(RWSEM_ACTIVE_MASK)
202 -#define SPL_RWSEM_SINGLE_READER_VALUE (RWSEM_ACTIVE_READ_BIAS)
203 -#define SPL_RWSEM_SINGLE_WRITER_VALUE (RWSEM_ACTIVE_WRITE_BIAS)
206 -/* Linux 3.16 changed activity to count for rwsem-spinlock */
207 -#if defined(CONFIG_PREEMPT_RT_FULL)
208 -#define RWSEM_COUNT(sem) sem->read_depth
209 -#elif defined(HAVE_RWSEM_ACTIVITY)
210 -#define RWSEM_COUNT(sem) sem->activity
211 -/* Linux 4.8 changed count to an atomic_long_t for !rwsem-spinlock */
212 -#elif defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
213 -#define RWSEM_COUNT(sem) atomic_long_read(&(sem)->count)
215 -#define RWSEM_COUNT(sem) sem->count
218 -#if defined(RWSEM_SPINLOCK_IS_RAW)
219 -#define spl_rwsem_lock_irqsave(lk, fl) raw_spin_lock_irqsave(lk, fl)
220 -#define spl_rwsem_unlock_irqrestore(lk, fl) \
221 - raw_spin_unlock_irqrestore(lk, fl)
222 -#define spl_rwsem_trylock_irqsave(lk, fl) raw_spin_trylock_irqsave(lk, fl)
224 -#define spl_rwsem_lock_irqsave(lk, fl) spin_lock_irqsave(lk, fl)
225 -#define spl_rwsem_unlock_irqrestore(lk, fl) spin_unlock_irqrestore(lk, fl)
226 -#define spl_rwsem_trylock_irqsave(lk, fl) spin_trylock_irqsave(lk, fl)
227 -#endif /* RWSEM_SPINLOCK_IS_RAW */
229 -#define spl_rwsem_is_locked(rwsem) rwsem_is_locked(rwsem)
234 @@ -133,7 +96,7 @@ spl_rw_lockdep_on_maybe(krwlock_t *rwp) \
236 RW_LOCK_HELD(krwlock_t *rwp)
238 - return (spl_rwsem_is_locked(SEM(rwp)));
239 + return (rwsem_is_locked(SEM(rwp)));
243 @@ -170,6 +133,12 @@ RW_READ_HELD(krwlock_t *rwp)
245 #define rw_destroy(rwp) ((void) 0)
248 + * Upgrading a rwsem from a reader to a writer is not supported by the
249 + * Linux kernel. The lock must be dropped and reacquired as a writer.
251 +#define rw_tryupgrade(rwp) RW_WRITE_HELD(rwp)
253 #define rw_tryenter(rwp, rw) \
256 @@ -228,24 +197,9 @@ RW_READ_HELD(krwlock_t *rwp)
257 spl_rw_lockdep_on_maybe(rwp); \
260 -#define rw_tryupgrade(rwp) \
264 - if (RW_WRITE_HELD(rwp)) { \
267 - spl_rw_lockdep_off_maybe(rwp); \
268 - if ((_rc_ = rwsem_tryupgrade(SEM(rwp)))) \
269 - spl_rw_set_owner(rwp); \
270 - spl_rw_lockdep_on_maybe(rwp); \
276 int spl_rw_init(void);
277 void spl_rw_fini(void);
278 -int rwsem_tryupgrade(struct rw_semaphore *rwsem);
280 #endif /* _SPL_RWLOCK_H */
281 diff --git a/module/spl/spl-rwlock.c b/module/spl/spl-rwlock.c
282 index 886e16924e6..10f7c38db4e 100644
283 --- a/module/spl/spl-rwlock.c
284 +++ b/module/spl/spl-rwlock.c
286 * Solaris Porting Layer (SPL) Reader/Writer Lock Implementation.
289 -#include <sys/rwlock.h>
290 -#include <linux/module.h>
292 -#if defined(CONFIG_PREEMPT_RT_FULL)
294 -#include <linux/rtmutex.h>
295 -#define RT_MUTEX_OWNER_MASKALL 1UL
298 -__rwsem_tryupgrade(struct rw_semaphore *rwsem)
300 -#if defined(READER_BIAS) && defined(WRITER_BIAS)
302 - * After the 4.9.20-rt16 kernel the realtime patch series lifted the
303 - * single reader restriction. While this could be accommodated by
304 - * adding additional compatibility code assume the rwsem can never
305 - * be upgraded. All caller must already cleanly handle this case.
309 - ASSERT((struct task_struct *)
310 - ((unsigned long)rwsem->lock.owner & ~RT_MUTEX_OWNER_MASKALL) ==
314 - * Prior to 4.9.20-rt16 kernel the realtime patch series, rwsem is
315 - * implemented as a single mutex held by readers and writers alike.
316 - * However, this implementation would prevent a thread from taking
317 - * a read lock twice, as the mutex would already be locked on
318 - * the second attempt. Therefore the implementation allows a
319 - * single thread to take a rwsem as read lock multiple times
320 - * tracking that nesting as read_depth counter.
322 - if (rwsem->read_depth <= 1) {
324 - * In case, the current thread has not taken the lock
325 - * more than once as read lock, we can allow an
326 - * upgrade to a write lock. rwsem_rt.h implements
327 - * write locks as read_depth == 0.
329 - rwsem->read_depth = 0;
335 -#elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK)
337 -__rwsem_tryupgrade(struct rw_semaphore *rwsem)
340 - unsigned long flags;
341 - spl_rwsem_lock_irqsave(&rwsem->wait_lock, flags);
342 - if (RWSEM_COUNT(rwsem) == SPL_RWSEM_SINGLE_READER_VALUE &&
343 - list_empty(&rwsem->wait_list)) {
345 - RWSEM_COUNT(rwsem) = SPL_RWSEM_SINGLE_WRITER_VALUE;
347 - spl_rwsem_unlock_irqrestore(&rwsem->wait_lock, flags);
350 -#elif defined(RWSEM_ACTIVE_MASK)
351 -#if defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
353 -__rwsem_tryupgrade(struct rw_semaphore *rwsem)
356 - val = atomic_long_cmpxchg(&rwsem->count, SPL_RWSEM_SINGLE_READER_VALUE,
357 - SPL_RWSEM_SINGLE_WRITER_VALUE);
358 - return (val == SPL_RWSEM_SINGLE_READER_VALUE);
362 -__rwsem_tryupgrade(struct rw_semaphore *rwsem)
364 - typeof(rwsem->count) val;
365 - val = cmpxchg(&rwsem->count, SPL_RWSEM_SINGLE_READER_VALUE,
366 - SPL_RWSEM_SINGLE_WRITER_VALUE);
367 - return (val == SPL_RWSEM_SINGLE_READER_VALUE);
372 -__rwsem_tryupgrade(struct rw_semaphore *rwsem)
379 -rwsem_tryupgrade(struct rw_semaphore *rwsem)
381 - if (__rwsem_tryupgrade(rwsem)) {
382 - rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
383 - rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
388 -EXPORT_SYMBOL(rwsem_tryupgrade);
390 int spl_rw_init(void) { return 0; }
391 void spl_rw_fini(void) { }
392 From a9ebdfdd43204b8f907c5395cd68b2d745544730 Mon Sep 17 00:00:00 2001
393 From: Tony Hutter <hutter2@llnl.gov>
394 Date: Wed, 21 Aug 2019 09:29:23 -0700
395 Subject: [PATCH] Linux 5.3: Fix switch() fall though compiler errors
397 Fix some switch() fall-though compiler errors:
399 abd.c:1504:9: error: this statement may fall through
401 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
402 Signed-off-by: Tony Hutter <hutter2@llnl.gov>
405 module/lua/llex.c | 9 ++++++---
406 module/zfs/abd.c | 4 ++++
407 module/zfs/vdev_raidz_math_scalar.c | 1 +
408 3 files changed, 11 insertions(+), 3 deletions(-)
410 diff --git a/module/lua/llex.c b/module/lua/llex.c
411 index 8760155d054..50c301f599f 100644
412 --- a/module/lua/llex.c
413 +++ b/module/lua/llex.c
414 @@ -431,9 +431,12 @@ static int llex (LexState *ls, SemInfo *seminfo) {
416 read_long_string(ls, seminfo, sep);
419 - else if (sep == -1) return '[';
420 - else lexerror(ls, "invalid long string delimiter", TK_STRING);
421 + } else if (sep == -1) {
424 + lexerror(ls, "invalid long string delimiter", TK_STRING);
430 diff --git a/module/zfs/abd.c b/module/zfs/abd.c
431 index 9f688d9bc2b..8b2514404a8 100644
432 --- a/module/zfs/abd.c
433 +++ b/module/zfs/abd.c
434 @@ -1408,8 +1408,10 @@ abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
437 len = MIN(caiters[2].iter_mapsize, len);
438 + /* falls through */
440 len = MIN(caiters[1].iter_mapsize, len);
441 + /* falls through */
443 len = MIN(caiters[0].iter_mapsize, len);
445 @@ -1499,9 +1501,11 @@ abd_raidz_rec_iterate(abd_t **cabds, abd_t **tabds,
447 len = MIN(xiters[2].iter_mapsize, len);
448 len = MIN(citers[2].iter_mapsize, len);
449 + /* falls through */
451 len = MIN(xiters[1].iter_mapsize, len);
452 len = MIN(citers[1].iter_mapsize, len);
453 + /* falls through */
455 len = MIN(xiters[0].iter_mapsize, len);
456 len = MIN(citers[0].iter_mapsize, len);
457 diff --git a/module/zfs/vdev_raidz_math_scalar.c b/module/zfs/vdev_raidz_math_scalar.c
458 index a693bff63ff..cd742e146ca 100644
459 --- a/module/zfs/vdev_raidz_math_scalar.c
460 +++ b/module/zfs/vdev_raidz_math_scalar.c
461 @@ -142,6 +142,7 @@ static const struct {
462 a.b[6] = mul_lt[a.b[6]]; \
463 a.b[5] = mul_lt[a.b[5]]; \
464 a.b[4] = mul_lt[a.b[4]]; \
465 + /* falls through */ \
467 a.b[3] = mul_lt[a.b[3]]; \
468 a.b[2] = mul_lt[a.b[2]]; \
469 From ff4b68eedc307e6e9b7f3890b809cbb0e9d73856 Mon Sep 17 00:00:00 2001
470 From: Dominic Pearson <dsp@technoanimal.net>
471 Date: Tue, 20 Aug 2019 00:22:52 +0200
472 Subject: [PATCH] Linux 5.3 compat: Makefile subdir-m no longer supported
474 Uses obj-m instead, due to kernel changes.
476 See LKML: Masahiro Yamada, Tue, 6 Aug 2019 19:03:23 +0900
478 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
479 Reviewed-by: Tony Hutter <hutter2@llnl.gov>
480 Signed-off-by: Dominic Pearson <dsp@technoanimal.net>
483 .gitignore | 11 +++++++++++
484 module/Makefile.in | 24 ++++++++++++------------
485 2 files changed, 23 insertions(+), 12 deletions(-)
487 diff --git a/.gitignore b/.gitignore
488 index 549fa59f382..ae9e22dfa7b 100644
491 @@ -63,3 +63,14 @@ cscope.*
498 +/module/avl/zavl.mod
500 +/module/lua/zlua.mod
501 +/module/nvpair/znvpair.mod
503 +/module/unicode/zunicode.mod
504 +/module/zcommon/zcommon.mod
506 diff --git a/module/Makefile.in b/module/Makefile.in
507 index eca7691aedb..7477dbe5650 100644
508 --- a/module/Makefile.in
509 +++ b/module/Makefile.in
528 INSTALL_MOD_DIR ?= extra
530 @@ -60,14 +60,15 @@ modules_install:
532 @# Uninstall the kernel modules
533 kmoddir=$(DESTDIR)$(INSTALL_MOD_PATH)/lib/modules/@LINUX_VERSION@
534 - list='$(subdir-m)'; for subdir in $$list; do \
535 - $(RM) -R $$kmoddir/$(INSTALL_MOD_DIR)/$$subdir; \
536 + list='$(obj-m)'; for objdir in $$list; do \
537 + $(RM) -R $$kmoddir/$(INSTALL_MOD_DIR)/$$objdir; \
541 - list='$(subdir-m)'; for subdir in $$list; do \
542 - (cd @top_srcdir@/module && find $$subdir -name '*.c' -o -name '*.h' -o -name '*.S' |\
543 - xargs cp --parents -t $$distdir); \
544 + list='$(obj-m)'; for objdir in $$list; do \
545 + (cd @top_srcdir@/module && find $$objdir \
546 + -name '*.c' -o -name '*.h' -o -name '*.S' | \
547 + xargs cp --parents -t @abs_top_builddir@/module/$$distdir); \
550 distclean maintainer-clean: clean