^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * kernel/lockdep_proc.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Runtime locking correctness validator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Started by Ingo Molnar:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Code for /proc/lockdep and /proc/lockdep_stats:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/debug_locks.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sort.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "lockdep_internals.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Since iteration of lock_classes is done without holding the lockdep lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * it is not safe to iterate all_lock_classes list directly as the iteration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * may branch off to free_lock_classes or the zapped list. Iteration is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * directly on the lock_classes array by checking the lock_classes_in_use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * bitmap and max_lock_class_idx.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define iterate_lock_classes(idx, class) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) for (idx = 0, class = lock_classes; idx <= max_lock_class_idx; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) idx++, class++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void *l_next(struct seq_file *m, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct lock_class *class = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ++class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *pos = class - lock_classes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return (*pos > max_lock_class_idx) ? NULL : class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static void *l_start(struct seq_file *m, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long idx = *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (idx > max_lock_class_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return lock_classes + idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void l_stop(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static void print_name(struct seq_file *m, struct lock_class *class)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) char str[KSYM_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) const char *name = class->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) name = __get_key_name(class->key, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) seq_printf(m, "%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) } else{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) seq_printf(m, "%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (class->name_version > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) seq_printf(m, "#%d", class->name_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (class->subclass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) seq_printf(m, "/%d", class->subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int l_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct lock_class *class = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct lock_list *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) char usage[LOCK_USAGE_CHARS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int idx = class - lock_classes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (v == lock_classes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) seq_printf(m, "all lock classes:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (!test_bit(idx, lock_classes_in_use))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) seq_printf(m, "%p", class->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #ifdef CONFIG_DEBUG_LOCKDEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) seq_printf(m, " OPS:%8ld", debug_class_ops_read(class));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #ifdef CONFIG_PROVE_LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) seq_printf(m, " FD:%5ld", lockdep_count_forward_deps(class));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) seq_printf(m, " BD:%5ld", lockdep_count_backward_deps(class));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) get_usage_chars(class, usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) seq_printf(m, " %s", usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) seq_printf(m, ": ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) print_name(m, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) list_for_each_entry(entry, &class->locks_after, entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (entry->distance == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) seq_printf(m, " -> [%p] ", entry->class->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) print_name(m, entry->class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static const struct seq_operations lockdep_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .start = l_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .next = l_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .stop = l_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .show = l_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #ifdef CONFIG_PROVE_LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void *lc_start(struct seq_file *m, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (*pos < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (*pos == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return SEQ_START_TOKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return lock_chains + (*pos - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static void *lc_next(struct seq_file *m, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *pos = lockdep_next_lockchain(*pos - 1) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return lc_start(m, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void lc_stop(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int lc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct lock_chain *chain = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct lock_class *class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static const char * const irq_strs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) [0] = "0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) [LOCK_CHAIN_HARDIRQ_CONTEXT] = "hardirq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) [LOCK_CHAIN_SOFTIRQ_CONTEXT] = "softirq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) [LOCK_CHAIN_SOFTIRQ_CONTEXT|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) LOCK_CHAIN_HARDIRQ_CONTEXT] = "hardirq|softirq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (v == SEQ_START_TOKEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (!nr_free_chain_hlocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) seq_printf(m, "(buggered) ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) seq_printf(m, "all lock chains:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) seq_printf(m, "irq_context: %s\n", irq_strs[chain->irq_context]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i = 0; i < chain->depth; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) class = lock_chain_get_class(chain, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (!class->key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) seq_printf(m, "[%p] ", class->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) print_name(m, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static const struct seq_operations lockdep_chains_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .start = lc_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .next = lc_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .stop = lc_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .show = lc_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #endif /* CONFIG_PROVE_LOCKING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void lockdep_stats_debug_show(struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #ifdef CONFIG_DEBUG_LOCKDEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned long long hi1 = debug_atomic_read(hardirqs_on_events),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) hi2 = debug_atomic_read(hardirqs_off_events),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) hr1 = debug_atomic_read(redundant_hardirqs_on),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) hr2 = debug_atomic_read(redundant_hardirqs_off),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) si1 = debug_atomic_read(softirqs_on_events),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) si2 = debug_atomic_read(softirqs_off_events),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) sr1 = debug_atomic_read(redundant_softirqs_on),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) sr2 = debug_atomic_read(redundant_softirqs_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) seq_printf(m, " chain lookup misses: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) debug_atomic_read(chain_lookup_misses));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) seq_printf(m, " chain lookup hits: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) debug_atomic_read(chain_lookup_hits));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) seq_printf(m, " cyclic checks: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) debug_atomic_read(nr_cyclic_checks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) seq_printf(m, " redundant checks: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) debug_atomic_read(nr_redundant_checks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) seq_printf(m, " redundant links: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) debug_atomic_read(nr_redundant));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) seq_printf(m, " find-mask forwards checks: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) debug_atomic_read(nr_find_usage_forwards_checks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) seq_printf(m, " find-mask backwards checks: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) debug_atomic_read(nr_find_usage_backwards_checks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) seq_printf(m, " hardirq on events: %11llu\n", hi1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) seq_printf(m, " hardirq off events: %11llu\n", hi2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) seq_printf(m, " redundant hardirq ons: %11llu\n", hr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) seq_printf(m, " redundant hardirq offs: %11llu\n", hr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) seq_printf(m, " softirq on events: %11llu\n", si1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) seq_printf(m, " softirq off events: %11llu\n", si2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) seq_printf(m, " redundant softirq ons: %11llu\n", sr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) seq_printf(m, " redundant softirq offs: %11llu\n", sr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int lockdep_stats_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) unsigned long nr_unused = 0, nr_uncategorized = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) nr_irq_safe = 0, nr_irq_unsafe = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) nr_softirq_safe = 0, nr_softirq_unsafe = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) nr_hardirq_safe = 0, nr_hardirq_unsafe = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) nr_irq_read_safe = 0, nr_irq_read_unsafe = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) nr_softirq_read_safe = 0, nr_softirq_read_unsafe = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) nr_hardirq_read_safe = 0, nr_hardirq_read_unsafe = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sum_forward_deps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #ifdef CONFIG_PROVE_LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct lock_class *class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned long idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) iterate_lock_classes(idx, class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!test_bit(idx, lock_classes_in_use))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (class->usage_mask == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) nr_unused++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (class->usage_mask == LOCKF_USED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) nr_uncategorized++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (class->usage_mask & LOCKF_USED_IN_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) nr_irq_safe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (class->usage_mask & LOCKF_ENABLED_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) nr_irq_unsafe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) nr_softirq_safe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (class->usage_mask & LOCKF_ENABLED_SOFTIRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) nr_softirq_unsafe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (class->usage_mask & LOCKF_USED_IN_HARDIRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) nr_hardirq_safe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (class->usage_mask & LOCKF_ENABLED_HARDIRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) nr_hardirq_unsafe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (class->usage_mask & LOCKF_USED_IN_IRQ_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) nr_irq_read_safe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (class->usage_mask & LOCKF_ENABLED_IRQ_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) nr_irq_read_unsafe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) nr_softirq_read_safe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (class->usage_mask & LOCKF_ENABLED_SOFTIRQ_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) nr_softirq_read_unsafe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) nr_hardirq_read_safe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (class->usage_mask & LOCKF_ENABLED_HARDIRQ_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) nr_hardirq_read_unsafe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) sum_forward_deps += lockdep_count_forward_deps(class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #ifdef CONFIG_DEBUG_LOCKDEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) DEBUG_LOCKS_WARN_ON(debug_atomic_read(nr_unused_locks) != nr_unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) seq_printf(m, " lock-classes: %11lu [max: %lu]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) nr_lock_classes, MAX_LOCKDEP_KEYS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) seq_printf(m, " direct dependencies: %11lu [max: %lu]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) nr_list_entries, MAX_LOCKDEP_ENTRIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) seq_printf(m, " indirect dependencies: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) sum_forward_deps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * Total number of dependencies:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * All irq-safe locks may nest inside irq-unsafe locks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * plus all the other known dependencies:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) seq_printf(m, " all direct dependencies: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) nr_irq_unsafe * nr_irq_safe +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) nr_hardirq_unsafe * nr_hardirq_safe +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) nr_list_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) #ifdef CONFIG_PROVE_LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) seq_printf(m, " dependency chains: %11lu [max: %lu]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) lock_chain_count(), MAX_LOCKDEP_CHAINS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) seq_printf(m, " dependency chain hlocks used: %11lu [max: %lu]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) MAX_LOCKDEP_CHAIN_HLOCKS -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) (nr_free_chain_hlocks + nr_lost_chain_hlocks),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) MAX_LOCKDEP_CHAIN_HLOCKS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) seq_printf(m, " dependency chain hlocks lost: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) nr_lost_chain_hlocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) #ifdef CONFIG_TRACE_IRQFLAGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) seq_printf(m, " in-hardirq chains: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) nr_hardirq_chains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) seq_printf(m, " in-softirq chains: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) nr_softirq_chains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) seq_printf(m, " in-process chains: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) nr_process_chains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) seq_printf(m, " stack-trace entries: %11lu [max: %lu]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) #if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) seq_printf(m, " number of stack traces: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) lockdep_stack_trace_count());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) seq_printf(m, " number of stack hash chains: %11llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) lockdep_stack_hash_count());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) seq_printf(m, " combined max dependencies: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) (nr_hardirq_chains + 1) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) (nr_softirq_chains + 1) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) (nr_process_chains + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) seq_printf(m, " hardirq-safe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) nr_hardirq_safe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) seq_printf(m, " hardirq-unsafe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) nr_hardirq_unsafe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) seq_printf(m, " softirq-safe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) nr_softirq_safe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) seq_printf(m, " softirq-unsafe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) nr_softirq_unsafe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) seq_printf(m, " irq-safe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) nr_irq_safe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) seq_printf(m, " irq-unsafe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) nr_irq_unsafe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) seq_printf(m, " hardirq-read-safe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) nr_hardirq_read_safe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) seq_printf(m, " hardirq-read-unsafe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) nr_hardirq_read_unsafe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) seq_printf(m, " softirq-read-safe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) nr_softirq_read_safe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) seq_printf(m, " softirq-read-unsafe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) nr_softirq_read_unsafe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) seq_printf(m, " irq-read-safe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) nr_irq_read_safe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) seq_printf(m, " irq-read-unsafe locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) nr_irq_read_unsafe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) seq_printf(m, " uncategorized locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) nr_uncategorized);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) seq_printf(m, " unused locks: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) nr_unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) seq_printf(m, " max locking depth: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) max_lockdep_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #ifdef CONFIG_PROVE_LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) seq_printf(m, " max bfs queue depth: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) max_bfs_queue_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) seq_printf(m, " max lock class index: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) max_lock_class_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) lockdep_stats_debug_show(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) seq_printf(m, " debug_locks: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) debug_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * Zappped classes and lockdep data buffers reuse statistics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) seq_printf(m, " zapped classes: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) nr_zapped_classes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) #ifdef CONFIG_PROVE_LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) seq_printf(m, " zapped lock chains: %11lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) nr_zapped_lock_chains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) seq_printf(m, " large chain blocks: %11u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) nr_large_chain_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) #ifdef CONFIG_LOCK_STAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct lock_stat_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct lock_class *class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct lock_class_stats stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct lock_stat_seq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct lock_stat_data *iter_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct lock_stat_data stats[MAX_LOCKDEP_KEYS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * sort on absolute number of contentions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static int lock_stat_cmp(const void *l, const void *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) const struct lock_stat_data *dl = l, *dr = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) unsigned long nl, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) nl = dl->stats.read_waittime.nr + dl->stats.write_waittime.nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) nr = dr->stats.read_waittime.nr + dr->stats.write_waittime.nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return nr - nl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static void seq_line(struct seq_file *m, char c, int offset, int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) for (i = 0; i < offset; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) seq_puts(m, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) for (i = 0; i < length; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) seq_printf(m, "%c", c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static void snprint_time(char *buf, size_t bufsiz, s64 nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) s64 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) s32 rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) nr += 5; /* for display rounding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) div = div_s64_rem(nr, 1000, &rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) snprintf(buf, bufsiz, "%lld.%02d", (long long)div, (int)rem/10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static void seq_time(struct seq_file *m, s64 time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) char num[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) snprint_time(num, sizeof(num), time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) seq_printf(m, " %14s", num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static void seq_lock_time(struct seq_file *m, struct lock_time *lt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) seq_printf(m, "%14lu", lt->nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) seq_time(m, lt->min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) seq_time(m, lt->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) seq_time(m, lt->total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) seq_time(m, lt->nr ? div64_u64(lt->total, lt->nr) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static void seq_stats(struct seq_file *m, struct lock_stat_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) const struct lockdep_subclass_key *ckey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct lock_class_stats *stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct lock_class *class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) const char *cname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int i, namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) char name[39];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) class = data->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) stats = &data->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) namelen = 38;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (class->name_version > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) namelen -= 2; /* XXX truncates versions > 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (class->subclass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) namelen -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) rcu_read_lock_sched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) cname = rcu_dereference_sched(class->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) ckey = rcu_dereference_sched(class->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!cname && !ckey) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) rcu_read_unlock_sched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) } else if (!cname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) char str[KSYM_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) const char *key_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) key_name = __get_key_name(ckey, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) snprintf(name, namelen, "%s", key_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) snprintf(name, namelen, "%s", cname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) rcu_read_unlock_sched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) namelen = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (class->name_version > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) snprintf(name+namelen, 3, "#%d", class->name_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) namelen += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (class->subclass) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) snprintf(name+namelen, 3, "/%d", class->subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) namelen += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (stats->write_holdtime.nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (stats->read_holdtime.nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) seq_printf(m, "%38s-W:", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) seq_printf(m, "%40s:", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) seq_printf(m, "%14lu ", stats->bounces[bounce_contended_write]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) seq_lock_time(m, &stats->write_waittime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_write]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) seq_lock_time(m, &stats->write_holdtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (stats->read_holdtime.nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) seq_printf(m, "%38s-R:", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) seq_printf(m, "%14lu ", stats->bounces[bounce_contended_read]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) seq_lock_time(m, &stats->read_waittime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_read]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) seq_lock_time(m, &stats->read_holdtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (stats->read_waittime.nr + stats->write_waittime.nr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (stats->read_holdtime.nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) namelen += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) for (i = 0; i < LOCKSTAT_POINTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) char ip[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (class->contention_point[i] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) seq_line(m, '-', 40-namelen, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) snprintf(ip, sizeof(ip), "[<%p>]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) (void *)class->contention_point[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) seq_printf(m, "%40s %14lu %29s %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) name, stats->contention_point[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ip, (void *)class->contention_point[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) for (i = 0; i < LOCKSTAT_POINTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) char ip[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (class->contending_point[i] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) seq_line(m, '-', 40-namelen, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) snprintf(ip, sizeof(ip), "[<%p>]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) (void *)class->contending_point[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) seq_printf(m, "%40s %14lu %29s %pS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) name, stats->contending_point[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ip, (void *)class->contending_point[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) seq_line(m, '.', 0, 40 + 1 + 12 * (14 + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static void seq_header(struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) seq_puts(m, "lock_stat version 0.4\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (unlikely(!debug_locks))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) seq_printf(m, "*WARNING* lock debugging disabled!! - possibly due to a lockdep warning\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) seq_line(m, '-', 0, 40 + 1 + 12 * (14 + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s %14s %14s "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) "%14s %14s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) "class name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) "con-bounces",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) "contentions",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) "waittime-min",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) "waittime-max",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) "waittime-total",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) "waittime-avg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) "acq-bounces",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) "acquisitions",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) "holdtime-min",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) "holdtime-max",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) "holdtime-total",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) "holdtime-avg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) seq_line(m, '-', 0, 40 + 1 + 12 * (14 + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) seq_printf(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static void *ls_start(struct seq_file *m, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct lock_stat_seq *data = m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct lock_stat_data *iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (*pos == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return SEQ_START_TOKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) iter = data->stats + (*pos - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (iter >= data->iter_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) iter = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static void *ls_next(struct seq_file *m, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) (*pos)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return ls_start(m, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static void ls_stop(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) static int ls_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (v == SEQ_START_TOKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) seq_header(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) seq_stats(m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static const struct seq_operations lockstat_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) .start = ls_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) .next = ls_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) .stop = ls_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) .show = ls_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static int lock_stat_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct lock_class *class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct lock_stat_seq *data = vmalloc(sizeof(struct lock_stat_seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) res = seq_open(file, &lockstat_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct lock_stat_data *iter = data->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct seq_file *m = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) unsigned long idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) iterate_lock_classes(idx, class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!test_bit(idx, lock_classes_in_use))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) iter->class = class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) iter->stats = lock_stats(class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) iter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) data->iter_end = iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) sort(data->stats, data->iter_end - data->stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) sizeof(struct lock_stat_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) lock_stat_cmp, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) m->private = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) vfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static ssize_t lock_stat_write(struct file *file, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct lock_class *class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) unsigned long idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (get_user(c, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (c != '0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) iterate_lock_classes(idx, class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (!test_bit(idx, lock_classes_in_use))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) clear_lock_stats(class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static int lock_stat_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct seq_file *seq = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) vfree(seq->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return seq_release(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static const struct proc_ops lock_stat_proc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .proc_open = lock_stat_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .proc_write = lock_stat_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) .proc_read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .proc_lseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .proc_release = lock_stat_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) #endif /* CONFIG_LOCK_STAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static int __init lockdep_proc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) proc_create_seq("lockdep", S_IRUSR, NULL, &lockdep_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) #ifdef CONFIG_PROVE_LOCKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) proc_create_seq("lockdep_chains", S_IRUSR, NULL, &lockdep_chains_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) proc_create_single("lockdep_stats", S_IRUSR, NULL, lockdep_stats_show);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) #ifdef CONFIG_LOCK_STAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) proc_create("lock_stat", S_IRUSR | S_IWUSR, NULL, &lock_stat_proc_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) __initcall(lockdep_proc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)