Debugging OOM is hard. UVM uses per-CPU counters and sadly counters_read(9) needs to allocate memory. This is not acceptable in ddb(4). As a result I cannot see the content of UVM counters in OOM situations.
Diff below introduces a *_static() variant of counters_read(9) that takes a secondary buffer to avoid calling malloc(9). Is it fine? Do you have a better idea? Should we make it the default or using the stack might be a problem? Thanks, Martin Index: kern/subr_percpu.c =================================================================== RCS file: /cvs/src/sys/kern/subr_percpu.c,v retrieving revision 1.10 diff -u -p -r1.10 subr_percpu.c --- kern/subr_percpu.c 3 Oct 2022 14:10:53 -0000 1.10 +++ kern/subr_percpu.c 6 Sep 2023 11:54:31 -0000 @@ -161,15 +161,25 @@ counters_free(struct cpumem *cm, unsigne void counters_read(struct cpumem *cm, uint64_t *output, unsigned int n) { - struct cpumem_iter cmi; - uint64_t *gen, *counters, *temp; - uint64_t enter, leave; + uint64_t *temp; unsigned int i; for (i = 0; i < n; i++) output[i] = 0; temp = mallocarray(n, sizeof(uint64_t), M_TEMP, M_WAITOK); + counters_read_static(cm, output, n, temp); + free(temp, M_TEMP, n * sizeof(uint64_t)); +} + +void +counters_read_static(struct cpumem *cm, uint64_t *output, unsigned int n, + uint64_t *temp) +{ + struct cpumem_iter cmi; + uint64_t *gen, *counters; + uint64_t enter, leave; + unsigned int i; gen = cpumem_first(&cmi, cm); do { @@ -201,8 +211,6 @@ counters_read(struct cpumem *cm, uint64_ gen = cpumem_next(&cmi, cm); } while (gen != NULL); - - free(temp, M_TEMP, n * sizeof(uint64_t)); } void Index: sys/percpu.h =================================================================== RCS file: /cvs/src/sys/sys/percpu.h,v retrieving revision 1.8 diff -u -p -r1.8 percpu.h --- sys/percpu.h 28 Aug 2018 15:15:02 -0000 1.8 +++ sys/percpu.h 6 Sep 2023 11:52:55 -0000 @@ -114,6 +114,8 @@ struct cpumem *counters_alloc(unsigned i struct cpumem *counters_alloc_ncpus(struct cpumem *, unsigned int); void counters_free(struct cpumem *, unsigned int); void counters_read(struct cpumem *, uint64_t *, unsigned int); +void counters_read_static(struct cpumem *, uint64_t *, + unsigned int, uint64_t *); void counters_zero(struct cpumem *, unsigned int); static inline uint64_t * Index: uvm/uvm_meter.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_meter.c,v retrieving revision 1.49 diff -u -p -r1.49 uvm_meter.c --- uvm/uvm_meter.c 18 Aug 2023 09:18:52 -0000 1.49 +++ uvm/uvm_meter.c 6 Sep 2023 11:53:02 -0000 @@ -249,11 +249,12 @@ uvm_total(struct vmtotal *totalp) void uvmexp_read(struct uvmexp *uexp) { - uint64_t counters[exp_ncounters]; + uint64_t counters[exp_ncounters], temp[exp_ncounters]; memcpy(uexp, &uvmexp, sizeof(*uexp)); - counters_read(uvmexp_counters, counters, exp_ncounters); + counters_read_static(uvmexp_counters, counters, exp_ncounters, + temp); /* stat counters */ uexp->faults = (int)counters[faults];