1df3e764dSLuis Chamberlain // SPDX-License-Identifier: GPL-2.0-or-later
2df3e764dSLuis Chamberlain /*
3df3e764dSLuis Chamberlain * Debugging module statistics.
4df3e764dSLuis Chamberlain *
5df3e764dSLuis Chamberlain * Copyright (C) 2023 Luis Chamberlain <mcgrof@kernel.org>
6df3e764dSLuis Chamberlain */
7df3e764dSLuis Chamberlain
8df3e764dSLuis Chamberlain #include <linux/module.h>
9635dc383SArnd Bergmann #include <uapi/linux/module.h>
10df3e764dSLuis Chamberlain #include <linux/string.h>
11df3e764dSLuis Chamberlain #include <linux/printk.h>
12df3e764dSLuis Chamberlain #include <linux/slab.h>
13df3e764dSLuis Chamberlain #include <linux/list.h>
14df3e764dSLuis Chamberlain #include <linux/debugfs.h>
15df3e764dSLuis Chamberlain #include <linux/rculist.h>
16df3e764dSLuis Chamberlain #include <linux/math.h>
17df3e764dSLuis Chamberlain
18df3e764dSLuis Chamberlain #include "internal.h"
19df3e764dSLuis Chamberlain
20df3e764dSLuis Chamberlain /**
21df3e764dSLuis Chamberlain * DOC: module debugging statistics overview
22df3e764dSLuis Chamberlain *
23df3e764dSLuis Chamberlain * Enabling CONFIG_MODULE_STATS enables module debugging statistics which
24df3e764dSLuis Chamberlain * are useful to monitor and root cause memory pressure issues with module
25df3e764dSLuis Chamberlain * loading. These statistics are useful to allow us to improve production
26df3e764dSLuis Chamberlain * workloads.
27df3e764dSLuis Chamberlain *
28df3e764dSLuis Chamberlain * The current module debugging statistics supported help keep track of module
29df3e764dSLuis Chamberlain * loading failures to enable improvements either for kernel module auto-loading
30df3e764dSLuis Chamberlain * usage (request_module()) or interactions with userspace. Statistics are
31df3e764dSLuis Chamberlain * provided to track all possible failures in the finit_module() path and memory
32df3e764dSLuis Chamberlain * wasted in this process space. Each of the failure counters are associated
33df3e764dSLuis Chamberlain * to a type of module loading failure which is known to incur a certain amount
34df3e764dSLuis Chamberlain * of memory allocation loss. In the worst case loading a module will fail after
35df3e764dSLuis Chamberlain * a 3 step memory allocation process:
36df3e764dSLuis Chamberlain *
37df3e764dSLuis Chamberlain * a) memory allocated with kernel_read_file_from_fd()
38df3e764dSLuis Chamberlain * b) module decompression processes the file read from
39df3e764dSLuis Chamberlain * kernel_read_file_from_fd(), and vmap() is used to map
40df3e764dSLuis Chamberlain * the decompressed module to a new local buffer which represents
41df3e764dSLuis Chamberlain * a copy of the decompressed module passed from userspace. The buffer
42df3e764dSLuis Chamberlain * from kernel_read_file_from_fd() is freed right away.
43df3e764dSLuis Chamberlain * c) layout_and_allocate() allocates space for the final resting
44df3e764dSLuis Chamberlain * place where we would keep the module if it were to be processed
45df3e764dSLuis Chamberlain * successfully.
46df3e764dSLuis Chamberlain *
47df3e764dSLuis Chamberlain * If a failure occurs after these three different allocations only one
48df3e764dSLuis Chamberlain * counter will be incremented with the summation of the allocated bytes freed
49df3e764dSLuis Chamberlain * incurred during this failure. Likewise, if module loading failed only after
50df3e764dSLuis Chamberlain * step b) a separate counter is used and incremented for the bytes freed and
51df3e764dSLuis Chamberlain * not used during both of those allocations.
52df3e764dSLuis Chamberlain *
53df3e764dSLuis Chamberlain * Virtual memory space can be limited, for example on x86 virtual memory size
54df3e764dSLuis Chamberlain * defaults to 128 MiB. We should strive to limit and avoid wasting virtual
55df3e764dSLuis Chamberlain * memory allocations when possible. These module debugging statistics help
56df3e764dSLuis Chamberlain * to evaluate how much memory is being wasted on bootup due to module loading
57df3e764dSLuis Chamberlain * failures.
58df3e764dSLuis Chamberlain *
59df3e764dSLuis Chamberlain * All counters are designed to be incremental. Atomic counters are used so to
60df3e764dSLuis Chamberlain * remain simple and avoid delays and deadlocks.
61df3e764dSLuis Chamberlain */
62df3e764dSLuis Chamberlain
63df3e764dSLuis Chamberlain /**
64df3e764dSLuis Chamberlain * DOC: dup_failed_modules - tracks duplicate failed modules
65df3e764dSLuis Chamberlain *
66df3e764dSLuis Chamberlain * Linked list of modules which failed to be loaded because an already existing
67df3e764dSLuis Chamberlain * module with the same name was already being processed or already loaded.
68df3e764dSLuis Chamberlain * The finit_module() system call incurs heavy virtual memory allocations. In
69df3e764dSLuis Chamberlain * the worst case an finit_module() system call can end up allocating virtual
70df3e764dSLuis Chamberlain * memory 3 times:
71df3e764dSLuis Chamberlain *
72df3e764dSLuis Chamberlain * 1) kernel_read_file_from_fd() call uses vmalloc()
73df3e764dSLuis Chamberlain * 2) optional module decompression uses vmap()
74df3e764dSLuis Chamberlain * 3) layout_and allocate() can use vzalloc() or an arch specific variation of
75df3e764dSLuis Chamberlain * vmalloc to deal with ELF sections requiring special permissions
76df3e764dSLuis Chamberlain *
77df3e764dSLuis Chamberlain * In practice on a typical boot today most finit_module() calls fail due to
78df3e764dSLuis Chamberlain * the module with the same name already being loaded or about to be processed.
79df3e764dSLuis Chamberlain * All virtual memory allocated to these failed modules will be freed with
80df3e764dSLuis Chamberlain * no functional use.
81df3e764dSLuis Chamberlain *
82df3e764dSLuis Chamberlain * To help with this the dup_failed_modules allows us to track modules which
83df3e764dSLuis Chamberlain * failed to load due to the fact that a module was already loaded or being
84df3e764dSLuis Chamberlain * processed. There are only two points at which we can fail such calls,
85df3e764dSLuis Chamberlain * we list them below along with the number of virtual memory allocation
86df3e764dSLuis Chamberlain * calls:
87df3e764dSLuis Chamberlain *
88df3e764dSLuis Chamberlain * a) FAIL_DUP_MOD_BECOMING: at the end of early_mod_check() before
89064f4536SLuis Chamberlain * layout_and_allocate().
90df3e764dSLuis Chamberlain * - with module decompression: 2 virtual memory allocation calls
91df3e764dSLuis Chamberlain * - without module decompression: 1 virtual memory allocation calls
92df3e764dSLuis Chamberlain * b) FAIL_DUP_MOD_LOAD: after layout_and_allocate() on add_unformed_module()
93df3e764dSLuis Chamberlain * - with module decompression 3 virtual memory allocation calls
94df3e764dSLuis Chamberlain * - without module decompression 2 virtual memory allocation calls
95df3e764dSLuis Chamberlain *
96df3e764dSLuis Chamberlain * We should strive to get this list to be as small as possible. If this list
97df3e764dSLuis Chamberlain * is not empty it is a reflection of possible work or optimizations possible
98df3e764dSLuis Chamberlain * either in-kernel or in userspace.
99df3e764dSLuis Chamberlain */
100df3e764dSLuis Chamberlain static LIST_HEAD(dup_failed_modules);
101df3e764dSLuis Chamberlain
102df3e764dSLuis Chamberlain /**
103df3e764dSLuis Chamberlain * DOC: module statistics debugfs counters
104df3e764dSLuis Chamberlain *
105df3e764dSLuis Chamberlain * The total amount of wasted virtual memory allocation space during module
106df3e764dSLuis Chamberlain * loading can be computed by adding the total from the summation:
107df3e764dSLuis Chamberlain *
108df3e764dSLuis Chamberlain * * @invalid_kread_bytes +
109df3e764dSLuis Chamberlain * @invalid_decompress_bytes +
110df3e764dSLuis Chamberlain * @invalid_becoming_bytes +
111df3e764dSLuis Chamberlain * @invalid_mod_bytes
112df3e764dSLuis Chamberlain *
113df3e764dSLuis Chamberlain * The following debugfs counters are available to inspect module loading
114df3e764dSLuis Chamberlain * failures:
115df3e764dSLuis Chamberlain *
116df3e764dSLuis Chamberlain * * total_mod_size: total bytes ever used by all modules we've dealt with on
117df3e764dSLuis Chamberlain * this system
118df3e764dSLuis Chamberlain * * total_text_size: total bytes of the .text and .init.text ELF section
119df3e764dSLuis Chamberlain * sizes we've dealt with on this system
120df3e764dSLuis Chamberlain * * invalid_kread_bytes: bytes allocated and then freed on failures which
121df3e764dSLuis Chamberlain * happen due to the initial kernel_read_file_from_fd(). kernel_read_file_from_fd()
122df3e764dSLuis Chamberlain * uses vmalloc(). These should typically not happen unless your system is
123df3e764dSLuis Chamberlain * under memory pressure.
124df3e764dSLuis Chamberlain * * invalid_decompress_bytes: number of bytes allocated and freed due to
125df3e764dSLuis Chamberlain * memory allocations in the module decompression path that use vmap().
126df3e764dSLuis Chamberlain * These typically should not happen unless your system is under memory
127df3e764dSLuis Chamberlain * pressure.
128df3e764dSLuis Chamberlain * * invalid_becoming_bytes: total number of bytes allocated and freed used
129df3e764dSLuis Chamberlain * used to read the kernel module userspace wants us to read before we
130064f4536SLuis Chamberlain * promote it to be processed to be added to our @modules linked list. These
131064f4536SLuis Chamberlain * failures can happen if we had a check in between a successful kernel_read_file_from_fd()
132df3e764dSLuis Chamberlain * call and right before we allocate the our private memory for the module
133df3e764dSLuis Chamberlain * which would be kept if the module is successfully loaded. The most common
134df3e764dSLuis Chamberlain * reason for this failure is when userspace is racing to load a module
135df3e764dSLuis Chamberlain * which it does not yet see loaded. The first module to succeed in
136df3e764dSLuis Chamberlain * add_unformed_module() will add a module to our &modules list and
137df3e764dSLuis Chamberlain * subsequent loads of modules with the same name will error out at the
138064f4536SLuis Chamberlain * end of early_mod_check(). The check for module_patient_check_exists()
139064f4536SLuis Chamberlain * at the end of early_mod_check() prevents duplicate allocations
140df3e764dSLuis Chamberlain * on layout_and_allocate() for modules already being processed. These
141df3e764dSLuis Chamberlain * duplicate failed modules are non-fatal, however they typically are
142df3e764dSLuis Chamberlain * indicative of userspace not seeing a module in userspace loaded yet and
143df3e764dSLuis Chamberlain * unnecessarily trying to load a module before the kernel even has a chance
144df3e764dSLuis Chamberlain * to begin to process prior requests. Although duplicate failures can be
145df3e764dSLuis Chamberlain * non-fatal, we should try to reduce vmalloc() pressure proactively, so
146df3e764dSLuis Chamberlain * ideally after boot this will be close to as 0 as possible. If module
147df3e764dSLuis Chamberlain * decompression was used we also add to this counter the cost of the
148df3e764dSLuis Chamberlain * initial kernel_read_file_from_fd() of the compressed module. If module
149df3e764dSLuis Chamberlain * decompression was not used the value represents the total allocated and
150df3e764dSLuis Chamberlain * freed bytes in kernel_read_file_from_fd() calls for these type of
151df3e764dSLuis Chamberlain * failures. These failures can occur because:
152df3e764dSLuis Chamberlain *
153df3e764dSLuis Chamberlain * * module_sig_check() - module signature checks
154df3e764dSLuis Chamberlain * * elf_validity_cache_copy() - some ELF validation issue
155df3e764dSLuis Chamberlain * * early_mod_check():
156df3e764dSLuis Chamberlain *
157df3e764dSLuis Chamberlain * * blacklisting
158df3e764dSLuis Chamberlain * * failed to rewrite section headers
159df3e764dSLuis Chamberlain * * version magic
160df3e764dSLuis Chamberlain * * live patch requirements didn't check out
161df3e764dSLuis Chamberlain * * the module was detected as being already present
162df3e764dSLuis Chamberlain *
163df3e764dSLuis Chamberlain * * invalid_mod_bytes: these are the total number of bytes allocated and
164df3e764dSLuis Chamberlain * freed due to failures after we did all the sanity checks of the module
165df3e764dSLuis Chamberlain * which userspace passed to us and after our first check that the module
166df3e764dSLuis Chamberlain * is unique. A module can still fail to load if we detect the module is
167df3e764dSLuis Chamberlain * loaded after we allocate space for it with layout_and_allocate(), we do
168df3e764dSLuis Chamberlain * this check right before processing the module as live and run its
169df3e764dSLuis Chamberlain * initialization routines. Note that you have a failure of this type it
170df3e764dSLuis Chamberlain * also means the respective kernel_read_file_from_fd() memory space was
171df3e764dSLuis Chamberlain * also freed and not used, and so we increment this counter with twice
172df3e764dSLuis Chamberlain * the size of the module. Additionally if you used module decompression
173df3e764dSLuis Chamberlain * the size of the compressed module is also added to this counter.
174df3e764dSLuis Chamberlain *
175df3e764dSLuis Chamberlain * * modcount: how many modules we've loaded in our kernel life time
176df3e764dSLuis Chamberlain * * failed_kreads: how many modules failed due to failed kernel_read_file_from_fd()
177df3e764dSLuis Chamberlain * * failed_decompress: how many failed module decompression attempts we've had.
178df3e764dSLuis Chamberlain * These really should not happen unless your compression / decompression
179df3e764dSLuis Chamberlain * might be broken.
180df3e764dSLuis Chamberlain * * failed_becoming: how many modules failed after we kernel_read_file_from_fd()
181df3e764dSLuis Chamberlain * it and before we allocate memory for it with layout_and_allocate(). This
182df3e764dSLuis Chamberlain * counter is never incremented if you manage to validate the module and
183df3e764dSLuis Chamberlain * call layout_and_allocate() for it.
184df3e764dSLuis Chamberlain * * failed_load_modules: how many modules failed once we've allocated our
185df3e764dSLuis Chamberlain * private space for our module using layout_and_allocate(). These failures
186df3e764dSLuis Chamberlain * should hopefully mostly be dealt with already. Races in theory could
187df3e764dSLuis Chamberlain * still exist here, but it would just mean the kernel had started processing
188df3e764dSLuis Chamberlain * two threads concurrently up to early_mod_check() and one thread won.
189df3e764dSLuis Chamberlain * These failures are good signs the kernel or userspace is doing something
190df3e764dSLuis Chamberlain * seriously stupid or that could be improved. We should strive to fix these,
191df3e764dSLuis Chamberlain * but it is perhaps not easy to fix them. A recent example are the modules
192df3e764dSLuis Chamberlain * requests incurred for frequency modules, a separate module request was
193df3e764dSLuis Chamberlain * being issued for each CPU on a system.
194df3e764dSLuis Chamberlain */
195df3e764dSLuis Chamberlain
196df3e764dSLuis Chamberlain atomic_long_t total_mod_size;
197df3e764dSLuis Chamberlain atomic_long_t total_text_size;
198df3e764dSLuis Chamberlain atomic_long_t invalid_kread_bytes;
199df3e764dSLuis Chamberlain atomic_long_t invalid_decompress_bytes;
200df3e764dSLuis Chamberlain static atomic_long_t invalid_becoming_bytes;
201df3e764dSLuis Chamberlain static atomic_long_t invalid_mod_bytes;
202df3e764dSLuis Chamberlain atomic_t modcount;
203df3e764dSLuis Chamberlain atomic_t failed_kreads;
204df3e764dSLuis Chamberlain atomic_t failed_decompress;
205df3e764dSLuis Chamberlain static atomic_t failed_becoming;
206df3e764dSLuis Chamberlain static atomic_t failed_load_modules;
207df3e764dSLuis Chamberlain
mod_fail_to_str(struct mod_fail_load * mod_fail)208df3e764dSLuis Chamberlain static const char *mod_fail_to_str(struct mod_fail_load *mod_fail)
209df3e764dSLuis Chamberlain {
210df3e764dSLuis Chamberlain if (test_bit(FAIL_DUP_MOD_BECOMING, &mod_fail->dup_fail_mask) &&
211df3e764dSLuis Chamberlain test_bit(FAIL_DUP_MOD_LOAD, &mod_fail->dup_fail_mask))
212df3e764dSLuis Chamberlain return "Becoming & Load";
213df3e764dSLuis Chamberlain if (test_bit(FAIL_DUP_MOD_BECOMING, &mod_fail->dup_fail_mask))
214df3e764dSLuis Chamberlain return "Becoming";
215df3e764dSLuis Chamberlain if (test_bit(FAIL_DUP_MOD_LOAD, &mod_fail->dup_fail_mask))
216df3e764dSLuis Chamberlain return "Load";
217df3e764dSLuis Chamberlain return "Bug-on-stats";
218df3e764dSLuis Chamberlain }
219df3e764dSLuis Chamberlain
mod_stat_bump_invalid(struct load_info * info,int flags)220df3e764dSLuis Chamberlain void mod_stat_bump_invalid(struct load_info *info, int flags)
221df3e764dSLuis Chamberlain {
222df3e764dSLuis Chamberlain atomic_long_add(info->len * 2, &invalid_mod_bytes);
223df3e764dSLuis Chamberlain atomic_inc(&failed_load_modules);
224df3e764dSLuis Chamberlain #if defined(CONFIG_MODULE_DECOMPRESS)
225df3e764dSLuis Chamberlain if (flags & MODULE_INIT_COMPRESSED_FILE)
226a81b1fc8SArnd Bergmann atomic_long_add(info->compressed_len, &invalid_mod_bytes);
227df3e764dSLuis Chamberlain #endif
228df3e764dSLuis Chamberlain }
229df3e764dSLuis Chamberlain
mod_stat_bump_becoming(struct load_info * info,int flags)230df3e764dSLuis Chamberlain void mod_stat_bump_becoming(struct load_info *info, int flags)
231df3e764dSLuis Chamberlain {
232df3e764dSLuis Chamberlain atomic_inc(&failed_becoming);
233df3e764dSLuis Chamberlain atomic_long_add(info->len, &invalid_becoming_bytes);
234df3e764dSLuis Chamberlain #if defined(CONFIG_MODULE_DECOMPRESS)
235df3e764dSLuis Chamberlain if (flags & MODULE_INIT_COMPRESSED_FILE)
236df3e764dSLuis Chamberlain atomic_long_add(info->compressed_len, &invalid_becoming_bytes);
237df3e764dSLuis Chamberlain #endif
238df3e764dSLuis Chamberlain }
239df3e764dSLuis Chamberlain
try_add_failed_module(const char * name,enum fail_dup_mod_reason reason)240df3e764dSLuis Chamberlain int try_add_failed_module(const char *name, enum fail_dup_mod_reason reason)
241df3e764dSLuis Chamberlain {
242df3e764dSLuis Chamberlain struct mod_fail_load *mod_fail;
243df3e764dSLuis Chamberlain
244df3e764dSLuis Chamberlain list_for_each_entry_rcu(mod_fail, &dup_failed_modules, list,
245df3e764dSLuis Chamberlain lockdep_is_held(&module_mutex)) {
246df3e764dSLuis Chamberlain if (!strcmp(mod_fail->name, name)) {
247df3e764dSLuis Chamberlain atomic_long_inc(&mod_fail->count);
248df3e764dSLuis Chamberlain __set_bit(reason, &mod_fail->dup_fail_mask);
249df3e764dSLuis Chamberlain goto out;
250df3e764dSLuis Chamberlain }
251df3e764dSLuis Chamberlain }
252df3e764dSLuis Chamberlain
253df3e764dSLuis Chamberlain mod_fail = kzalloc(sizeof(*mod_fail), GFP_KERNEL);
254df3e764dSLuis Chamberlain if (!mod_fail)
255df3e764dSLuis Chamberlain return -ENOMEM;
256df3e764dSLuis Chamberlain memcpy(mod_fail->name, name, strlen(name));
257df3e764dSLuis Chamberlain __set_bit(reason, &mod_fail->dup_fail_mask);
258df3e764dSLuis Chamberlain atomic_long_inc(&mod_fail->count);
259df3e764dSLuis Chamberlain list_add_rcu(&mod_fail->list, &dup_failed_modules);
260df3e764dSLuis Chamberlain out:
261df3e764dSLuis Chamberlain return 0;
262df3e764dSLuis Chamberlain }
263df3e764dSLuis Chamberlain
264df3e764dSLuis Chamberlain /*
265df3e764dSLuis Chamberlain * At 64 bytes per module and assuming a 1024 bytes preamble we can fit the
266df3e764dSLuis Chamberlain * 112 module prints within 8k.
267df3e764dSLuis Chamberlain *
268df3e764dSLuis Chamberlain * 1024 + (64*112) = 8k
269df3e764dSLuis Chamberlain */
270df3e764dSLuis Chamberlain #define MAX_PREAMBLE 1024
271df3e764dSLuis Chamberlain #define MAX_FAILED_MOD_PRINT 112
272df3e764dSLuis Chamberlain #define MAX_BYTES_PER_MOD 64
read_file_mod_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)273df3e764dSLuis Chamberlain static ssize_t read_file_mod_stats(struct file *file, char __user *user_buf,
274df3e764dSLuis Chamberlain size_t count, loff_t *ppos)
275df3e764dSLuis Chamberlain {
276df3e764dSLuis Chamberlain struct mod_fail_load *mod_fail;
277df3e764dSLuis Chamberlain unsigned int len, size, count_failed = 0;
278df3e764dSLuis Chamberlain char *buf;
279*d36f6efbSHarshit Mogalapalli int ret;
280df3e764dSLuis Chamberlain u32 live_mod_count, fkreads, fdecompress, fbecoming, floads;
281719ccd80SArnd Bergmann unsigned long total_size, text_size, ikread_bytes, ibecoming_bytes,
282719ccd80SArnd Bergmann idecompress_bytes, imod_bytes, total_virtual_lost;
283df3e764dSLuis Chamberlain
284df3e764dSLuis Chamberlain live_mod_count = atomic_read(&modcount);
285df3e764dSLuis Chamberlain fkreads = atomic_read(&failed_kreads);
286df3e764dSLuis Chamberlain fdecompress = atomic_read(&failed_decompress);
287df3e764dSLuis Chamberlain fbecoming = atomic_read(&failed_becoming);
288df3e764dSLuis Chamberlain floads = atomic_read(&failed_load_modules);
289df3e764dSLuis Chamberlain
290719ccd80SArnd Bergmann total_size = atomic_long_read(&total_mod_size);
291719ccd80SArnd Bergmann text_size = atomic_long_read(&total_text_size);
292719ccd80SArnd Bergmann ikread_bytes = atomic_long_read(&invalid_kread_bytes);
293719ccd80SArnd Bergmann idecompress_bytes = atomic_long_read(&invalid_decompress_bytes);
294719ccd80SArnd Bergmann ibecoming_bytes = atomic_long_read(&invalid_becoming_bytes);
295719ccd80SArnd Bergmann imod_bytes = atomic_long_read(&invalid_mod_bytes);
296df3e764dSLuis Chamberlain
297df3e764dSLuis Chamberlain total_virtual_lost = ikread_bytes + idecompress_bytes + ibecoming_bytes + imod_bytes;
298df3e764dSLuis Chamberlain
299df3e764dSLuis Chamberlain size = MAX_PREAMBLE + min((unsigned int)(floads + fbecoming),
300df3e764dSLuis Chamberlain (unsigned int)MAX_FAILED_MOD_PRINT) * MAX_BYTES_PER_MOD;
301df3e764dSLuis Chamberlain buf = kzalloc(size, GFP_KERNEL);
302df3e764dSLuis Chamberlain if (buf == NULL)
303df3e764dSLuis Chamberlain return -ENOMEM;
304df3e764dSLuis Chamberlain
305df3e764dSLuis Chamberlain /* The beginning of our debug preamble */
3069f5cab17STom Rix len = scnprintf(buf, size, "%25s\t%u\n", "Mods ever loaded", live_mod_count);
307df3e764dSLuis Chamberlain
308df3e764dSLuis Chamberlain len += scnprintf(buf + len, size - len, "%25s\t%u\n", "Mods failed on kread", fkreads);
309df3e764dSLuis Chamberlain
310df3e764dSLuis Chamberlain len += scnprintf(buf + len, size - len, "%25s\t%u\n", "Mods failed on decompress",
311df3e764dSLuis Chamberlain fdecompress);
312df3e764dSLuis Chamberlain len += scnprintf(buf + len, size - len, "%25s\t%u\n", "Mods failed on becoming", fbecoming);
313df3e764dSLuis Chamberlain
314df3e764dSLuis Chamberlain len += scnprintf(buf + len, size - len, "%25s\t%u\n", "Mods failed on load", floads);
315df3e764dSLuis Chamberlain
316719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Total module size", total_size);
317719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Total mod text size", text_size);
318df3e764dSLuis Chamberlain
319719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Failed kread bytes", ikread_bytes);
320df3e764dSLuis Chamberlain
321719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Failed decompress bytes",
322df3e764dSLuis Chamberlain idecompress_bytes);
323df3e764dSLuis Chamberlain
324719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Failed becoming bytes", ibecoming_bytes);
325df3e764dSLuis Chamberlain
326719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Failed kmod bytes", imod_bytes);
327df3e764dSLuis Chamberlain
328719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Virtual mem wasted bytes", total_virtual_lost);
329df3e764dSLuis Chamberlain
330df3e764dSLuis Chamberlain if (live_mod_count && total_size) {
331719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Average mod size",
332df3e764dSLuis Chamberlain DIV_ROUND_UP(total_size, live_mod_count));
333df3e764dSLuis Chamberlain }
334df3e764dSLuis Chamberlain
335df3e764dSLuis Chamberlain if (live_mod_count && text_size) {
336719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Average mod text size",
337df3e764dSLuis Chamberlain DIV_ROUND_UP(text_size, live_mod_count));
338df3e764dSLuis Chamberlain }
339df3e764dSLuis Chamberlain
340df3e764dSLuis Chamberlain /*
341df3e764dSLuis Chamberlain * We use WARN_ON_ONCE() for the counters to ensure we always have parity
342df3e764dSLuis Chamberlain * for keeping tabs on a type of failure with one type of byte counter.
343df3e764dSLuis Chamberlain * The counters for imod_bytes does not increase for fkreads failures
344df3e764dSLuis Chamberlain * for example, and so on.
345df3e764dSLuis Chamberlain */
346df3e764dSLuis Chamberlain
347df3e764dSLuis Chamberlain WARN_ON_ONCE(ikread_bytes && !fkreads);
348df3e764dSLuis Chamberlain if (fkreads && ikread_bytes) {
349719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Avg fail kread bytes",
350df3e764dSLuis Chamberlain DIV_ROUND_UP(ikread_bytes, fkreads));
351df3e764dSLuis Chamberlain }
352df3e764dSLuis Chamberlain
353df3e764dSLuis Chamberlain WARN_ON_ONCE(ibecoming_bytes && !fbecoming);
354df3e764dSLuis Chamberlain if (fbecoming && ibecoming_bytes) {
355719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Avg fail becoming bytes",
356df3e764dSLuis Chamberlain DIV_ROUND_UP(ibecoming_bytes, fbecoming));
357df3e764dSLuis Chamberlain }
358df3e764dSLuis Chamberlain
359df3e764dSLuis Chamberlain WARN_ON_ONCE(idecompress_bytes && !fdecompress);
360df3e764dSLuis Chamberlain if (fdecompress && idecompress_bytes) {
361719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Avg fail decomp bytes",
362df3e764dSLuis Chamberlain DIV_ROUND_UP(idecompress_bytes, fdecompress));
363df3e764dSLuis Chamberlain }
364df3e764dSLuis Chamberlain
365df3e764dSLuis Chamberlain WARN_ON_ONCE(imod_bytes && !floads);
366df3e764dSLuis Chamberlain if (floads && imod_bytes) {
367719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%lu\n", "Average fail load bytes",
368df3e764dSLuis Chamberlain DIV_ROUND_UP(imod_bytes, floads));
369df3e764dSLuis Chamberlain }
370df3e764dSLuis Chamberlain
371df3e764dSLuis Chamberlain /* End of our debug preamble header. */
372df3e764dSLuis Chamberlain
373df3e764dSLuis Chamberlain /* Catch when we've gone beyond our expected preamble */
374df3e764dSLuis Chamberlain WARN_ON_ONCE(len >= MAX_PREAMBLE);
375df3e764dSLuis Chamberlain
376df3e764dSLuis Chamberlain if (list_empty(&dup_failed_modules))
377df3e764dSLuis Chamberlain goto out;
378df3e764dSLuis Chamberlain
379df3e764dSLuis Chamberlain len += scnprintf(buf + len, size - len, "Duplicate failed modules:\n");
380df3e764dSLuis Chamberlain len += scnprintf(buf + len, size - len, "%25s\t%15s\t%25s\n",
381df3e764dSLuis Chamberlain "Module-name", "How-many-times", "Reason");
382df3e764dSLuis Chamberlain mutex_lock(&module_mutex);
383df3e764dSLuis Chamberlain
384df3e764dSLuis Chamberlain
385df3e764dSLuis Chamberlain list_for_each_entry_rcu(mod_fail, &dup_failed_modules, list) {
386df3e764dSLuis Chamberlain if (WARN_ON_ONCE(++count_failed >= MAX_FAILED_MOD_PRINT))
387df3e764dSLuis Chamberlain goto out_unlock;
388719ccd80SArnd Bergmann len += scnprintf(buf + len, size - len, "%25s\t%15lu\t%25s\n", mod_fail->name,
389719ccd80SArnd Bergmann atomic_long_read(&mod_fail->count), mod_fail_to_str(mod_fail));
390df3e764dSLuis Chamberlain }
391df3e764dSLuis Chamberlain out_unlock:
392df3e764dSLuis Chamberlain mutex_unlock(&module_mutex);
393df3e764dSLuis Chamberlain out:
394*d36f6efbSHarshit Mogalapalli ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
395df3e764dSLuis Chamberlain kfree(buf);
396*d36f6efbSHarshit Mogalapalli return ret;
397df3e764dSLuis Chamberlain }
398df3e764dSLuis Chamberlain #undef MAX_PREAMBLE
399df3e764dSLuis Chamberlain #undef MAX_FAILED_MOD_PRINT
400df3e764dSLuis Chamberlain #undef MAX_BYTES_PER_MOD
401df3e764dSLuis Chamberlain
402df3e764dSLuis Chamberlain static const struct file_operations fops_mod_stats = {
403df3e764dSLuis Chamberlain .read = read_file_mod_stats,
404df3e764dSLuis Chamberlain .open = simple_open,
405df3e764dSLuis Chamberlain .owner = THIS_MODULE,
406df3e764dSLuis Chamberlain .llseek = default_llseek,
407df3e764dSLuis Chamberlain };
408df3e764dSLuis Chamberlain
409df3e764dSLuis Chamberlain #define mod_debug_add_ulong(name) debugfs_create_ulong(#name, 0400, mod_debugfs_root, (unsigned long *) &name.counter)
410df3e764dSLuis Chamberlain #define mod_debug_add_atomic(name) debugfs_create_atomic_t(#name, 0400, mod_debugfs_root, &name)
module_stats_init(void)411df3e764dSLuis Chamberlain static int __init module_stats_init(void)
412df3e764dSLuis Chamberlain {
413df3e764dSLuis Chamberlain mod_debug_add_ulong(total_mod_size);
414df3e764dSLuis Chamberlain mod_debug_add_ulong(total_text_size);
415df3e764dSLuis Chamberlain mod_debug_add_ulong(invalid_kread_bytes);
416df3e764dSLuis Chamberlain mod_debug_add_ulong(invalid_decompress_bytes);
417df3e764dSLuis Chamberlain mod_debug_add_ulong(invalid_becoming_bytes);
418df3e764dSLuis Chamberlain mod_debug_add_ulong(invalid_mod_bytes);
419df3e764dSLuis Chamberlain
420df3e764dSLuis Chamberlain mod_debug_add_atomic(modcount);
421df3e764dSLuis Chamberlain mod_debug_add_atomic(failed_kreads);
422df3e764dSLuis Chamberlain mod_debug_add_atomic(failed_decompress);
423df3e764dSLuis Chamberlain mod_debug_add_atomic(failed_becoming);
424df3e764dSLuis Chamberlain mod_debug_add_atomic(failed_load_modules);
425df3e764dSLuis Chamberlain
426df3e764dSLuis Chamberlain debugfs_create_file("stats", 0400, mod_debugfs_root, mod_debugfs_root, &fops_mod_stats);
427df3e764dSLuis Chamberlain
428df3e764dSLuis Chamberlain return 0;
429df3e764dSLuis Chamberlain }
430df3e764dSLuis Chamberlain #undef mod_debug_add_ulong
431df3e764dSLuis Chamberlain #undef mod_debug_add_atomic
432df3e764dSLuis Chamberlain module_init(module_stats_init);
433