History

locking/csd_lock: Add boot parameter for controlling CSD lock debugging

Currently CSD lock debugging can be switched on and off via a kernel config option only. Unfortunately there is at least one problem with CSD lock handling pending for about 2 years now, which has been seen in different environments (mostly when running virtualized under KVM or Xen, at least once on bare metal). Multiple attempts to catch this issue have finally led to introduction of CSD lock debug code, but this code is not in use in most distros as it has some impact on performance. In order to be able to ship kernels with CONFIG_CSD_LOCK_WAIT_DEBUG enabled even for production use, add a boot parameter for switching the debug functionality on. This will reduce any performance impact of the debug coding to a bare minimum when not being used.

Juergen Gross committed 5 years ago

Commit 8d0968c1 parent 50bf8082 files · +40 −4Browse files

Unified · Split

2 files
  1. Documentation/admin-guide/kernel-parameters.txt +6 −0
  2. kernel/smp.c +34 −4
Documentation/admin-guide/kernel-parameters.txt+6−0
@@ -784,6 +784,12 @@ · 783 unmodified lines
784 cs89x0_media= [HW,NET]784 cs89x0_media= [HW,NET]
785 Format: { rj45 | aui | bnc }785 Format: { rj45 | aui | bnc }
786 786
787 csdlock_debug= [KNL] Enable debug add-ons of cross-CPU function call
788 handling. When switched on, additional debug data is
789 printed to the console in case a hanging CPU is
790 detected, and that CPU is pinged again in order to try
791 to resolve the hang situation.
792
787 dasd= [HW,NET]793 dasd= [HW,NET]
788 See header of drivers/s390/block/dasd_devmap.c.794 See header of drivers/s390/block/dasd_devmap.c.
789 795
kernel/smp.c+34−4
@@ -24,6 +24,7 @@ · 23 unmodified lines
24#include <linux/sched/clock.h>24#include <linux/sched/clock.h>
25#include <linux/nmi.h>25#include <linux/nmi.h>
26#include <linux/sched/debug.h>26#include <linux/sched/debug.h>
27#include <linux/jump_label.h>
27 28
28#include "smpboot.h"29#include "smpboot.h"
29#include "sched/smp.h"30#include "sched/smp.h"
@@ -102,6 +103,20 @@ void __init call_function_init(void) · 72 unmodified lines
102 103
103#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG104#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
104 105
106static DEFINE_STATIC_KEY_FALSE(csdlock_debug_enabled);
107
108static int __init csdlock_debug(char *str)
109{
110 unsigned int val = 0;
111
112 get_option(&str, &val);
113 if (val)
114 static_branch_enable(&csdlock_debug_enabled);
115
116 return 0;
117}
118early_param("csdlock_debug", csdlock_debug);
119
105static DEFINE_PER_CPU(call_single_data_t *, cur_csd);120static DEFINE_PER_CPU(call_single_data_t *, cur_csd);
106static DEFINE_PER_CPU(smp_call_func_t, cur_csd_func);121static DEFINE_PER_CPU(smp_call_func_t, cur_csd_func);
107static DEFINE_PER_CPU(void *, cur_csd_info);122static DEFINE_PER_CPU(void *, cur_csd_info);
@@ -110,7 +125,7 @@ static DEFINE_PER_CPU(void *, cur_csd_info); · 2 unmodified lines
110static atomic_t csd_bug_count = ATOMIC_INIT(0);125static atomic_t csd_bug_count = ATOMIC_INIT(0);
111 126
112/* Record current CSD work for current CPU, NULL to erase. */127/* Record current CSD work for current CPU, NULL to erase. */
113static void csd_lock_record(call_single_data_t *csd)128static void __csd_lock_record(call_single_data_t *csd)
114{129{
115 if (!csd) {130 if (!csd) {
116 smp_mb(); /* NULL cur_csd after unlock. */131 smp_mb(); /* NULL cur_csd after unlock. */
@@ -125,7 +140,13 @@ static void csd_lock_record(call_single_data_t *csd) · 8 unmodified lines
125 /* Or before unlock, as the case may be. */140 /* Or before unlock, as the case may be. */
126}141}
127 142
128static __always_inline int csd_lock_wait_getcpu(call_single_data_t *csd)143static __always_inline void csd_lock_record(call_single_data_t *csd)
144{
145 if (static_branch_unlikely(&csdlock_debug_enabled))
146 __csd_lock_record(csd);
147}
148
149static int csd_lock_wait_getcpu(call_single_data_t *csd)
129{150{
130 unsigned int csd_type;151 unsigned int csd_type;
131 152
@@ -140,7 +161,7 @@ static __always_inline int csd_lock_wait_getcpu(call_single_data_t *csd) · 8 unmodified lines
140 * the CSD_TYPE_SYNC/ASYNC types provide the destination CPU,161 * the CSD_TYPE_SYNC/ASYNC types provide the destination CPU,
141 * so waiting on other types gets much less information.162 * so waiting on other types gets much less information.
142 */163 */
143static __always_inline bool csd_lock_wait_toolong(call_single_data_t *csd, u64 ts0, u64 *ts1, int *bug_id)164static bool csd_lock_wait_toolong(call_single_data_t *csd, u64 ts0, u64 *ts1, int *bug_id)
144{165{
145 int cpu = -1;166 int cpu = -1;
146 int cpux;167 int cpux;
@@ -204,7 +225,7 @@ static __always_inline bool csd_lock_wait_toolong(call_single_data_t *csd, u64 t · 57 unmodified lines
204 * previous function call. For multi-cpu calls its even more interesting225 * previous function call. For multi-cpu calls its even more interesting
205 * as we'll have to ensure no other cpu is observing our csd.226 * as we'll have to ensure no other cpu is observing our csd.
206 */227 */
207static __always_inline void csd_lock_wait(call_single_data_t *csd)228static void __csd_lock_wait(call_single_data_t *csd)
208{229{
209 int bug_id = 0;230 int bug_id = 0;
210 u64 ts0, ts1;231 u64 ts0, ts1;
@@ -218,6 +239,15 @@ static __always_inline void csd_lock_wait(call_single_data_t *csd) · 7 unmodified lines
218 smp_acquire__after_ctrl_dep();239 smp_acquire__after_ctrl_dep();
219}240}
220 241
242static __always_inline void csd_lock_wait(call_single_data_t *csd)
243{
244 if (static_branch_unlikely(&csdlock_debug_enabled)) {
245 __csd_lock_wait(csd);
246 return;
247 }
248
249 smp_cond_load_acquire(&csd->node.u_flags, !(VAL & CSD_FLAG_LOCK));
250}
221#else251#else
222static void csd_lock_record(call_single_data_t *csd)252static void csd_lock_record(call_single_data_t *csd)
223{253{

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t