Skip to content

Commit 1771257

Browse files
paulmckrcuPeter Zijlstra
authored andcommitted
locking/csd_lock: Remove added data from CSD lock debugging
The diagnostics added by this commit were extremely useful in one instance: a5aabac ("locking/csd_lock: Add more data to CSD lock debugging") However, they have not seen much action since, and there have been some concerns expressed that the complexity is not worth the benefit. Therefore, manually revert this commit, but leave a comment telling people where to find these diagnostics. [ paulmck: Apply Juergen Gross feedback. ] Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Juergen Gross <jgross@suse.com> Link: https://lore.kernel.org/r/20230321005516.50558-2-paulmck@kernel.org
1 parent c521986 commit 1771257

2 files changed

Lines changed: 12 additions & 225 deletions

File tree

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -896,10 +896,6 @@
896896
to resolve the hang situation. The default value of
897897
this option depends on the CSD_LOCK_WAIT_DEBUG_DEFAULT
898898
Kconfig option.
899-
0: disable csdlock debugging
900-
1: enable basic csdlock debugging (minor impact)
901-
ext: enable extended csdlock debugging (more impact,
902-
but more data)
903899

904900
dasd= [HW,NET]
905901
See header of drivers/s390/block/dasd_devmap.c.

kernel/smp.c

Lines changed: 12 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -31,59 +31,8 @@
3131

3232
#define CSD_TYPE(_csd) ((_csd)->node.u_flags & CSD_FLAG_TYPE_MASK)
3333

34-
#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
35-
union cfd_seq_cnt {
36-
u64 val;
37-
struct {
38-
u64 src:16;
39-
u64 dst:16;
40-
#define CFD_SEQ_NOCPU 0xffff
41-
u64 type:4;
42-
#define CFD_SEQ_QUEUE 0
43-
#define CFD_SEQ_IPI 1
44-
#define CFD_SEQ_NOIPI 2
45-
#define CFD_SEQ_PING 3
46-
#define CFD_SEQ_PINGED 4
47-
#define CFD_SEQ_HANDLE 5
48-
#define CFD_SEQ_DEQUEUE 6
49-
#define CFD_SEQ_IDLE 7
50-
#define CFD_SEQ_GOTIPI 8
51-
#define CFD_SEQ_HDLEND 9
52-
u64 cnt:28;
53-
} u;
54-
};
55-
56-
static char *seq_type[] = {
57-
[CFD_SEQ_QUEUE] = "queue",
58-
[CFD_SEQ_IPI] = "ipi",
59-
[CFD_SEQ_NOIPI] = "noipi",
60-
[CFD_SEQ_PING] = "ping",
61-
[CFD_SEQ_PINGED] = "pinged",
62-
[CFD_SEQ_HANDLE] = "handle",
63-
[CFD_SEQ_DEQUEUE] = "dequeue (src CPU 0 == empty)",
64-
[CFD_SEQ_IDLE] = "idle",
65-
[CFD_SEQ_GOTIPI] = "gotipi",
66-
[CFD_SEQ_HDLEND] = "hdlend (src CPU 0 == early)",
67-
};
68-
69-
struct cfd_seq_local {
70-
u64 ping;
71-
u64 pinged;
72-
u64 handle;
73-
u64 dequeue;
74-
u64 idle;
75-
u64 gotipi;
76-
u64 hdlend;
77-
};
78-
#endif
79-
8034
struct cfd_percpu {
8135
call_single_data_t csd;
82-
#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
83-
u64 seq_queue;
84-
u64 seq_ipi;
85-
u64 seq_noipi;
86-
#endif
8736
};
8837

8938
struct call_function_data {
@@ -159,18 +108,21 @@ void __init call_function_init(void)
159108
#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
160109

161110
static DEFINE_STATIC_KEY_MAYBE(CONFIG_CSD_LOCK_WAIT_DEBUG_DEFAULT, csdlock_debug_enabled);
162-
static DEFINE_STATIC_KEY_FALSE(csdlock_debug_extended);
163111

112+
/*
113+
* Parse the csdlock_debug= kernel boot parameter.
114+
*
115+
* If you need to restore the old "ext" value that once provided
116+
* additional debugging information, reapply the following commits:
117+
*
118+
* de7b09ef658d ("locking/csd_lock: Prepare more CSD lock debugging")
119+
* a5aabace5fb8 ("locking/csd_lock: Add more data to CSD lock debugging")
120+
*/
164121
static int __init csdlock_debug(char *str)
165122
{
166123
unsigned int val = 0;
167124

168-
if (str && !strcmp(str, "ext")) {
169-
val = 1;
170-
static_branch_enable(&csdlock_debug_extended);
171-
} else
172-
get_option(&str, &val);
173-
125+
get_option(&str, &val);
174126
if (val)
175127
static_branch_enable(&csdlock_debug_enabled);
176128

@@ -181,36 +133,11 @@ __setup("csdlock_debug=", csdlock_debug);
181133
static DEFINE_PER_CPU(call_single_data_t *, cur_csd);
182134
static DEFINE_PER_CPU(smp_call_func_t, cur_csd_func);
183135
static DEFINE_PER_CPU(void *, cur_csd_info);
184-
static DEFINE_PER_CPU(struct cfd_seq_local, cfd_seq_local);
185136

186137
static ulong csd_lock_timeout = 5000; /* CSD lock timeout in milliseconds. */
187138
module_param(csd_lock_timeout, ulong, 0444);
188139

189140
static atomic_t csd_bug_count = ATOMIC_INIT(0);
190-
static u64 cfd_seq;
191-
192-
#define CFD_SEQ(s, d, t, c) \
193-
(union cfd_seq_cnt){ .u.src = s, .u.dst = d, .u.type = t, .u.cnt = c }
194-
195-
static u64 cfd_seq_inc(unsigned int src, unsigned int dst, unsigned int type)
196-
{
197-
union cfd_seq_cnt new, old;
198-
199-
new = CFD_SEQ(src, dst, type, 0);
200-
201-
do {
202-
old.val = READ_ONCE(cfd_seq);
203-
new.u.cnt = old.u.cnt + 1;
204-
} while (cmpxchg(&cfd_seq, old.val, new.val) != old.val);
205-
206-
return old.val;
207-
}
208-
209-
#define cfd_seq_store(var, src, dst, type) \
210-
do { \
211-
if (static_branch_unlikely(&csdlock_debug_extended)) \
212-
var = cfd_seq_inc(src, dst, type); \
213-
} while (0)
214141

215142
/* Record current CSD work for current CPU, NULL to erase. */
216143
static void __csd_lock_record(struct __call_single_data *csd)
@@ -244,80 +171,6 @@ static int csd_lock_wait_getcpu(struct __call_single_data *csd)
244171
return -1;
245172
}
246173

247-
static void cfd_seq_data_add(u64 val, unsigned int src, unsigned int dst,
248-
unsigned int type, union cfd_seq_cnt *data,
249-
unsigned int *n_data, unsigned int now)
250-
{
251-
union cfd_seq_cnt new[2];
252-
unsigned int i, j, k;
253-
254-
new[0].val = val;
255-
new[1] = CFD_SEQ(src, dst, type, new[0].u.cnt + 1);
256-
257-
for (i = 0; i < 2; i++) {
258-
if (new[i].u.cnt <= now)
259-
new[i].u.cnt |= 0x80000000U;
260-
for (j = 0; j < *n_data; j++) {
261-
if (new[i].u.cnt == data[j].u.cnt) {
262-
/* Direct read value trumps generated one. */
263-
if (i == 0)
264-
data[j].val = new[i].val;
265-
break;
266-
}
267-
if (new[i].u.cnt < data[j].u.cnt) {
268-
for (k = *n_data; k > j; k--)
269-
data[k].val = data[k - 1].val;
270-
data[j].val = new[i].val;
271-
(*n_data)++;
272-
break;
273-
}
274-
}
275-
if (j == *n_data) {
276-
data[j].val = new[i].val;
277-
(*n_data)++;
278-
}
279-
}
280-
}
281-
282-
static const char *csd_lock_get_type(unsigned int type)
283-
{
284-
return (type >= ARRAY_SIZE(seq_type)) ? "?" : seq_type[type];
285-
}
286-
287-
static void csd_lock_print_extended(struct __call_single_data *csd, int cpu)
288-
{
289-
struct cfd_seq_local *seq = &per_cpu(cfd_seq_local, cpu);
290-
unsigned int srccpu = csd->node.src;
291-
struct call_function_data *cfd = per_cpu_ptr(&cfd_data, srccpu);
292-
struct cfd_percpu *pcpu = per_cpu_ptr(cfd->pcpu, cpu);
293-
unsigned int now;
294-
union cfd_seq_cnt data[2 * ARRAY_SIZE(seq_type)];
295-
unsigned int n_data = 0, i;
296-
297-
data[0].val = READ_ONCE(cfd_seq);
298-
now = data[0].u.cnt;
299-
300-
cfd_seq_data_add(pcpu->seq_queue, srccpu, cpu, CFD_SEQ_QUEUE, data, &n_data, now);
301-
cfd_seq_data_add(pcpu->seq_ipi, srccpu, cpu, CFD_SEQ_IPI, data, &n_data, now);
302-
cfd_seq_data_add(pcpu->seq_noipi, srccpu, cpu, CFD_SEQ_NOIPI, data, &n_data, now);
303-
304-
cfd_seq_data_add(per_cpu(cfd_seq_local.ping, srccpu), srccpu, CFD_SEQ_NOCPU, CFD_SEQ_PING, data, &n_data, now);
305-
cfd_seq_data_add(per_cpu(cfd_seq_local.pinged, srccpu), srccpu, CFD_SEQ_NOCPU, CFD_SEQ_PINGED, data, &n_data, now);
306-
307-
cfd_seq_data_add(seq->idle, CFD_SEQ_NOCPU, cpu, CFD_SEQ_IDLE, data, &n_data, now);
308-
cfd_seq_data_add(seq->gotipi, CFD_SEQ_NOCPU, cpu, CFD_SEQ_GOTIPI, data, &n_data, now);
309-
cfd_seq_data_add(seq->handle, CFD_SEQ_NOCPU, cpu, CFD_SEQ_HANDLE, data, &n_data, now);
310-
cfd_seq_data_add(seq->dequeue, CFD_SEQ_NOCPU, cpu, CFD_SEQ_DEQUEUE, data, &n_data, now);
311-
cfd_seq_data_add(seq->hdlend, CFD_SEQ_NOCPU, cpu, CFD_SEQ_HDLEND, data, &n_data, now);
312-
313-
for (i = 0; i < n_data; i++) {
314-
pr_alert("\tcsd: cnt(%07x): %04x->%04x %s\n",
315-
data[i].u.cnt & ~0x80000000U, data[i].u.src,
316-
data[i].u.dst, csd_lock_get_type(data[i].u.type));
317-
}
318-
pr_alert("\tcsd: cnt now: %07x\n", now);
319-
}
320-
321174
/*
322175
* Complain if too much time spent waiting. Note that only
323176
* the CSD_TYPE_SYNC/ASYNC types provide the destination CPU,
@@ -368,8 +221,6 @@ static bool csd_lock_wait_toolong(struct __call_single_data *csd, u64 ts0, u64 *
368221
*bug_id, !cpu_cur_csd ? "unresponsive" : "handling this request");
369222
}
370223
if (cpu >= 0) {
371-
if (static_branch_unlikely(&csdlock_debug_extended))
372-
csd_lock_print_extended(csd, cpu);
373224
dump_cpu_task(cpu);
374225
if (!cpu_cur_csd) {
375226
pr_alert("csd: Re-sending CSD lock (#%d) IPI from CPU#%02d to CPU#%02d\n", *bug_id, raw_smp_processor_id(), cpu);
@@ -412,27 +263,7 @@ static __always_inline void csd_lock_wait(struct __call_single_data *csd)
412263

413264
smp_cond_load_acquire(&csd->node.u_flags, !(VAL & CSD_FLAG_LOCK));
414265
}
415-
416-
static void __smp_call_single_queue_debug(int cpu, struct llist_node *node)
417-
{
418-
unsigned int this_cpu = smp_processor_id();
419-
struct cfd_seq_local *seq = this_cpu_ptr(&cfd_seq_local);
420-
struct call_function_data *cfd = this_cpu_ptr(&cfd_data);
421-
struct cfd_percpu *pcpu = per_cpu_ptr(cfd->pcpu, cpu);
422-
423-
cfd_seq_store(pcpu->seq_queue, this_cpu, cpu, CFD_SEQ_QUEUE);
424-
if (llist_add(node, &per_cpu(call_single_queue, cpu))) {
425-
cfd_seq_store(pcpu->seq_ipi, this_cpu, cpu, CFD_SEQ_IPI);
426-
cfd_seq_store(seq->ping, this_cpu, cpu, CFD_SEQ_PING);
427-
send_call_function_single_ipi(cpu);
428-
cfd_seq_store(seq->pinged, this_cpu, cpu, CFD_SEQ_PINGED);
429-
} else {
430-
cfd_seq_store(pcpu->seq_noipi, this_cpu, cpu, CFD_SEQ_NOIPI);
431-
}
432-
}
433266
#else
434-
#define cfd_seq_store(var, src, dst, type)
435-
436267
static void csd_lock_record(struct __call_single_data *csd)
437268
{
438269
}
@@ -470,19 +301,6 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(call_single_data_t, csd_data);
470301

471302
void __smp_call_single_queue(int cpu, struct llist_node *node)
472303
{
473-
#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
474-
if (static_branch_unlikely(&csdlock_debug_extended)) {
475-
unsigned int type;
476-
477-
type = CSD_TYPE(container_of(node, call_single_data_t,
478-
node.llist));
479-
if (type == CSD_TYPE_SYNC || type == CSD_TYPE_ASYNC) {
480-
__smp_call_single_queue_debug(cpu, node);
481-
return;
482-
}
483-
}
484-
#endif
485-
486304
/*
487305
* The list addition should be visible before sending the IPI
488306
* handler locks the list to pull the entry off it because of
@@ -541,8 +359,6 @@ static int generic_exec_single(int cpu, struct __call_single_data *csd)
541359
*/
542360
void generic_smp_call_function_single_interrupt(void)
543361
{
544-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->gotipi, CFD_SEQ_NOCPU,
545-
smp_processor_id(), CFD_SEQ_GOTIPI);
546362
__flush_smp_call_function_queue(true);
547363
}
548364

@@ -570,13 +386,7 @@ static void __flush_smp_call_function_queue(bool warn_cpu_offline)
570386
lockdep_assert_irqs_disabled();
571387

572388
head = this_cpu_ptr(&call_single_queue);
573-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->handle, CFD_SEQ_NOCPU,
574-
smp_processor_id(), CFD_SEQ_HANDLE);
575389
entry = llist_del_all(head);
576-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->dequeue,
577-
/* Special meaning of source cpu: 0 == queue empty */
578-
entry ? CFD_SEQ_NOCPU : 0,
579-
smp_processor_id(), CFD_SEQ_DEQUEUE);
580390
entry = llist_reverse_order(entry);
581391

582392
/* There shouldn't be any pending callbacks on an offline CPU. */
@@ -635,12 +445,8 @@ static void __flush_smp_call_function_queue(bool warn_cpu_offline)
635445
}
636446
}
637447

638-
if (!entry) {
639-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->hdlend,
640-
0, smp_processor_id(),
641-
CFD_SEQ_HDLEND);
448+
if (!entry)
642449
return;
643-
}
644450

645451
/*
646452
* Second; run all !SYNC callbacks.
@@ -678,9 +484,6 @@ static void __flush_smp_call_function_queue(bool warn_cpu_offline)
678484
*/
679485
if (entry)
680486
sched_ttwu_pending(entry);
681-
682-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->hdlend, CFD_SEQ_NOCPU,
683-
smp_processor_id(), CFD_SEQ_HDLEND);
684487
}
685488

686489

@@ -704,8 +507,6 @@ void flush_smp_call_function_queue(void)
704507
if (llist_empty(this_cpu_ptr(&call_single_queue)))
705508
return;
706509

707-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->idle, CFD_SEQ_NOCPU,
708-
smp_processor_id(), CFD_SEQ_IDLE);
709510
local_irq_save(flags);
710511
/* Get the already pending soft interrupts for RT enabled kernels */
711512
was_pending = local_softirq_pending();
@@ -929,8 +730,7 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
929730

930731
cpumask_clear(cfd->cpumask_ipi);
931732
for_each_cpu(cpu, cfd->cpumask) {
932-
struct cfd_percpu *pcpu = per_cpu_ptr(cfd->pcpu, cpu);
933-
call_single_data_t *csd = &pcpu->csd;
733+
call_single_data_t *csd = &per_cpu_ptr(cfd->pcpu, cpu)->csd;
934734

935735
if (cond_func && !cond_func(cpu, info))
936736
continue;
@@ -944,20 +744,13 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
944744
csd->node.src = smp_processor_id();
945745
csd->node.dst = cpu;
946746
#endif
947-
cfd_seq_store(pcpu->seq_queue, this_cpu, cpu, CFD_SEQ_QUEUE);
948747
if (llist_add(&csd->node.llist, &per_cpu(call_single_queue, cpu))) {
949748
__cpumask_set_cpu(cpu, cfd->cpumask_ipi);
950749
nr_cpus++;
951750
last_cpu = cpu;
952-
953-
cfd_seq_store(pcpu->seq_ipi, this_cpu, cpu, CFD_SEQ_IPI);
954-
} else {
955-
cfd_seq_store(pcpu->seq_noipi, this_cpu, cpu, CFD_SEQ_NOIPI);
956751
}
957752
}
958753

959-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->ping, this_cpu, CFD_SEQ_NOCPU, CFD_SEQ_PING);
960-
961754
/*
962755
* Choose the most efficient way to send an IPI. Note that the
963756
* number of CPUs might be zero due to concurrent changes to the
@@ -967,8 +760,6 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
967760
send_call_function_single_ipi(last_cpu);
968761
else if (likely(nr_cpus > 1))
969762
arch_send_call_function_ipi_mask(cfd->cpumask_ipi);
970-
971-
cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->pinged, this_cpu, CFD_SEQ_NOCPU, CFD_SEQ_PINGED);
972763
}
973764

974765
if (run_local && (!cond_func || cond_func(this_cpu, info))) {

0 commit comments

Comments
 (0)