diff options
8 files changed, 256 insertions, 11 deletions
diff --git a/patches/apparmor-use-a-locallock-instead-preempt_disable.patch b/patches/apparmor-use-a-locallock-instead-preempt_disable.patch index 6bd8c73ac89e..13e9a775f5bf 100644 --- a/patches/apparmor-use-a-locallock-instead-preempt_disable.patch +++ b/patches/apparmor-use-a-locallock-instead-preempt_disable.patch @@ -43,7 +43,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + "__get_buffer without aa_buffers_lock\n"); +} + -+#elif CONFIG_DEBUG_PREEMPT ++#elif defined(CONFIG_DEBUG_PREEMPT) #define AA_BUG_PREEMPT_ENABLED(X) AA_BUG(preempt_count() <= 0, X) #else #define AA_BUG_PREEMPT_ENABLED(X) /* nop */ diff --git a/patches/fs-convert-two-mroe-BH_Uptodate_Lock-related-bitspin.patch b/patches/fs-convert-two-mroe-BH_Uptodate_Lock-related-bitspin.patch new file mode 100644 index 000000000000..bc8fad5f6ca0 --- /dev/null +++ b/patches/fs-convert-two-mroe-BH_Uptodate_Lock-related-bitspin.patch @@ -0,0 +1,66 @@ +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Date: Mon, 6 Nov 2017 18:45:30 +0100 +Subject: [PATCH] fs: convert two more BH_Uptodate_Lock related bitspinlocks + +We convert all BH_Uptodate_Lock based bit-spinlocks to use +bh_uptodate_lock_irqsave() instead. Those two were introduced after the +initial change in -RT and were not noticed before. + +Cc: stable-rt@vger.kernel.org +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + fs/ext4/page-io.c | 6 ++---- + fs/xfs/xfs_aops.c | 6 ++---- + 2 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index c2fce4478cca..a8e94791990d 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -94,8 +94,7 @@ static void ext4_finish_bio(struct bio *bio) + * We check all buffers in the page under BH_Uptodate_Lock + * to avoid races with other end io clearing async_write flags + */ +- local_irq_save(flags); +- bit_spin_lock(BH_Uptodate_Lock, &head->b_state); ++ flags = bh_uptodate_lock_irqsave(head); + do { + if (bh_offset(bh) < bio_start || + bh_offset(bh) + bh->b_size > bio_end) { +@@ -107,8 +106,7 @@ static void ext4_finish_bio(struct bio *bio) + if (bio->bi_status) + buffer_io_error(bh); + } while ((bh = bh->b_this_page) != head); +- bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); +- local_irq_restore(flags); ++ bh_uptodate_unlock_irqrestore(head, flags); + if (!under_io) { + #ifdef CONFIG_EXT4_FS_ENCRYPTION + if (data_page) +diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c +index 41b767ecfe50..e35ad09124ab 100644 +--- a/fs/xfs/xfs_aops.c ++++ b/fs/xfs/xfs_aops.c +@@ -107,8 +107,7 @@ xfs_finish_page_writeback( + ASSERT(bvec->bv_offset + bvec->bv_len <= PAGE_SIZE); + ASSERT((bvec->bv_len & (i_blocksize(inode) - 1)) == 0); + +- local_irq_save(flags); +- bit_spin_lock(BH_Uptodate_Lock, &head->b_state); ++ flags = bh_uptodate_lock_irqsave(head); + do { + if (off >= bvec->bv_offset && + off < bvec->bv_offset + bvec->bv_len) { +@@ -130,8 +129,7 @@ xfs_finish_page_writeback( + } + off += bh->b_size; + } while ((bh = bh->b_this_page) != head); +- bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); +- local_irq_restore(flags); ++ bh_uptodate_unlock_irqrestore(head, flags); + + if (!busy) + end_page_writeback(bvec->bv_page); +-- +2.15.0 + diff --git a/patches/localversion.patch b/patches/localversion.patch index 03a80b8b0e80..72cdd2b3c760 100644 --- a/patches/localversion.patch +++ b/patches/localversion.patch @@ -10,4 +10,4 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- /dev/null +++ b/localversion-rt @@ -0,0 +1 @@ -+-rt4 ++-rt5 diff --git a/patches/locking-rt-mutex-fix-deadlock-in-device-mapper-block.patch b/patches/locking-rt-mutex-fix-deadlock-in-device-mapper-block.patch new file mode 100644 index 000000000000..5976db76eddb --- /dev/null +++ b/patches/locking-rt-mutex-fix-deadlock-in-device-mapper-block.patch @@ -0,0 +1,78 @@ +From: Mikulas Patocka <mpatocka@redhat.com> +Date: Mon, 13 Nov 2017 12:56:53 -0500 +Subject: [PATCH] locking/rt-mutex: fix deadlock in device mapper / block-IO + +When some block device driver creates a bio and submits it to another +block device driver, the bio is added to current->bio_list (in order to +avoid unbounded recursion). + +However, this queuing of bios can cause deadlocks, in order to avoid them, +device mapper registers a function flush_current_bio_list. This function +is called when device mapper driver blocks. It redirects bios queued on +current->bio_list to helper workqueues, so that these bios can proceed +even if the driver is blocked. + +The problem with CONFIG_PREEMPT_RT_FULL is that when the device mapper +driver blocks, it won't call flush_current_bio_list (because +tsk_is_pi_blocked returns true in sched_submit_work), so deadlocks in +block device stack can happen. + +Note that we can't call blk_schedule_flush_plug if tsk_is_pi_blocked +returns true - that would cause +BUG_ON(rt_mutex_real_waiter(task->pi_blocked_on)) in +task_blocks_on_rt_mutex when flush_current_bio_list attempts to take a +spinlock. + +So the proper fix is to call blk_schedule_flush_plug in rt_mutex_fastlock, +when fast acquire failed and when the task is about to block. + +CC: stable-rt@vger.kernel.org +[bigeasy: The deadlock is not device-mapper specific, it can also occur + in plain EXT4] +Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/locking/rtmutex.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c +index c72b2acf4db4..1636498cc658 100644 +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -24,6 +24,7 @@ + #include <linux/sched/debug.h> + #include <linux/timer.h> + #include <linux/ww_mutex.h> ++#include <linux/blkdev.h> + + #include "rtmutex_common.h" + +@@ -1939,6 +1940,15 @@ rt_mutex_fastlock(struct rt_mutex *lock, int state, + if (likely(rt_mutex_cmpxchg_acquire(lock, NULL, current))) + return 0; + ++ /* ++ * If rt_mutex blocks, the function sched_submit_work will not call ++ * blk_schedule_flush_plug (because tsk_is_pi_blocked would be true). ++ * We must call blk_schedule_flush_plug here, if we don't call it, ++ * a deadlock in device mapper may happen. ++ */ ++ if (unlikely(blk_needs_flush_plug(current))) ++ blk_schedule_flush_plug(current); ++ + return slowfn(lock, state, NULL, RT_MUTEX_MIN_CHAINWALK, ww_ctx); + } + +@@ -1956,6 +1966,9 @@ rt_mutex_timed_fastlock(struct rt_mutex *lock, int state, + likely(rt_mutex_cmpxchg_acquire(lock, NULL, current))) + return 0; + ++ if (unlikely(blk_needs_flush_plug(current))) ++ blk_schedule_flush_plug(current); ++ + return slowfn(lock, state, timeout, chwalk, ww_ctx); + } + +-- +2.15.0 + diff --git a/patches/locking-rtmutex-re-init-the-wait_lock-in-rt_mutex_in.patch b/patches/locking-rtmutex-re-init-the-wait_lock-in-rt_mutex_in.patch new file mode 100644 index 000000000000..6d229c40db2e --- /dev/null +++ b/patches/locking-rtmutex-re-init-the-wait_lock-in-rt_mutex_in.patch @@ -0,0 +1,37 @@ +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Date: Thu, 16 Nov 2017 16:48:48 +0100 +Subject: [PATCH] locking/rtmutex: re-init the wait_lock in + rt_mutex_init_proxy_locked() + +We could provide a key-class for the lockdep (and fixup all callers) or +move the init to all callers (like it was) in order to avoid lockdep +seeing a double-lock of the wait_lock. + +Reported-by: Fernando Lopez-Lezcano <nando@ccrma.Stanford.EDU> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/locking/rtmutex.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c +index 37433e3b8596..c72b2acf4db4 100644 +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -2261,6 +2261,14 @@ void rt_mutex_init_proxy_locked(struct rt_mutex *lock, + struct task_struct *proxy_owner) + { + __rt_mutex_init(lock, NULL, NULL); ++#ifdef CONFIG_DEBUG_SPINLOCK ++ /* ++ * get another key class for the wait_lock. LOCK_PI and UNLOCK_PI is ++ * holding the ->wait_lock of the proxy_lock while unlocking a sleeping ++ * lock. ++ */ ++ raw_spin_lock_init(&lock->wait_lock); ++#endif + debug_rt_mutex_proxy_lock(lock, proxy_owner); + rt_mutex_set_owner(lock, proxy_owner); + } +-- +2.15.0 + diff --git a/patches/md-raid5-do-not-disable-interrupts.patch b/patches/md-raid5-do-not-disable-interrupts.patch new file mode 100644 index 000000000000..293dfc9b4f96 --- /dev/null +++ b/patches/md-raid5-do-not-disable-interrupts.patch @@ -0,0 +1,59 @@ +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Date: Fri, 17 Nov 2017 16:21:00 +0100 +Subject: [PATCH] md/raid5: do not disable interrupts + +|BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:974 +|in_atomic(): 0, irqs_disabled(): 1, pid: 2992, name: lvm +|CPU: 2 PID: 2992 Comm: lvm Not tainted 4.13.10-rt3+ #54 +|Call Trace: +| dump_stack+0x4f/0x65 +| ___might_sleep+0xfc/0x150 +| atomic_dec_and_spin_lock+0x3c/0x80 +| raid5_release_stripe+0x73/0x110 +| grow_one_stripe+0xce/0xf0 +| setup_conf+0x841/0xaa0 +| raid5_run+0x7e7/0xa40 +| md_run+0x515/0xaf0 +| raid_ctr+0x147d/0x25e0 +| dm_table_add_target+0x155/0x320 +| table_load+0x103/0x320 +| ctl_ioctl+0x1d9/0x510 +| dm_ctl_ioctl+0x9/0x10 +| do_vfs_ioctl+0x8e/0x670 +| SyS_ioctl+0x3c/0x70 +| entry_SYSCALL_64_fastpath+0x17/0x98 + +The interrupts were disabled because ->device_lock is taken with +interrupts disabled. + +Cc: stable-rt@vger.kernel.org +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + drivers/md/raid5.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 4df1cdad153d..2b956738b3e8 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -410,7 +410,7 @@ void raid5_release_stripe(struct stripe_head *sh) + md_wakeup_thread(conf->mddev->thread); + return; + slow_path: +- local_irq_save(flags); ++ local_irq_save_nort(flags); + /* we are ok here if STRIPE_ON_RELEASE_LIST is set or not */ + if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) { + INIT_LIST_HEAD(&list); +@@ -419,7 +419,7 @@ void raid5_release_stripe(struct stripe_head *sh) + spin_unlock(&conf->device_lock); + release_inactive_stripe_list(conf, &list, hash); + } +- local_irq_restore(flags); ++ local_irq_restore_nort(flags); + } + + static inline void remove_hash(struct stripe_head *sh) +-- +2.15.0 + diff --git a/patches/pci-switchtec-Don-t-use-completion-s-wait-queue.patch b/patches/pci-switchtec-Don-t-use-completion-s-wait-queue.patch index d66b6b3353f8..e3accac42add 100644 --- a/patches/pci-switchtec-Don-t-use-completion-s-wait-queue.patch +++ b/patches/pci-switchtec-Don-t-use-completion-s-wait-queue.patch @@ -18,8 +18,8 @@ Cc: Kurt Schwemmer <kurt.schwemmer@microsemi.com> Cc: Logan Gunthorpe <logang@deltatee.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- - drivers/pci/switch/switchtec.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) + drivers/pci/switch/switchtec.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -54,21 +54,22 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> list_add_tail(&stuser->list, &stdev->mrpc_queue); mrpc_cmd_submit(stdev); -@@ -451,7 +452,7 @@ static void mrpc_complete_cmd(struct swi +@@ -451,7 +452,8 @@ static void mrpc_complete_cmd(struct swi stuser->read_len); out: - complete_all(&stuser->comp); ++ stuser->cmd_done = true; + wake_up_interruptible(&stuser->cmd_comp); list_del_init(&stuser->list); stuser_put(stuser); stdev->mrpc_busy = 0; -@@ -721,10 +722,11 @@ static ssize_t switchtec_dev_read(struct +@@ -721,10 +723,11 @@ static ssize_t switchtec_dev_read(struct mutex_unlock(&stdev->mrpc_mutex); if (filp->f_flags & O_NONBLOCK) { - if (!try_wait_for_completion(&stuser->comp)) -+ if (!stuser->cmd_done) ++ if (!READ_ONCE(stuser->cmd_done)) return -EAGAIN; } else { - rc = wait_for_completion_interruptible(&stuser->comp); @@ -77,7 +78,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (rc < 0) return rc; } -@@ -772,7 +774,7 @@ static unsigned int switchtec_dev_poll(s +@@ -772,7 +775,7 @@ static unsigned int switchtec_dev_poll(s struct switchtec_dev *stdev = stuser->stdev; int ret = 0; @@ -86,16 +87,16 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> poll_wait(filp, &stdev->event_wq, wait); if (lock_mutex_and_test_alive(stdev)) -@@ -780,7 +782,7 @@ static unsigned int switchtec_dev_poll(s +@@ -780,7 +783,7 @@ static unsigned int switchtec_dev_poll(s mutex_unlock(&stdev->mrpc_mutex); - if (try_wait_for_completion(&stuser->comp)) -+ if (stuser->cmd_done) ++ if (READ_ONCE(stuser->cmd_done)) ret |= POLLIN | POLLRDNORM; if (stuser->event_cnt != atomic_read(&stdev->event_cnt)) -@@ -1255,7 +1257,8 @@ static void stdev_kill(struct switchtec_ +@@ -1255,7 +1258,8 @@ static void stdev_kill(struct switchtec_ /* Wake up and kill any users waiting on an MRPC request */ list_for_each_entry_safe(stuser, tmpuser, &stdev->mrpc_queue, list) { diff --git a/patches/series b/patches/series index de7948046f40..3c89ea844702 100644 --- a/patches/series +++ b/patches/series @@ -264,6 +264,7 @@ net-wireless-warn-nort.patch # BIT SPINLOCKS - SIGH fs-replace-bh_uptodate_lock-for-rt.patch +fs-convert-two-mroe-BH_Uptodate_Lock-related-bitspin.patch fs-jbd-replace-bh_state-lock.patch # GENIRQ @@ -400,6 +401,8 @@ rtmutex-add-rwsem-implementation-based-on-rtmutex.patch rtmutex-add-rwlock-implementation-based-on-rtmutex.patch rtmutex-wire-up-RT-s-locking.patch rtmutex-add-ww_mutex-addon-for-mutex-rt.patch +locking-rt-mutex-fix-deadlock-in-device-mapper-block.patch +locking-rtmutex-re-init-the-wait_lock-in-rt_mutex_in.patch ptrace-fix-ptrace-vs-tasklist_lock-race.patch RCU-we-need-to-skip-that-warning-but-only-on-sleepin.patch locking-don-t-check-for-__LINUX_SPINLOCK_TYPES_H-on-.patch @@ -449,6 +452,7 @@ block-mq-use-cpu_light.patch block-mq-drop-preempt-disable.patch block-mq-don-t-complete-requests-via-IPI.patch md-raid5-percpu-handling-rt-aware.patch +md-raid5-do-not-disable-interrupts.patch # CPU CHILL rt-introduce-cpu-chill.patch |