| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: vmstat.c,v 1.244 2021/04/01 05:33:50 simonb Exp $ */ | | 1 | /* $NetBSD: vmstat.c,v 1.245 2021/04/01 06:23:14 simonb Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2000, 2001, 2007, 2019, 2020 | | 4 | * Copyright (c) 1998, 2000, 2001, 2007, 2019, 2020 |
5 | * The NetBSD Foundation, Inc. | | 5 | * The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation by: | | 8 | * This code is derived from software contributed to The NetBSD Foundation by: |
9 | * - Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 9 | * - Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
10 | * NASA Ames Research Center. | | 10 | * NASA Ames Research Center. |
11 | * - Simon Burge and Luke Mewburn of Wasabi Systems, Inc. | | 11 | * - Simon Burge and Luke Mewburn of Wasabi Systems, Inc. |
12 | * | | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | | 13 | * Redistribution and use in source and binary forms, with or without |
14 | * modification, are permitted provided that the following conditions | | 14 | * modification, are permitted provided that the following conditions |
| @@ -61,27 +61,27 @@ | | | @@ -61,27 +61,27 @@ |
61 | * SUCH DAMAGE. | | 61 | * SUCH DAMAGE. |
62 | */ | | 62 | */ |
63 | | | 63 | |
64 | #include <sys/cdefs.h> | | 64 | #include <sys/cdefs.h> |
65 | #ifndef lint | | 65 | #ifndef lint |
66 | __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\ | | 66 | __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\ |
67 | The Regents of the University of California. All rights reserved."); | | 67 | The Regents of the University of California. All rights reserved."); |
68 | #endif /* not lint */ | | 68 | #endif /* not lint */ |
69 | | | 69 | |
70 | #ifndef lint | | 70 | #ifndef lint |
71 | #if 0 | | 71 | #if 0 |
72 | static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95"; | | 72 | static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95"; |
73 | #else | | 73 | #else |
74 | __RCSID("$NetBSD: vmstat.c,v 1.244 2021/04/01 05:33:50 simonb Exp $"); | | 74 | __RCSID("$NetBSD: vmstat.c,v 1.245 2021/04/01 06:23:14 simonb Exp $"); |
75 | #endif | | 75 | #endif |
76 | #endif /* not lint */ | | 76 | #endif /* not lint */ |
77 | | | 77 | |
78 | #define __POOL_EXPOSE | | 78 | #define __POOL_EXPOSE |
79 | #define __NAMECACHE_PRIVATE | | 79 | #define __NAMECACHE_PRIVATE |
80 | | | 80 | |
81 | #include <sys/param.h> | | 81 | #include <sys/param.h> |
82 | #include <sys/types.h> | | 82 | #include <sys/types.h> |
83 | #include <sys/mount.h> | | 83 | #include <sys/mount.h> |
84 | #include <sys/uio.h> | | 84 | #include <sys/uio.h> |
85 | | | 85 | |
86 | #include <sys/buf.h> | | 86 | #include <sys/buf.h> |
87 | #include <sys/evcnt.h> | | 87 | #include <sys/evcnt.h> |
| @@ -103,26 +103,27 @@ __RCSID("$NetBSD: vmstat.c,v 1.244 2021/ | | | @@ -103,26 +103,27 @@ __RCSID("$NetBSD: vmstat.c,v 1.244 2021/ |
103 | #include <uvm/uvm_extern.h> | | 103 | #include <uvm/uvm_extern.h> |
104 | #include <uvm/uvm_stat.h> | | 104 | #include <uvm/uvm_stat.h> |
105 | | | 105 | |
106 | #include <net/if.h> | | 106 | #include <net/if.h> |
107 | #include <netinet/in.h> | | 107 | #include <netinet/in.h> |
108 | #include <netinet/in_var.h> | | 108 | #include <netinet/in_var.h> |
109 | | | 109 | |
110 | #include <ufs/ufs/inode.h> | | 110 | #include <ufs/ufs/inode.h> |
111 | | | 111 | |
112 | #include <nfs/rpcv2.h> | | 112 | #include <nfs/rpcv2.h> |
113 | #include <nfs/nfsproto.h> | | 113 | #include <nfs/nfsproto.h> |
114 | #include <nfs/nfsnode.h> | | 114 | #include <nfs/nfsnode.h> |
115 | | | 115 | |
| | | 116 | #include <assert.h> |
116 | #include <ctype.h> | | 117 | #include <ctype.h> |
117 | #include <err.h> | | 118 | #include <err.h> |
118 | #include <errno.h> | | 119 | #include <errno.h> |
119 | #include <fcntl.h> | | 120 | #include <fcntl.h> |
120 | #include <kvm.h> | | 121 | #include <kvm.h> |
121 | #include <limits.h> | | 122 | #include <limits.h> |
122 | #include <nlist.h> | | 123 | #include <nlist.h> |
123 | #undef n_hash | | 124 | #undef n_hash |
124 | #include <paths.h> | | 125 | #include <paths.h> |
125 | #include <signal.h> | | 126 | #include <signal.h> |
126 | #include <stdio.h> | | 127 | #include <stdio.h> |
127 | #include <stddef.h> | | 128 | #include <stddef.h> |
128 | #include <stdlib.h> | | 129 | #include <stdlib.h> |
| @@ -197,51 +198,43 @@ struct nlist intrnl[] = | | | @@ -197,51 +198,43 @@ struct nlist intrnl[] = |
197 | { .n_name = "_intrcnt" }, | | 198 | { .n_name = "_intrcnt" }, |
198 | #define X_EINTRCNT 3 | | 199 | #define X_EINTRCNT 3 |
199 | { .n_name = "_eintrcnt" }, | | 200 | { .n_name = "_eintrcnt" }, |
200 | #define X_INTRNL_SIZE 4 | | 201 | #define X_INTRNL_SIZE 4 |
201 | { .n_name = NULL }, | | 202 | { .n_name = NULL }, |
202 | }; | | 203 | }; |
203 | | | 204 | |
204 | | | 205 | |
205 | /* | | 206 | /* |
206 | * Namelist for hash statistics | | 207 | * Namelist for hash statistics |
207 | */ | | 208 | */ |
208 | struct nlist hashnl[] = | | 209 | struct nlist hashnl[] = |
209 | { | | 210 | { |
210 | #define X_NFSNODE 0 | | 211 | #define X_BUFHASH 0 |
211 | { .n_name = "_nfsnodehash" }, | | | |
212 | #define X_NFSNODETBL 1 | | | |
213 | { .n_name = "_nfsnodehashtbl" }, | | | |
214 | #define X_IHASH 2 | | | |
215 | { .n_name = "_ihash" }, | | | |
216 | #define X_IHASHTBL 3 | | | |
217 | { .n_name = "_ihashtbl" }, | | | |
218 | #define X_BUFHASH 4 | | | |
219 | { .n_name = "_bufhash" }, | | 212 | { .n_name = "_bufhash" }, |
220 | #define X_BUFHASHTBL 5 | | 213 | #define X_BUFHASHTBL 1 |
221 | { .n_name = "_bufhashtbl" }, | | 214 | { .n_name = "_bufhashtbl" }, |
222 | #define X_UIHASH 6 | | 215 | #define X_UIHASH 2 |
223 | { .n_name = "_uihash" }, | | 216 | { .n_name = "_uihash" }, |
224 | #define X_UIHASHTBL 7 | | 217 | #define X_UIHASHTBL 3 |
225 | { .n_name = "_uihashtbl" }, | | 218 | { .n_name = "_uihashtbl" }, |
226 | #define X_IFADDRHASH 8 | | 219 | #define X_IFADDRHASH 4 |
227 | { .n_name = "_in_ifaddrhash" }, | | 220 | { .n_name = "_in_ifaddrhash" }, |
228 | #define X_IFADDRHASHTBL 9 | | 221 | #define X_IFADDRHASHTBL 5 |
229 | { .n_name = "_in_ifaddrhashtbl" }, | | 222 | { .n_name = "_in_ifaddrhashtbl" }, |
230 | #define X_VCACHEHASH 10 | | 223 | #define X_VCACHEHASH 6 |
231 | { .n_name = "_vcache_hashmask" }, | | 224 | { .n_name = "_vcache_hashmask" }, |
232 | #define X_VCACHETBL 11 | | 225 | #define X_VCACHETBL 7 |
233 | { .n_name = "_vcache_hashtab" }, | | 226 | { .n_name = "_vcache_hashtab" }, |
234 | #define X_HASHNL_SIZE 12 /* must be last */ | | 227 | #define X_HASHNL_SIZE 8 /* must be last */ |
235 | { .n_name = NULL }, | | 228 | { .n_name = NULL }, |
236 | }; | | 229 | }; |
237 | | | 230 | |
238 | /* | | 231 | /* |
239 | * Namelist for kernel histories | | 232 | * Namelist for kernel histories |
240 | */ | | 233 | */ |
241 | struct nlist histnl[] = | | 234 | struct nlist histnl[] = |
242 | { | | 235 | { |
243 | { .n_name = "_kern_histories" }, | | 236 | { .n_name = "_kern_histories" }, |
244 | #define X_KERN_HISTORIES 0 | | 237 | #define X_KERN_HISTORIES 0 |
245 | { .n_name = NULL }, | | 238 | { .n_name = NULL }, |
246 | }; | | 239 | }; |
247 | | | 240 | |
| @@ -290,26 +283,27 @@ kvm_t *kd; | | | @@ -290,26 +283,27 @@ kvm_t *kd; |
290 | (width) - (fixed) - (ovflw) > 0 ? \ | | 283 | (width) - (fixed) - (ovflw) > 0 ? \ |
291 | (width) - (fixed) - (ovflw) : 0, \ | | 284 | (width) - (fixed) - (ovflw) : 0, \ |
292 | (val)) - (width); \ | | 285 | (val)) - (width); \ |
293 | if ((ovflw) < 0) \ | | 286 | if ((ovflw) < 0) \ |
294 | (ovflw) = 0; \ | | 287 | (ovflw) = 0; \ |
295 | } while (/* CONSTCOND */0) | | 288 | } while (/* CONSTCOND */0) |
296 | | | 289 | |
297 | void cpustats(int *); | | 290 | void cpustats(int *); |
298 | void cpucounters(struct cpu_counter *); | | 291 | void cpucounters(struct cpu_counter *); |
299 | void deref_kptr(const void *, void *, size_t, const char *); | | 292 | void deref_kptr(const void *, void *, size_t, const char *); |
300 | void drvstats(int *); | | 293 | void drvstats(int *); |
301 | void doevcnt(int verbose, int type); | | 294 | void doevcnt(int verbose, int type); |
302 | void dohashstat(int, int, const char *); | | 295 | void dohashstat(int, int, const char *); |
| | | 296 | void dohashstat_sysctl(int, int, const char *); |
303 | void dointr(int verbose); | | 297 | void dointr(int verbose); |
304 | void dopool(int, int); | | 298 | void dopool(int, int); |
305 | void dopoolcache(int); | | 299 | void dopoolcache(int); |
306 | void dosum(void); | | 300 | void dosum(void); |
307 | void dovmstat(struct timespec *, int); | | 301 | void dovmstat(struct timespec *, int); |
308 | void print_total_hdr(void); | | 302 | void print_total_hdr(void); |
309 | void dovmtotal(struct timespec *, int); | | 303 | void dovmtotal(struct timespec *, int); |
310 | void kread(struct nlist *, int, void *, size_t); | | 304 | void kread(struct nlist *, int, void *, size_t); |
311 | int kreadc(struct nlist *, int, void *, size_t); | | 305 | int kreadc(struct nlist *, int, void *, size_t); |
312 | void needhdr(int); | | 306 | void needhdr(int); |
313 | void getnlist(int); | | 307 | void getnlist(int); |
314 | long getuptime(void); | | 308 | long getuptime(void); |
315 | void printhdr(void); | | 309 | void printhdr(void); |
| @@ -1915,26 +1909,29 @@ struct kernel_hash { | | | @@ -1915,26 +1909,29 @@ struct kernel_hash { |
1915 | | | 1909 | |
1916 | void | | 1910 | void |
1917 | dohashstat(int verbose, int todo, const char *hashname) | | 1911 | dohashstat(int verbose, int todo, const char *hashname) |
1918 | { | | 1912 | { |
1919 | LIST_HEAD(, generic) *hashtbl_list; | | 1913 | LIST_HEAD(, generic) *hashtbl_list; |
1920 | SLIST_HEAD(, generic) *hashtbl_slist; | | 1914 | SLIST_HEAD(, generic) *hashtbl_slist; |
1921 | TAILQ_HEAD(, generic) *hashtbl_tailq; | | 1915 | TAILQ_HEAD(, generic) *hashtbl_tailq; |
1922 | struct kernel_hash *curhash; | | 1916 | struct kernel_hash *curhash; |
1923 | void *hashaddr, *hashbuf, *nhashbuf, *nextaddr; | | 1917 | void *hashaddr, *hashbuf, *nhashbuf, *nextaddr; |
1924 | size_t elemsize, hashbufsize, thissize; | | 1918 | size_t elemsize, hashbufsize, thissize; |
1925 | u_long hashsize, i; | | 1919 | u_long hashsize, i; |
1926 | int used, items, chain, maxchain; | | 1920 | int used, items, chain, maxchain; |
1927 | | | 1921 | |
| | | 1922 | if (memf == NULL) |
| | | 1923 | return dohashstat_sysctl(verbose, todo, hashname); |
| | | 1924 | |
1928 | hashbuf = NULL; | | 1925 | hashbuf = NULL; |
1929 | hashbufsize = 0; | | 1926 | hashbufsize = 0; |
1930 | | | 1927 | |
1931 | if (todo & HASHLIST) { | | 1928 | if (todo & HASHLIST) { |
1932 | (void)printf("Supported hashes:\n"); | | 1929 | (void)printf("Supported hashes:\n"); |
1933 | for (curhash = khashes; curhash->description; curhash++) { | | 1930 | for (curhash = khashes; curhash->description; curhash++) { |
1934 | if (hashnl[curhash->hashsize].n_value == 0 || | | 1931 | if (hashnl[curhash->hashsize].n_value == 0 || |
1935 | hashnl[curhash->hashtbl].n_value == 0) | | 1932 | hashnl[curhash->hashtbl].n_value == 0) |
1936 | continue; | | 1933 | continue; |
1937 | (void)printf("\t%-16s%s\n", | | 1934 | (void)printf("\t%-16s%s\n", |
1938 | hashnl[curhash->hashsize].n_name + 1, | | 1935 | hashnl[curhash->hashsize].n_name + 1, |
1939 | curhash->description); | | 1936 | curhash->description); |
1940 | } | | 1937 | } |
| @@ -2047,26 +2044,95 @@ dohashstat(int verbose, int todo, const | | | @@ -2047,26 +2044,95 @@ dohashstat(int verbose, int todo, const |
2047 | items += chain; | | 2044 | items += chain; |
2048 | if (verbose && chain > 1) | | 2045 | if (verbose && chain > 1) |
2049 | (void)printf("\tchain = %d\n", chain); | | 2046 | (void)printf("\tchain = %d\n", chain); |
2050 | if (chain > maxchain) | | 2047 | if (chain > maxchain) |
2051 | maxchain = chain; | | 2048 | maxchain = chain; |
2052 | } | | 2049 | } |
2053 | (void)printf("%-16s %8ld %8d %8.2f %8d %8.2f %8d\n", | | 2050 | (void)printf("%-16s %8ld %8d %8.2f %8d %8.2f %8d\n", |
2054 | hashnl[curhash->hashsize].n_name + 1, | | 2051 | hashnl[curhash->hashsize].n_name + 1, |
2055 | hashsize, used, used * 100.0 / hashsize, | | 2052 | hashsize, used, used * 100.0 / hashsize, |
2056 | items, used ? (double)items / used : 0.0, maxchain); | | 2053 | items, used ? (double)items / used : 0.0, maxchain); |
2057 | } | | 2054 | } |
2058 | } | | 2055 | } |
2059 | | | 2056 | |
| | | 2057 | void |
| | | 2058 | dohashstat_sysctl(int verbose, int todo, const char *hashname) |
| | | 2059 | { |
| | | 2060 | struct hashstat_sysctl hash, *data, *hs; |
| | | 2061 | int mib[3]; |
| | | 2062 | int error; |
| | | 2063 | size_t i, len, miblen; |
| | | 2064 | |
| | | 2065 | |
| | | 2066 | miblen = __arraycount(mib); |
| | | 2067 | error = sysctlnametomib("kern.hashstat", mib, &miblen); |
| | | 2068 | if (error) |
| | | 2069 | err(EXIT_FAILURE, "nametomib kern.hashstat failed"); |
| | | 2070 | assert(miblen < 3); |
| | | 2071 | |
| | | 2072 | if (todo & HASHLIST) { |
| | | 2073 | mib[miblen] = CTL_DESCRIBE; |
| | | 2074 | miblen++; |
| | | 2075 | }; |
| | | 2076 | |
| | | 2077 | if (hashname) { |
| | | 2078 | mib[miblen] = CTL_QUERY; |
| | | 2079 | miblen++; |
| | | 2080 | memset(&hash, 0, sizeof(hash)); |
| | | 2081 | strlcpy(hash.hash_name, hashname, sizeof(hash.hash_name)); |
| | | 2082 | len = sizeof(hash); |
| | | 2083 | error = sysctl(mib, miblen, &hash, &len, &hash, len); |
| | | 2084 | if (error == ENOENT) { |
| | | 2085 | err(1, "hash '%s' not found", hashname); |
| | | 2086 | return; |
| | | 2087 | } else if (error) { |
| | | 2088 | err(1, "sysctl kern.hashstat query failed"); |
| | | 2089 | return; |
| | | 2090 | } |
| | | 2091 | |
| | | 2092 | data = &hash; |
| | | 2093 | len = 1; |
| | | 2094 | } else { |
| | | 2095 | data = asysctl(mib, miblen, &len); |
| | | 2096 | if (data == NULL) |
| | | 2097 | err(1, "failed to read kern.hashstat"); |
| | | 2098 | len /= sizeof(*data); |
| | | 2099 | } |
| | | 2100 | |
| | | 2101 | if (todo & HASHLIST) { |
| | | 2102 | printf("Supported hashes:\n"); |
| | | 2103 | for (i = 0, hs = data; i < len; i++, hs++) { |
| | | 2104 | printf("\t%-16s%s\n", hs->hash_name, hs->hash_desc); |
| | | 2105 | } |
| | | 2106 | } else { |
| | | 2107 | printf("%-16s %8s %8s %8s %8s %8s %8s\n" |
| | | 2108 | "%-16s %8s %8s %8s %8s %8s %8s\n", |
| | | 2109 | "", "total", "used", "util", "num", "average", "maximum", |
| | | 2110 | "hash table", "buckets", "buckets", "%", "items", "chain", |
| | | 2111 | "chain"); |
| | | 2112 | for (i = 0, hs = data; i < len; i++, hs++) { |
| | | 2113 | printf("%-16s %8"PRId64" %8"PRId64" %8.2f %8"PRId64 |
| | | 2114 | " %8.2f %8"PRId64"\n", |
| | | 2115 | hs->hash_name, hs->hash_size, hs->hash_used, |
| | | 2116 | hs->hash_used * 100.0 / hs->hash_size, hs->hash_items, |
| | | 2117 | hs->hash_used ? (double)hs->hash_items / hs->hash_used : 0.0, |
| | | 2118 | hs->hash_maxchain); |
| | | 2119 | } |
| | | 2120 | } |
| | | 2121 | |
| | | 2122 | if (!hashname && (data != NULL)) |
| | | 2123 | free(data); |
| | | 2124 | } |
| | | 2125 | |
2060 | /* | | 2126 | /* |
2061 | * kreadc like kread but returns 1 if successful, 0 otherwise | | 2127 | * kreadc like kread but returns 1 if successful, 0 otherwise |
2062 | */ | | 2128 | */ |
2063 | int | | 2129 | int |
2064 | kreadc(struct nlist *nl, int nlx, void *addr, size_t size) | | 2130 | kreadc(struct nlist *nl, int nlx, void *addr, size_t size) |
2065 | { | | 2131 | { |
2066 | const char *sym; | | 2132 | const char *sym; |
2067 | | | 2133 | |
2068 | sym = nl[nlx].n_name; | | 2134 | sym = nl[nlx].n_name; |
2069 | if (*sym == '_') | | 2135 | if (*sym == '_') |
2070 | ++sym; | | 2136 | ++sym; |
2071 | if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) | | 2137 | if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) |
2072 | return 0; | | 2138 | return 0; |
| @@ -2244,27 +2310,27 @@ hist_traverse_sysctl(int todo, const cha | | | @@ -2244,27 +2310,27 @@ hist_traverse_sysctl(int todo, const cha |
2244 | int mib[4]; | | 2310 | int mib[4]; |
2245 | unsigned int i; | | 2311 | unsigned int i; |
2246 | size_t len, miblen; | | 2312 | size_t len, miblen; |
2247 | struct sysctlnode query, histnode[32]; | | 2313 | struct sysctlnode query, histnode[32]; |
2248 | | | 2314 | |
2249 | /* retrieve names of available histories */ | | 2315 | /* retrieve names of available histories */ |
2250 | miblen = __arraycount(mib); | | 2316 | miblen = __arraycount(mib); |
2251 | error = sysctlnametomib("kern.hist", mib, &miblen); | | 2317 | error = sysctlnametomib("kern.hist", mib, &miblen); |
2252 | if (error != 0) { | | 2318 | if (error != 0) { |
2253 | if (errno == ENOENT) { | | 2319 | if (errno == ENOENT) { |
2254 | warnx("kernel history is not compiled into the kernel."); | | 2320 | warnx("kernel history is not compiled into the kernel."); |
2255 | return; | | 2321 | return; |
2256 | } else | | 2322 | } else |
2257 | err(EXIT_FAILURE, "nametomib failed"); | | 2323 | err(EXIT_FAILURE, "nametomib kern.hist failed"); |
2258 | } | | 2324 | } |
2259 | | | 2325 | |
2260 | /* get the list of nodenames below kern.hist */ | | 2326 | /* get the list of nodenames below kern.hist */ |
2261 | mib[2] = CTL_QUERY; | | 2327 | mib[2] = CTL_QUERY; |
2262 | memset(&query, 0, sizeof(query)); | | 2328 | memset(&query, 0, sizeof(query)); |
2263 | query.sysctl_flags = SYSCTL_VERSION; | | 2329 | query.sysctl_flags = SYSCTL_VERSION; |
2264 | len = sizeof(histnode); | | 2330 | len = sizeof(histnode); |
2265 | error = sysctl(mib, 3, &histnode[0], &len, &query, sizeof(query)); | | 2331 | error = sysctl(mib, 3, &histnode[0], &len, &query, sizeof(query)); |
2266 | if (error != 0) { | | 2332 | if (error != 0) { |
2267 | err(1, "query failed"); | | 2333 | err(1, "query failed"); |
2268 | return; | | 2334 | return; |
2269 | } | | 2335 | } |
2270 | if (len == 0) { | | 2336 | if (len == 0) { |