Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/vm/vm_meter.c
39564 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1982, 1986, 1989, 1993
5
* The Regents of the University of California. All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* 3. Neither the name of the University nor the names of its contributors
16
* may be used to endorse or promote products derived from this software
17
* without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
#include <sys/param.h>
33
#include <sys/systm.h>
34
#include <sys/kernel.h>
35
#include <sys/lock.h>
36
#include <sys/malloc.h>
37
#include <sys/mutex.h>
38
#include <sys/proc.h>
39
#include <sys/resource.h>
40
#include <sys/rwlock.h>
41
#include <sys/sx.h>
42
#include <sys/vmmeter.h>
43
#include <sys/smp.h>
44
45
#include <vm/vm.h>
46
#include <vm/vm_page.h>
47
#include <vm/vm_extern.h>
48
#include <vm/vm_param.h>
49
#include <vm/vm_phys.h>
50
#include <vm/vm_pagequeue.h>
51
#include <vm/pmap.h>
52
#include <vm/vm_map.h>
53
#include <vm/vm_object.h>
54
#include <sys/sysctl.h>
55
56
struct vmmeter __read_mostly vm_cnt = {
57
.v_swtch = EARLY_COUNTER,
58
.v_trap = EARLY_COUNTER,
59
.v_syscall = EARLY_COUNTER,
60
.v_intr = EARLY_COUNTER,
61
.v_soft = EARLY_COUNTER,
62
.v_vm_faults = EARLY_COUNTER,
63
.v_io_faults = EARLY_COUNTER,
64
.v_cow_faults = EARLY_COUNTER,
65
.v_cow_optim = EARLY_COUNTER,
66
.v_zfod = EARLY_COUNTER,
67
.v_ozfod = EARLY_COUNTER,
68
.v_swapin = EARLY_COUNTER,
69
.v_swapout = EARLY_COUNTER,
70
.v_swappgsin = EARLY_COUNTER,
71
.v_swappgsout = EARLY_COUNTER,
72
.v_vnodein = EARLY_COUNTER,
73
.v_vnodeout = EARLY_COUNTER,
74
.v_vnodepgsin = EARLY_COUNTER,
75
.v_vnodepgsout = EARLY_COUNTER,
76
.v_intrans = EARLY_COUNTER,
77
.v_reactivated = EARLY_COUNTER,
78
.v_pdwakeups = EARLY_COUNTER,
79
.v_pdpages = EARLY_COUNTER,
80
.v_pdshortfalls = EARLY_COUNTER,
81
.v_dfree = EARLY_COUNTER,
82
.v_pfree = EARLY_COUNTER,
83
.v_tfree = EARLY_COUNTER,
84
.v_forks = EARLY_COUNTER,
85
.v_vforks = EARLY_COUNTER,
86
.v_rforks = EARLY_COUNTER,
87
.v_kthreads = EARLY_COUNTER,
88
.v_forkpages = EARLY_COUNTER,
89
.v_vforkpages = EARLY_COUNTER,
90
.v_rforkpages = EARLY_COUNTER,
91
.v_kthreadpages = EARLY_COUNTER,
92
.v_wire_count = EARLY_COUNTER,
93
.v_nofree_count = EARLY_COUNTER,
94
};
95
96
u_long __exclusive_cache_line vm_user_wire_count;
97
98
static void
99
vmcounter_startup(void)
100
{
101
counter_u64_t *cnt = (counter_u64_t *)&vm_cnt;
102
103
COUNTER_ARRAY_ALLOC(cnt, VM_METER_NCOUNTERS, M_WAITOK);
104
}
105
SYSINIT(counter, SI_SUB_KMEM, SI_ORDER_FIRST, vmcounter_startup, NULL);
106
107
SYSCTL_UINT(_vm, VM_V_FREE_MIN, v_free_min,
108
CTLFLAG_RW, &vm_cnt.v_free_min, 0, "Minimum low-free-pages threshold");
109
SYSCTL_UINT(_vm, VM_V_FREE_TARGET, v_free_target,
110
CTLFLAG_RW, &vm_cnt.v_free_target, 0, "Desired free pages");
111
SYSCTL_UINT(_vm, VM_V_FREE_RESERVED, v_free_reserved,
112
CTLFLAG_RW, &vm_cnt.v_free_reserved, 0, "Pages reserved for deadlock");
113
SYSCTL_UINT(_vm, VM_V_INACTIVE_TARGET, v_inactive_target,
114
CTLFLAG_RW, &vm_cnt.v_inactive_target, 0, "Pages desired inactive");
115
SYSCTL_UINT(_vm, VM_V_PAGEOUT_FREE_MIN, v_pageout_free_min,
116
CTLFLAG_RW, &vm_cnt.v_pageout_free_min, 0, "Min pages reserved for kernel");
117
SYSCTL_UINT(_vm, OID_AUTO, v_free_severe,
118
CTLFLAG_RW, &vm_cnt.v_free_severe, 0, "Severe page depletion point");
119
120
static int
121
sysctl_vm_loadavg(SYSCTL_HANDLER_ARGS)
122
{
123
124
#ifdef SCTL_MASK32
125
uint32_t la[4];
126
127
if (req->flags & SCTL_MASK32) {
128
la[0] = averunnable.ldavg[0];
129
la[1] = averunnable.ldavg[1];
130
la[2] = averunnable.ldavg[2];
131
la[3] = averunnable.fscale;
132
return SYSCTL_OUT(req, la, sizeof(la));
133
} else
134
#endif
135
return SYSCTL_OUT(req, &averunnable, sizeof(averunnable));
136
}
137
SYSCTL_PROC(_vm, VM_LOADAVG, loadavg, CTLTYPE_STRUCT | CTLFLAG_RD |
138
CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_loadavg, "S,loadavg",
139
"Machine loadaverage history");
140
141
#if defined(COMPAT_FREEBSD11)
142
struct vmtotal11 {
143
int16_t t_rq;
144
int16_t t_dw;
145
int16_t t_pw;
146
int16_t t_sl;
147
int16_t t_sw;
148
int32_t t_vm;
149
int32_t t_avm;
150
int32_t t_rm;
151
int32_t t_arm;
152
int32_t t_vmshr;
153
int32_t t_avmshr;
154
int32_t t_rmshr;
155
int32_t t_armshr;
156
int32_t t_free;
157
};
158
#endif
159
160
static int
161
vmtotal(SYSCTL_HANDLER_ARGS)
162
{
163
struct vmtotal total;
164
#if defined(COMPAT_FREEBSD11)
165
struct vmtotal11 total11;
166
#endif
167
vm_object_t object;
168
struct proc *p;
169
struct thread *td;
170
171
if (req->oldptr == NULL) {
172
#if defined(COMPAT_FREEBSD11)
173
if (curproc->p_osrel < P_OSREL_VMTOTAL64)
174
return (SYSCTL_OUT(req, NULL, sizeof(total11)));
175
#endif
176
return (SYSCTL_OUT(req, NULL, sizeof(total)));
177
}
178
bzero(&total, sizeof(total));
179
180
/*
181
* Calculate process statistics.
182
*/
183
sx_slock(&allproc_lock);
184
FOREACH_PROC_IN_SYSTEM(p) {
185
if ((p->p_flag & P_SYSTEM) != 0)
186
continue;
187
PROC_LOCK(p);
188
if (p->p_state != PRS_NEW) {
189
FOREACH_THREAD_IN_PROC(p, td) {
190
thread_lock(td);
191
switch (TD_GET_STATE(td)) {
192
case TDS_INHIBITED:
193
if (TD_IS_SLEEPING(td)) {
194
if (td->td_priority <= PZERO)
195
total.t_dw++;
196
else
197
total.t_sl++;
198
}
199
break;
200
case TDS_CAN_RUN:
201
total.t_sw++;
202
break;
203
case TDS_RUNQ:
204
case TDS_RUNNING:
205
total.t_rq++;
206
break;
207
default:
208
break;
209
}
210
thread_unlock(td);
211
}
212
}
213
PROC_UNLOCK(p);
214
}
215
sx_sunlock(&allproc_lock);
216
/*
217
* Calculate object memory usage statistics.
218
*/
219
mtx_lock(&vm_object_list_mtx);
220
TAILQ_FOREACH(object, &vm_object_list, object_list) {
221
/*
222
* Perform unsynchronized reads on the object. In
223
* this case, the lack of synchronization should not
224
* impair the accuracy of the reported statistics.
225
*/
226
if ((object->flags & OBJ_FICTITIOUS) != 0) {
227
/*
228
* Devices, like /dev/mem, will badly skew our totals.
229
*/
230
continue;
231
}
232
if (object->ref_count == 0) {
233
/*
234
* Also skip unreferenced objects, including
235
* vnodes representing mounted file systems.
236
*/
237
continue;
238
}
239
if (object->ref_count == 1 &&
240
(object->flags & (OBJ_ANON | OBJ_SWAP)) == OBJ_SWAP) {
241
/*
242
* Also skip otherwise unreferenced swap
243
* objects backing tmpfs vnodes, and POSIX or
244
* SysV shared memory.
245
*/
246
continue;
247
}
248
total.t_vm += object->size;
249
total.t_rm += object->resident_page_count;
250
if (vm_object_is_active(object)) {
251
total.t_avm += object->size;
252
total.t_arm += object->resident_page_count;
253
}
254
if (object->shadow_count > 1) {
255
/* shared object */
256
total.t_vmshr += object->size;
257
total.t_rmshr += object->resident_page_count;
258
if (vm_object_is_active(object)) {
259
total.t_avmshr += object->size;
260
total.t_armshr += object->resident_page_count;
261
}
262
}
263
}
264
mtx_unlock(&vm_object_list_mtx);
265
total.t_pw = vm_wait_count();
266
total.t_free = vm_free_count();
267
#if defined(COMPAT_FREEBSD11)
268
/* sysctl(8) allocates twice as much memory as reported by sysctl(3) */
269
if (curproc->p_osrel < P_OSREL_VMTOTAL64 && (req->oldlen ==
270
sizeof(total11) || req->oldlen == 2 * sizeof(total11))) {
271
bzero(&total11, sizeof(total11));
272
total11.t_rq = total.t_rq;
273
total11.t_dw = total.t_dw;
274
total11.t_pw = total.t_pw;
275
total11.t_sl = total.t_sl;
276
total11.t_sw = total.t_sw;
277
total11.t_vm = total.t_vm; /* truncate */
278
total11.t_avm = total.t_avm; /* truncate */
279
total11.t_rm = total.t_rm; /* truncate */
280
total11.t_arm = total.t_arm; /* truncate */
281
total11.t_vmshr = total.t_vmshr; /* truncate */
282
total11.t_avmshr = total.t_avmshr; /* truncate */
283
total11.t_rmshr = total.t_rmshr; /* truncate */
284
total11.t_armshr = total.t_armshr; /* truncate */
285
total11.t_free = total.t_free; /* truncate */
286
return (SYSCTL_OUT(req, &total11, sizeof(total11)));
287
}
288
#endif
289
return (SYSCTL_OUT(req, &total, sizeof(total)));
290
}
291
292
SYSCTL_PROC(_vm, VM_TOTAL, vmtotal, CTLTYPE_OPAQUE | CTLFLAG_RD |
293
CTLFLAG_MPSAFE, NULL, 0, vmtotal, "S,vmtotal",
294
"System virtual memory statistics");
295
SYSCTL_NODE(_vm, OID_AUTO, stats, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
296
"VM meter stats");
297
static SYSCTL_NODE(_vm_stats, OID_AUTO, sys, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
298
"VM meter sys stats");
299
static SYSCTL_NODE(_vm_stats, OID_AUTO, vm, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
300
"VM meter vm stats");
301
SYSCTL_NODE(_vm_stats, OID_AUTO, misc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
302
"VM meter misc stats");
303
304
static int
305
sysctl_handle_vmstat(SYSCTL_HANDLER_ARGS)
306
{
307
uint64_t val;
308
#ifdef COMPAT_FREEBSD11
309
uint32_t val32;
310
#endif
311
312
val = counter_u64_fetch(*(counter_u64_t *)arg1);
313
#ifdef COMPAT_FREEBSD11
314
if (req->oldlen == sizeof(val32)) {
315
val32 = val; /* truncate */
316
return (SYSCTL_OUT(req, &val32, sizeof(val32)));
317
}
318
#endif
319
return (SYSCTL_OUT(req, &val, sizeof(val)));
320
}
321
322
#define VM_STATS(parent, var, descr) \
323
SYSCTL_OID(parent, OID_AUTO, var, CTLTYPE_U64 | CTLFLAG_MPSAFE | \
324
CTLFLAG_RD, &vm_cnt.var, 0, sysctl_handle_vmstat, "QU", descr)
325
#define VM_STATS_VM(var, descr) VM_STATS(_vm_stats_vm, var, descr)
326
#define VM_STATS_SYS(var, descr) VM_STATS(_vm_stats_sys, var, descr)
327
328
VM_STATS_SYS(v_swtch, "Context switches");
329
VM_STATS_SYS(v_trap, "Traps");
330
VM_STATS_SYS(v_syscall, "System calls");
331
VM_STATS_SYS(v_intr, "Device interrupts");
332
VM_STATS_SYS(v_soft, "Software interrupts");
333
VM_STATS_VM(v_vm_faults, "Address memory faults");
334
VM_STATS_VM(v_io_faults, "Page faults requiring I/O");
335
VM_STATS_VM(v_cow_faults, "Copy-on-write faults");
336
VM_STATS_VM(v_cow_optim, "Optimized COW faults");
337
VM_STATS_VM(v_zfod, "Pages zero-filled on demand");
338
VM_STATS_VM(v_ozfod, "Optimized zero fill pages");
339
VM_STATS_VM(v_swapin, "Swap pager pageins");
340
VM_STATS_VM(v_swapout, "Swap pager pageouts");
341
VM_STATS_VM(v_swappgsin, "Swap pages swapped in");
342
VM_STATS_VM(v_swappgsout, "Swap pages swapped out");
343
VM_STATS_VM(v_vnodein, "Vnode pager pageins");
344
VM_STATS_VM(v_vnodeout, "Vnode pager pageouts");
345
VM_STATS_VM(v_vnodepgsin, "Vnode pages paged in");
346
VM_STATS_VM(v_vnodepgsout, "Vnode pages paged out");
347
VM_STATS_VM(v_intrans, "In transit page faults");
348
VM_STATS_VM(v_reactivated, "Pages reactivated by pagedaemon");
349
VM_STATS_VM(v_pdwakeups, "Pagedaemon wakeups");
350
VM_STATS_VM(v_pdshortfalls, "Page reclamation shortfalls");
351
VM_STATS_VM(v_dfree, "Pages freed by pagedaemon");
352
VM_STATS_VM(v_pfree, "Pages freed by exiting processes");
353
VM_STATS_VM(v_tfree, "Total pages freed");
354
VM_STATS_VM(v_forks, "Number of fork() calls");
355
VM_STATS_VM(v_vforks, "Number of vfork() calls");
356
VM_STATS_VM(v_rforks, "Number of rfork() calls");
357
VM_STATS_VM(v_kthreads, "Number of fork() calls by kernel");
358
VM_STATS_VM(v_forkpages, "VM pages affected by fork()");
359
VM_STATS_VM(v_vforkpages, "VM pages affected by vfork()");
360
VM_STATS_VM(v_rforkpages, "VM pages affected by rfork()");
361
VM_STATS_VM(v_kthreadpages, "VM pages affected by fork() by kernel");
362
363
static int
364
sysctl_handle_vmstat_proc(SYSCTL_HANDLER_ARGS)
365
{
366
u_int (*fn)(void);
367
uint32_t val;
368
369
fn = arg1;
370
val = fn();
371
return (SYSCTL_OUT(req, &val, sizeof(val)));
372
}
373
374
#define VM_STATS_PROC(var, descr, fn) \
375
SYSCTL_OID(_vm_stats_vm, OID_AUTO, var, CTLTYPE_U32 | CTLFLAG_MPSAFE | \
376
CTLFLAG_RD, fn, 0, sysctl_handle_vmstat_proc, "IU", descr)
377
378
#define VM_STATS_UINT(var, descr) \
379
SYSCTL_UINT(_vm_stats_vm, OID_AUTO, var, CTLFLAG_RD, &vm_cnt.var, 0, descr)
380
#define VM_STATS_ULONG(var, descr) \
381
SYSCTL_ULONG(_vm_stats_vm, OID_AUTO, var, CTLFLAG_RD, &vm_cnt.var, 0, descr)
382
383
VM_STATS_UINT(v_page_size, "Page size in bytes");
384
VM_STATS_UINT(v_page_count, "Total number of pages in system");
385
VM_STATS_UINT(v_free_reserved, "Pages reserved for deadlock");
386
VM_STATS_UINT(v_free_target, "Pages desired free");
387
VM_STATS_UINT(v_free_min, "Minimum low-free-pages threshold");
388
VM_STATS_PROC(v_free_count, "Free pages", vm_free_count);
389
VM_STATS_PROC(v_wire_count, "Wired pages", vm_wire_count);
390
VM_STATS_PROC(v_nofree_count, "Permanently allocated pages", vm_nofree_count);
391
VM_STATS_PROC(v_active_count, "Active pages", vm_active_count);
392
VM_STATS_UINT(v_inactive_target, "Desired inactive pages");
393
VM_STATS_PROC(v_inactive_count, "Inactive pages", vm_inactive_count);
394
VM_STATS_PROC(v_laundry_count, "Pages eligible for laundering",
395
vm_laundry_count);
396
VM_STATS_UINT(v_pageout_free_min, "Min pages reserved for kernel");
397
VM_STATS_UINT(v_interrupt_free_min, "Reserved pages for interrupt code");
398
VM_STATS_UINT(v_free_severe, "Severe page depletion point");
399
400
SYSCTL_ULONG(_vm_stats_vm, OID_AUTO, v_user_wire_count, CTLFLAG_RD,
401
&vm_user_wire_count, 0, "User-wired virtual memory");
402
403
#ifdef COMPAT_FREEBSD11
404
/*
405
* Provide compatibility sysctls for the benefit of old utilities which exit
406
* with an error if they cannot be found.
407
*/
408
SYSCTL_UINT(_vm_stats_vm, OID_AUTO, v_cache_count, CTLFLAG_RD,
409
SYSCTL_NULL_UINT_PTR, 0, "Dummy for compatibility");
410
SYSCTL_UINT(_vm_stats_vm, OID_AUTO, v_tcached, CTLFLAG_RD,
411
SYSCTL_NULL_UINT_PTR, 0, "Dummy for compatibility");
412
#endif
413
414
u_int
415
vm_free_count(void)
416
{
417
u_int v;
418
int i;
419
420
v = 0;
421
for (i = 0; i < vm_ndomains; i++)
422
v += vm_dom[i].vmd_free_count;
423
424
return (v);
425
}
426
427
static u_int
428
vm_pagequeue_count(int pq)
429
{
430
u_int v;
431
int i;
432
433
v = 0;
434
for (i = 0; i < vm_ndomains; i++)
435
v += vm_dom[i].vmd_pagequeues[pq].pq_cnt;
436
437
return (v);
438
}
439
440
u_int
441
vm_active_count(void)
442
{
443
444
return (vm_pagequeue_count(PQ_ACTIVE));
445
}
446
447
u_int
448
vm_inactive_count(void)
449
{
450
451
return (vm_pagequeue_count(PQ_INACTIVE));
452
}
453
454
u_int
455
vm_laundry_count(void)
456
{
457
458
return (vm_pagequeue_count(PQ_LAUNDRY) +
459
vm_pagequeue_count(PQ_UNSWAPPABLE));
460
}
461
462
static int
463
sysctl_vm_pdpages(SYSCTL_HANDLER_ARGS)
464
{
465
struct vm_pagequeue *pq;
466
uint64_t ret;
467
int dom, i;
468
469
ret = counter_u64_fetch(vm_cnt.v_pdpages);
470
for (dom = 0; dom < vm_ndomains; dom++)
471
for (i = 0; i < PQ_COUNT; i++) {
472
pq = &VM_DOMAIN(dom)->vmd_pagequeues[i];
473
ret += pq->pq_pdpages;
474
}
475
return (SYSCTL_OUT(req, &ret, sizeof(ret)));
476
}
477
SYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_pdpages,
478
CTLTYPE_U64 | CTLFLAG_MPSAFE | CTLFLAG_RD, NULL, 0, sysctl_vm_pdpages, "QU",
479
"Pages analyzed by pagedaemon");
480
481
static int
482
sysctl_vm_laundry_pages(SYSCTL_HANDLER_ARGS)
483
{
484
struct vm_domain *vmd;
485
u_int ret;
486
487
vmd = arg1;
488
ret = vmd->vmd_pagequeues[PQ_LAUNDRY].pq_cnt +
489
vmd->vmd_pagequeues[PQ_UNSWAPPABLE].pq_cnt;
490
return (SYSCTL_OUT(req, &ret, sizeof(ret)));
491
}
492
493
static void
494
vm_domain_stats_init(struct vm_domain *vmd, struct sysctl_oid *parent)
495
{
496
struct sysctl_oid *oid;
497
498
vmd->vmd_oid = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(parent), OID_AUTO,
499
vmd->vmd_name, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
500
oid = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(vmd->vmd_oid), OID_AUTO,
501
"stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
502
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
503
"free_count", CTLFLAG_RD, &vmd->vmd_free_count, 0,
504
"Free pages");
505
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
506
"active", CTLFLAG_RD, &vmd->vmd_pagequeues[PQ_ACTIVE].pq_cnt, 0,
507
"Active pages");
508
SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
509
"actpdpgs", CTLFLAG_RD,
510
&vmd->vmd_pagequeues[PQ_ACTIVE].pq_pdpages, 0,
511
"Active pages scanned by the page daemon");
512
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
513
"inactive", CTLFLAG_RD, &vmd->vmd_pagequeues[PQ_INACTIVE].pq_cnt, 0,
514
"Inactive pages");
515
SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
516
"inactpdpgs", CTLFLAG_RD,
517
&vmd->vmd_pagequeues[PQ_INACTIVE].pq_pdpages, 0,
518
"Inactive pages scanned by the page daemon");
519
SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
520
"laundry", CTLFLAG_RD | CTLTYPE_UINT, vmd, 0,
521
sysctl_vm_laundry_pages, "IU",
522
"laundry pages");
523
SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
524
"laundpdpgs", CTLFLAG_RD,
525
&vmd->vmd_pagequeues[PQ_LAUNDRY].pq_pdpages, 0,
526
"Laundry pages scanned by the page daemon");
527
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, "unswappable",
528
CTLFLAG_RD, &vmd->vmd_pagequeues[PQ_UNSWAPPABLE].pq_cnt, 0,
529
"Unswappable pages");
530
SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
531
"unswppdpgs", CTLFLAG_RD,
532
&vmd->vmd_pagequeues[PQ_UNSWAPPABLE].pq_pdpages, 0,
533
"Unswappable pages scanned by the page daemon");
534
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
535
"inactive_target", CTLFLAG_RD, &vmd->vmd_inactive_target, 0,
536
"Target inactive pages");
537
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
538
"free_target", CTLFLAG_RD, &vmd->vmd_free_target, 0,
539
"Target free pages");
540
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
541
"free_reserved", CTLFLAG_RD, &vmd->vmd_free_reserved, 0,
542
"Reserved free pages");
543
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
544
"free_min", CTLFLAG_RD, &vmd->vmd_free_min, 0,
545
"Minimum free pages");
546
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
547
"free_severe", CTLFLAG_RD, &vmd->vmd_free_severe, 0,
548
"Severe free pages");
549
SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO,
550
"inactive_pps", CTLFLAG_RD, &vmd->vmd_inactive_pps, 0,
551
"inactive pages freed/second");
552
553
}
554
555
static void
556
vm_stats_init(void *arg __unused)
557
{
558
struct sysctl_oid *oid;
559
int i;
560
561
oid = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(_vm), OID_AUTO,
562
"domain", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
563
for (i = 0; i < vm_ndomains; i++)
564
vm_domain_stats_init(VM_DOMAIN(i), oid);
565
}
566
567
SYSINIT(vmstats_init, SI_SUB_VM_CONF, SI_ORDER_FIRST, vm_stats_init, NULL);
568
569