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];

Reply via email to