[ANNOUNCE] v4.13.13-rt5

From: Sebastian Andrzej Siewior
Date: Fri Nov 17 2017 - 16:04:55 EST


Dear RT folks!

I'm pleased to announce the v4.13.13-rt5 patch set.

Changes since v4.13.13-rt4:

- Correct the elif macro in the apparmor patch applied in the last
release.

- Update the fixup for the PCI switchtec driver. It was introduced in
the v4.13 cycle and was not perfect.

- Some of the bit_spin_locks were converted to proper spinlock
including BH_Uptodate_Lock. After that change some new users popped
up and were not updated. They are now.

- The raid5 code disabled interrupts where it should not on -RT.
Noticed while running the lvm test suite.

- The device-mapper could deadlock itself on -RT. A deadlock could
also happen with plain ext4. Reported and patched by Mikulas
Patocka.

- Lockdep could report a possible double lock in during the futex
lock-pi opcode due to missing annotation. Reported by Fernando
Lopez-Lezcano.

Known issues
None

The delta patch against v4.13.13-rt4 is appended below and can be found here:

https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.13/incr/patch-4.13.13-rt4-rt5.patch.xz

You can get this release via the git tree at:

git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v4.13.13-rt5

The RT patch against v4.13.13 can be found here:

https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.13/older/patch-4.13.13-rt5.patch.xz

The split quilt queue is available at:

https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.13/older/patches-4.13.13-rt5.tar.xz

Sebastian
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
--- 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)
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -452,6 +452,7 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
stuser->read_len);

out:
+ stuser->cmd_done = true;
wake_up_interruptible(&stuser->cmd_comp);
list_del_init(&stuser->list);
stuser_put(stuser);
@@ -722,7 +723,7 @@ static ssize_t switchtec_dev_read(struct file *filp, char __user *data,
mutex_unlock(&stdev->mrpc_mutex);

if (filp->f_flags & O_NONBLOCK) {
- if (!stuser->cmd_done)
+ if (!READ_ONCE(stuser->cmd_done))
return -EAGAIN;
} else {
rc = wait_event_interruptible(stuser->cmd_comp,
@@ -782,7 +783,7 @@ static unsigned int switchtec_dev_poll(struct file *filp, poll_table *wait)

mutex_unlock(&stdev->mrpc_mutex);

- if (stuser->cmd_done)
+ if (READ_ONCE(stuser->cmd_done))
ret |= POLLIN | POLLRDNORM;

if (stuser->event_cnt != atomic_read(&stdev->event_cnt))
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
--- 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
--- 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);
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
--- 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);
}

@@ -2261,6 +2274,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);
}
diff --git a/localversion-rt b/localversion-rt
--- a/localversion-rt
+++ b/localversion-rt
@@ -1 +1 @@
--rt4
+-rt5
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
--- a/security/apparmor/include/path.h
+++ b/security/apparmor/include/path.h
@@ -67,7 +67,7 @@ static inline void AA_BUG_PREEMPT_ENABLED(const char *s)
"__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 */