Skip to contentSkip to conversation

Linux 3.18.91-rt98-rc1

PATCH In review Steven Rostedt 2 participants 16 messages Jan 17, 2018

Subsystems (10)
lore
Share & tools
lore

Steven Rostedt

author reviewer
#0 lore raw

cover Linux 3.18.91-rt98-rc1

Dear RT Folks,

This is the RT stable review cycle of patch 3.18.91-rt98-rc1.

Please scream at me if I messed something up. Please test the patches too.

The -rc release will be uploaded to kernel.org and will be deleted when the final release is out. This is just a review release (or release candidate).

The pre-releases will not be pushed to the git repository, only the final release is.

If all goes well, this patch will be converted to the next main release on 1/19/2018.

Enjoy,

-- Steve

To build 3.18.91-rt98-rc1 directly, the following patches should be applied:

http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.tar.xz

http://www.kernel.org/pub/linux/kernel/v3.x/patch-3.18.91.xz

http://www.kernel.org/pub/linux/kernel/projects/rt/3.18/patch-3.18.91-rt98-rc1.patch.xz

You can also build from 3.18.91-rt97 by applying the incremental patch:

http://www.kernel.org/pub/linux/kernel/projects/rt/3.18/incr/patch-3.18.91-rt97-rt98-rc1.patch.xz

Changes from 3.18.91-rt97:

---

Alex Shi (1):
cpu_pm: replace raw_notifier to atomic_notifier

Mike Galbraith (1):
kernel/hrtimer/hotplug: don't wake ktimersoftd while holding the hrtimer base lock

Mikulas Patocka (1):
locking/rt-mutex: fix deadlock in device mapper / block-IO

Sebastian Andrzej Siewior (7):
random: avoid preempt_disable()ed section
fs: convert two more BH_Uptodate_Lock related bitspinlocks md/raid5: do not disable interrupts
Revert "fs: jbd2: pull your plug when waiting for space" kernel/hrtimer: migrate deferred timer on CPU down rt/locking: allow recursive local_trylock()
net: use trylock in icmp_sk

Steven Rostedt (VMware) (1):

      Linux 3.18.91-rt98-rc1

Thomas Gleixner (2):
rtmutex: Make lock_killable work
sched: Prevent task state corruption by spurious lock wakeup

----

 drivers/char/random.c     | 10 ++++++----
 drivers/md/raid5.c        |  4 ++--
 fs/ext4/page-io.c         |  6 ++----
 fs/jbd2/checkpoint.c      |  2 --
 include/linux/locallock.h |  9 +++++++++
 kernel/cpu_pm.c           | 43 ++++++-------------------------------------
 kernel/locking/rtmutex.c  | 44 +++++++++++++++++++++++++++-----------------
 kernel/sched/core.c       |  2 +-
 kernel/time/hrtimer.c     | 20 ++++++++++++++++----
 localversion-rt           |  2 +-
 net/ipv4/icmp.c           |  6 +++++-
 11 files changed, 75 insertions(+), 73 deletions(-)
author reviewer
#1 lore raw

PATCH 1/13 rtmutex: Make lock_killable work

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Thomas Gleixner <[email protected]>

Locking an rt mutex killable does not work because signal handling is restricted to TASK_INTERRUPTIBLE.

Use signal_pending_state() unconditionaly.

---
 kernel/locking/rtmutex.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)
kernel/locking/rtmutex.c +7 -12
index 8d950b4521fc..da35f7ef5324 100644
@@ -1532,18 +1532,13 @@ __rt_mutex_slowlock(struct rt_mutex *lock, int state,
 		if (try_to_take_rt_mutex(lock, current, waiter))
 			break;
 
-		/*
-		 * TASK_INTERRUPTIBLE checks for signals and
-		 * timeout. Ignored otherwise.
-		 */
-		if (unlikely(state == TASK_INTERRUPTIBLE)) {
-			/* Signal pending? */
-			if (signal_pending(current))
-				ret = -EINTR;
-			if (timeout && !timeout->task)
-				ret = -ETIMEDOUT;
-			if (ret)
-				break;
+		if (timeout && !timeout->task) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+		if (signal_pending_state(state, current)) {
+			ret = -EINTR;
+			break;
 		}
 
 		if (ww_ctx && ww_ctx->acquired > 0) {
Signature · 1 line
2.13.2
author reviewer
#2 lore raw

PATCH 2/13 random: avoid preempt_disable()ed section

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

extract_crng() will use sleeping locks while in a preempt_disable() section due to get_cpu_var().
Work around it with local_locks.

---
 drivers/char/random.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/char/random.c +6 -4
index acb8e7c218d1..06c4b06fcea0 100644
@@ -260,6 +260,7 @@
 #include <linux/irq.h>
 #include <linux/syscalls.h>
 #include <linux/completion.h>
+#include <linux/locallock.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -1712,6 +1713,7 @@ int random_int_secret_init(void)
 
 static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
 		__aligned(sizeof(unsigned long));
+static DEFINE_LOCAL_IRQ_LOCK(hash_entropy_int_lock);
 
 /*
  * Get a random word for internal kernel use only. Similar to urandom but
@@ -1727,12 +1729,12 @@ unsigned int get_random_int(void)
 	if (arch_get_random_int(&ret))
 		return ret;
 
-	hash = get_cpu_var(get_random_int_hash);
+	hash = get_locked_var(hash_entropy_int_lock, get_random_int_hash);
 
 	hash[0] += current->pid + jiffies + random_get_entropy();
 	md5_transform(hash, random_int_secret);
 	ret = hash[0];
-	put_cpu_var(get_random_int_hash);
+	put_locked_var(hash_entropy_int_lock, get_random_int_hash);
 
 	return ret;
 }
@@ -1749,12 +1751,12 @@ unsigned long get_random_long(void)
 	if (arch_get_random_long(&ret))
 		return ret;
 
-	hash = get_cpu_var(get_random_int_hash);
+	hash = get_locked_var(hash_entropy_int_lock, get_random_int_hash);
 
 	hash[0] += current->pid + jiffies + random_get_entropy();
 	md5_transform(hash, random_int_secret);
 	ret = *(unsigned long *)hash;
-	put_cpu_var(get_random_int_hash);
+	put_locked_var(hash_entropy_int_lock, get_random_int_hash);
 
 	return ret;
 }
Signature · 1 line
2.13.2
author reviewer
#3 lore raw

PATCH 3/13 sched: Prevent task state corruption by spurious lock wakeup

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Thomas Gleixner <[email protected]>

Mathias and others reported GDB failures on RT.

The following scenario leads to task state corruption:

CPU0 CPU1

T1->state = TASK_XXX;
spin_lock(&lock)
rt_spin_lock_slowlock(&lock->rtmutex)

    raw_spin_lock(&rtm->wait_lock);
    T1->saved_state = current->state;
    T1->state = TASK_UNINTERRUPTIBLE;
						spin_unlock(&lock)
    task_blocks_on_rt_mutex(rtm)  		  rt_spin_lock_slowunlock(&lock->rtmutex)
      queue_waiter(rtm)				    raw_spin_lock(&rtm->wait_lock);
      pi_chain_walk(rtm)
        raw_spin_unlock(&rtm->wait_lock);
						    wake_top_waiter(T1)

      raw_spin_lock(&rtm->wait_lock);

    for (;;) {
      if (__try_to_take_rt_mutex())  <- Succeeds
        break;
      ...
    }

    T1->state = T1->saved_state;
						     try_to_wake_up(T1)
						       ttwu_do_wakeup(T1)
						         T1->state = TASK_RUNNING;

In most cases this is harmless because waiting for some event, which is the usual reason for TASK_[UN]INTERRUPTIBLE has to be safe against other forms of spurious wakeups anyway.

But in case of TASK_TRACED this is actually fatal, because the task loses the TASK_TRACED state. In consequence it fails to consume SIGSTOP which was sent from the debugger and actually delivers SIGSTOP to the task which breaks the ptrace mechanics and brings the debugger into an unexpected state.

The TASK_TRACED state should prevent getting there due to the state matching logic in try_to_wake_up(). But that's not true because wake_up_lock_sleeper() uses TASK_ALL as state mask. That's bogus because lock sleepers always use TASK_UNINTERRUPTIBLE, so the wakeup should use that as well.

The cure is way simpler as figuring it out:

Change the mask used in wake_up_lock_sleeper() from TASK_ALL to TASK_UNINTERRUPTIBLE.

---
 kernel/sched/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/core.c +1 -1
index 2532e4f2d075..b606f31e5034 100644
@@ -1923,7 +1923,7 @@ EXPORT_SYMBOL(wake_up_process);
  */
 int wake_up_lock_sleeper(struct task_struct *p)
 {
-	return try_to_wake_up(p, TASK_ALL, WF_LOCK_SLEEPER);
+	return try_to_wake_up(p, TASK_UNINTERRUPTIBLE, WF_LOCK_SLEEPER);
 }
 
 int wake_up_state(struct task_struct *p, unsigned int state)
Signature · 1 line
2.13.2
author reviewer
#4 lore raw

PATCH 4/13 fs: convert two more BH_Uptodate_Lock related bitspinlocks

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

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.

---
 fs/ext4/page-io.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
fs/ext4/page-io.c +2 -4
index b24a2541a9ba..662c027417ff 100644
@@ -87,8 +87,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) {
@@ -100,8 +99,7 @@ static void ext4_finish_bio(struct bio *bio)
 			if (error)
 				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)
 			end_page_writeback(page);
 	}
Signature · 1 line
2.13.2
author reviewer
#5 lore raw

PATCH 5/13 md/raid5: do not disable interrupts

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

|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.

---
 drivers/md/raid5.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/raid5.c +2 -2
index 6a97d9e930c8..c206ed033542 100644
@@ -433,7 +433,7 @@ static void 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);
@@ -442,7 +442,7 @@ slow_path:
 		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)
Signature · 1 line
2.13.2
author reviewer
#6 lore raw

PATCH 6/13 locking/rt-mutex: fix deadlock in device mapper / block-IO

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Mikulas Patocka <[email protected]>

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: [email protected]
[bigeasy: The deadlock is not device-mapper specific, it can also occur
in plain EXT4]

---
 kernel/locking/rtmutex.c | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)
kernel/locking/rtmutex.c +20 -5
index da35f7ef5324..d58780b59583 100644
@@ -22,6 +22,7 @@
 #include <linux/sched/deadline.h>
 #include <linux/timer.h>
 #include <linux/ww_mutex.h>
+#include <linux/blkdev.h>
 
 #include "rtmutex_common.h"
 
@@ -1843,9 +1844,19 @@ rt_mutex_fastlock(struct rt_mutex *lock, int state,
 	if (likely(rt_mutex_cmpxchg(lock, NULL, current))) {
 		rt_mutex_deadlock_account_lock(lock, current);
 		return 0;
-	} else
-		return slowfn(lock, state, NULL, RT_MUTEX_MIN_CHAINWALK,
-			      ww_ctx);
+	}
+
+	/*
+	 * 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);
 }
 
 static inline int
@@ -1862,8 +1873,12 @@ rt_mutex_timed_fastlock(struct rt_mutex *lock, int state,
 	    likely(rt_mutex_cmpxchg(lock, NULL, current))) {
 		rt_mutex_deadlock_account_lock(lock, current);
 		return 0;
-	} else
-		return slowfn(lock, state, timeout, chwalk, ww_ctx);
+	}
+
+	if (unlikely(blk_needs_flush_plug(current)))
+		blk_schedule_flush_plug(current);
+
+	return slowfn(lock, state, timeout, chwalk, ww_ctx);
 }
 
 static inline int
Signature · 1 line
2.13.2
author reviewer
#7 lore raw

PATCH 7/13 Revert "fs: jbd2: pull your plug when waiting for space"

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

This reverts commit "fs: jbd2: pull your plug when waiting for space". This was a duct-tape fix which shouldn't be needed since commit "locking/rt-mutex: fix deadlock in device mapper / block-IO".

---
 fs/jbd2/checkpoint.c | 2 --
 1 file changed, 2 deletions(-)
fs/jbd2/checkpoint.c +0 -2
index 78c1545a3fab..8c44654ce274 100644
@@ -116,8 +116,6 @@ void __jbd2_log_wait_for_space(journal_t *journal)
 	nblocks = jbd2_space_needed(journal);
 	while (jbd2_log_space_left(journal) < nblocks) {
 		write_unlock(&journal->j_state_lock);
-		if (current->plug)
-			io_schedule();
 		mutex_lock(&journal->j_checkpoint_mutex);
 
 		/*
Signature · 1 line
2.13.2
#8 lore raw

Re: [PATCH RT 07/13] Revert "fs: jbd2: pull your plug when waiting for space"

Quoted 7 lines · Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

Quoted 7 lines

This reverts commit "fs: jbd2: pull your plug when waiting for space". This was a duct-tape fix which shouldn't be needed since commit "locking/rt-mutex: fix deadlock in device mapper / block-IO".

you could also revert 3b5cf23e6b87 ("fs, jbd: pull your plug when waiting for space") which is the same thing but for ext3/jbd.

The code was removed at some point so I did not revert in my tree.

Sebastian

author reviewer
#9 lore raw

Re: [PATCH RT 07/13] Revert "fs: jbd2: pull your plug when waiting for space"

Quoted 12 lines · On Wed, 17 Jan 2018 16:46:44 +0100 Sebastian Andrzej Siewior…
Quoted 11 lines · Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

This reverts commit "fs: jbd2: pull your plug when waiting for space". This was a duct-tape fix which shouldn't be needed since commit "locking/rt-mutex: fix deadlock in device mapper / block-IO".

Quoted 9 lines
Quoted 3 lines

you could also revert 3b5cf23e6b87 ("fs, jbd: pull your plug when waiting for space") which is the same thing but for ext3/jbd.

The code was removed at some point so I did not revert in my tree.

Great! That can be one of the first things Tom does when he takes over 3.18-rt :-)

-- Steve

author reviewer
#10 lore raw

PATCH 8/13 cpu_pm: replace raw_notifier to atomic_notifier

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Alex Shi <[email protected]>

This patch replace a rwlock and raw notifier by atomic notifier which protected by spin_lock and rcu.

The first to reason to have this replace is due to a 'scheduling while
atomic' bug of RT kernel on arm/arm64 platform. On arm/arm64, rwlock
cpu_pm_notifier_lock in cpu_pm cause a potential schedule after irq disable in idle call chain:

cpu_startup_entry
cpu_idle_loop

    local_irq_disable()
    cpuidle_idle_call
      call_cpuidle
        cpuidle_enter
          cpuidle_enter_state
            ->enter :arm_enter_idle_state
              cpu_pm_enter/exit
                CPU_PM_CPU_IDLE_ENTER
                  read_lock(&cpu_pm_notifier_lock); <-- sleep in idle
                     __rt_spin_lock();
                        schedule();

The kernel panic is here:

[    4.609601] BUG: scheduling while atomic: swapper/1/0/0x00000002
[    4.609608] [<ffff0000086fae70>] arm_enter_idle_state+0x18/0x70
[    4.609614] Modules linked in:
[    4.609615] [<ffff0000086f9298>] cpuidle_enter_state+0xf0/0x218
[    4.609620] [<ffff0000086f93f8>] cpuidle_enter+0x18/0x20
[    4.609626] Preemption disabled at:
[    4.609627] [<ffff0000080fa234>] call_cpuidle+0x24/0x40
[    4.609635] [<ffff000008882fa4>] schedule_preempt_disabled+0x1c/0x28
[    4.609639] [<ffff0000080fa49c>] cpu_startup_entry+0x154/0x1f8
[    4.609645] [<ffff00000808e004>] secondary_start_kernel+0x15c/0x1a0

Daniel Lezcano said this notification is needed on arm/arm64 platforms. Sebastian suggested using atomic_notifier instead of rwlock, which is not only removing the sleeping in idle, but also getting better latency improvement.

This patch passed Fengguang's 0day testing.

Cc Sebastian Andrzej Siewior <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Anders Roxell <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Daniel Lezcano <[email protected]>
Cc linux-rt-users <[email protected]>
---
 kernel/cpu_pm.c | 43 ++++++-------------------------------------
 1 file changed, 6 insertions(+), 37 deletions(-)
kernel/cpu_pm.c +6 -37
index 9656a3c36503..9da42f83ee03 100644
@@ -22,14 +22,13 @@
 #include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
 
-static DEFINE_RWLOCK(cpu_pm_notifier_lock);
-static RAW_NOTIFIER_HEAD(cpu_pm_notifier_chain);
+static ATOMIC_NOTIFIER_HEAD(cpu_pm_notifier_chain);
 
 static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)
 {
 	int ret;
 
-	ret = __raw_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL,
+	ret = __atomic_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL,
 		nr_to_call, nr_calls);
 
 	return notifier_to_errno(ret);
@@ -47,14 +46,7 @@ static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)
  */
 int cpu_pm_register_notifier(struct notifier_block *nb)
 {
-	unsigned long flags;
-	int ret;
-
-	write_lock_irqsave(&cpu_pm_notifier_lock, flags);
-	ret = raw_notifier_chain_register(&cpu_pm_notifier_chain, nb);
-	write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
-
-	return ret;
+	return atomic_notifier_chain_register(&cpu_pm_notifier_chain, nb);
 }
 EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);
 
@@ -69,14 +61,7 @@ EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);
  */
 int cpu_pm_unregister_notifier(struct notifier_block *nb)
 {
-	unsigned long flags;
-	int ret;
-
-	write_lock_irqsave(&cpu_pm_notifier_lock, flags);
-	ret = raw_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);
-	write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);
-
-	return ret;
+	return atomic_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);
 }
 EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);
 
@@ -100,7 +85,6 @@ int cpu_pm_enter(void)
 	int nr_calls;
 	int ret = 0;
 
-	read_lock(&cpu_pm_notifier_lock);
 	ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls);
 	if (ret)
 		/*
@@ -108,7 +92,6 @@ int cpu_pm_enter(void)
 		 * PM entry who are notified earlier to prepare for it.
 		 */
 		cpu_pm_notify(CPU_PM_ENTER_FAILED, nr_calls - 1, NULL);
-	read_unlock(&cpu_pm_notifier_lock);
 
 	return ret;
 }
@@ -128,13 +111,7 @@ EXPORT_SYMBOL_GPL(cpu_pm_enter);
  */
 int cpu_pm_exit(void)
 {
-	int ret;
-
-	read_lock(&cpu_pm_notifier_lock);
-	ret = cpu_pm_notify(CPU_PM_EXIT, -1, NULL);
-	read_unlock(&cpu_pm_notifier_lock);
-
-	return ret;
+	return cpu_pm_notify(CPU_PM_EXIT, -1, NULL);
 }
 EXPORT_SYMBOL_GPL(cpu_pm_exit);
 
@@ -159,7 +136,6 @@ int cpu_cluster_pm_enter(void)
 	int nr_calls;
 	int ret = 0;
 
-	read_lock(&cpu_pm_notifier_lock);
 	ret = cpu_pm_notify(CPU_CLUSTER_PM_ENTER, -1, &nr_calls);
 	if (ret)
 		/*
@@ -167,7 +143,6 @@ int cpu_cluster_pm_enter(void)
 		 * PM entry who are notified earlier to prepare for it.
 		 */
 		cpu_pm_notify(CPU_CLUSTER_PM_ENTER_FAILED, nr_calls - 1, NULL);
-	read_unlock(&cpu_pm_notifier_lock);
 
 	return ret;
 }
@@ -190,13 +165,7 @@ EXPORT_SYMBOL_GPL(cpu_cluster_pm_enter);
  */
 int cpu_cluster_pm_exit(void)
 {
-	int ret;
-
-	read_lock(&cpu_pm_notifier_lock);
-	ret = cpu_pm_notify(CPU_CLUSTER_PM_EXIT, -1, NULL);
-	read_unlock(&cpu_pm_notifier_lock);
-
-	return ret;
+	return cpu_pm_notify(CPU_CLUSTER_PM_EXIT, -1, NULL);
 }
 EXPORT_SYMBOL_GPL(cpu_cluster_pm_exit);
 
Signature · 1 line
2.13.2
author reviewer
#11 lore raw

PATCH 9/13 kernel/hrtimer: migrate deferred timer on CPU down

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

hrtimers, which were deferred to the softirq context, and expire between softirq shutdown and hrtimer migration are dangling around. If the CPU goes back up the list head will be initialized and this corrupts the timer's list. It will remain unnoticed until a hrtimer_cancel(). This moves those timers so they will expire.

---
 kernel/time/hrtimer.c | 5 +++++
 1 file changed, 5 insertions(+)
kernel/time/hrtimer.c +5 -0
index 2c1597d2bd6d..2e869c707628 100644
@@ -1959,6 +1959,11 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
 		/* Clear the migration state bit */
 		timer->state &= ~HRTIMER_STATE_MIGRATE;
 	}
+#ifdef CONFIG_PREEMPT_RT_BASE
+	list_splice_tail(&old_base->expired, &new_base->expired);
+	if (!list_empty(&new_base->expired))
+		raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+#endif
 }
 
 static void migrate_hrtimers(int scpu)
Signature · 1 line
2.13.2
author reviewer
#12 lore raw

PATCH 10/13 kernel/hrtimer/hotplug: dont wake ktimersoftd while holding the hrtimer base lock

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Mike Galbraith <[email protected]>

kernel/hrtimer: don't wakeup a process while holding the hrtimer base lock missed a path, namely hrtimers_dead_cpu() -> migrate_hrtimer_list(). Defer raising softirq until after base lock has been released there as well.

---
 kernel/time/hrtimer.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)
kernel/time/hrtimer.c +13 -6
index 2e869c707628..1e7c0c9b0e77 100644
@@ -1928,7 +1928,7 @@ static void init_hrtimers_cpu(int cpu)
 
 #ifdef CONFIG_HOTPLUG_CPU
 
-static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
+static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
 				struct hrtimer_clock_base *new_base)
 {
 	struct hrtimer *timer;
@@ -1961,15 +1961,19 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
 	}
 #ifdef CONFIG_PREEMPT_RT_BASE
 	list_splice_tail(&old_base->expired, &new_base->expired);
-	if (!list_empty(&new_base->expired))
-		raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+	/*
+	 * Tell the caller to raise HRTIMER_SOFTIRQ.  We can't safely
+	 * acquire ktimersoftd->pi_lock while the base lock is held.
+	 */
+	return !list_empty(&new_base->expired);
 #endif
+	return 0;
 }
 
 static void migrate_hrtimers(int scpu)
 {
 	struct hrtimer_cpu_base *old_base, *new_base;
-	int i;
+	int i, raise = 0;
 
 	BUG_ON(cpu_online(scpu));
 	tick_cancel_sched_timer(scpu);
@@ -1985,13 +1989,16 @@ static void migrate_hrtimers(int scpu)
 	raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
 
 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
-		migrate_hrtimer_list(&old_base->clock_base[i],
-				     &new_base->clock_base[i]);
+		raise |= migrate_hrtimer_list(&old_base->clock_base[i],
+					      &new_base->clock_base[i]);
 	}
 
 	raw_spin_unlock(&old_base->lock);
 	raw_spin_unlock(&new_base->lock);
 
+	if (raise)
+		raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+
 	/* Check, if we got expired work to do */
 	__hrtimer_peek_ahead_timers();
 	local_irq_enable();
Signature · 1 line
2.13.2
author reviewer
#13 lore raw

PATCH 11/13 rt/locking: allow recursive local_trylock()

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

required for following networking patch which does recursive try-lock. While at it, add the !RT version of it because it did not yet exist.

---
 include/linux/locallock.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/linux/locallock.h +9 -0
index 015271ff8ec8..930ec941c2c0 100644
@@ -77,6 +77,9 @@ static inline int __local_trylock(struct local_irq_lock *lv)
 		lv->owner = current;
 		lv->nestcnt = 1;
 		return 1;
+	} else if (lv->owner == current) {
+		lv->nestcnt++;
+		return 1;
 	}
 	return 0;
 }
@@ -250,6 +253,12 @@ static inline int __local_unlock_irqrestore(struct local_irq_lock *lv,
 
 static inline void local_irq_lock_init(int lvar) { }
 
+#define local_trylock(lvar)					\
+	({							\
+		preempt_disable();				\
+		1;						\
+	})
+
 #define local_lock(lvar)			preempt_disable()
 #define local_unlock(lvar)			preempt_enable()
 #define local_lock_irq(lvar)			local_irq_disable()
Signature · 1 line
2.13.2
author reviewer
#14 lore raw

PATCH 12/13 net: use trylock in icmp_sk

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

The locking path can be recursive (same as for sk->sk_lock.slock) and therefore we need a trylock version for the locallock, too.

---
 net/ipv4/icmp.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/ipv4/icmp.c +5 -1
index 76b11e3e2b95..434eef536092 100644
@@ -218,7 +218,11 @@ static inline struct sock *icmp_xmit_lock(struct net *net)
 
 	local_bh_disable();
 
-	local_lock(icmp_sk_lock);
+	if (!local_trylock(icmp_sk_lock)) {
+		local_bh_enable();
+		return NULL;
+	}
+
 	sk = icmp_sk(net);
 
 	if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
Signature · 1 line
2.13.2
author reviewer
#15 lore raw

PATCH 13/13 Linux 3.18.91-rt98-rc1

In reply to Steven Rostedt

3.18.91-rt98-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: "Steven Rostedt (VMware)" <[email protected]>

---
 localversion-rt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
localversion-rt +1 -1
index f5eca15b92de..195e539be979 100644
@@ -1 +1 @@
--rt97
+-rt98-rc1
Signature · 1 line
2.13.2