1e92324a2SMatthew Dillon /* 2e92324a2SMatthew Dillon * Copyright (c) 1999, Matthew Dillon. All Rights Reserved. 39e749cc9SWarner Losh * Copyright (c) 2001, Thomas Moestl. All Rights Reserved. 4e92324a2SMatthew Dillon * 5e92324a2SMatthew Dillon * Redistribution and use in source and binary forms, with or without 69e749cc9SWarner Losh * modification, are permitted provided that the following conditions 79e749cc9SWarner Losh * are met: 89e749cc9SWarner Losh * 1. Redistributions of source code must retain the above copyright 99e749cc9SWarner Losh * notice, this list of conditions and the following disclaimer. 109e749cc9SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 119e749cc9SWarner Losh * notice, this list of conditions and the following disclaimer in the 129e749cc9SWarner Losh * documentation and/or other materials provided with the distribution. 139e749cc9SWarner Losh * 149e749cc9SWarner Losh * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 159e749cc9SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 169e749cc9SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 179e749cc9SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 189e749cc9SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 199e749cc9SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 209e749cc9SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 219e749cc9SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 229e749cc9SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 239e749cc9SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 249e749cc9SWarner Losh * SUCH DAMAGE. 25e92324a2SMatthew Dillon */ 26e92324a2SMatthew Dillon 27e67f5b9fSMatthew Dillon #include <sys/cdefs.h> 28e67f5b9fSMatthew Dillon __FBSDID("$FreeBSD$"); 29e92324a2SMatthew Dillon 30e92324a2SMatthew Dillon #include <sys/param.h> 31e92324a2SMatthew Dillon #include <sys/time.h> 32e92324a2SMatthew Dillon #include <sys/stat.h> 33e92324a2SMatthew Dillon #include <sys/blist.h> 34ae3a37adSRobert Watson #include <sys/sysctl.h> 35e92324a2SMatthew Dillon 36e04a7c4aSThomas Moestl #include <vm/vm_param.h> 37e04a7c4aSThomas Moestl 38e92324a2SMatthew Dillon #include <err.h> 39e04a7c4aSThomas Moestl #include <errno.h> 40e92324a2SMatthew Dillon #include <fcntl.h> 41e92324a2SMatthew Dillon #include <kvm.h> 42e92324a2SMatthew Dillon #include <nlist.h> 431a37aa56SDavid E. O'Brien #include <paths.h> 44e92324a2SMatthew Dillon #include <stdio.h> 45e92324a2SMatthew Dillon #include <stdlib.h> 46e92324a2SMatthew Dillon #include <string.h> 47e92324a2SMatthew Dillon #include <unistd.h> 48ae3a37adSRobert Watson #include <limits.h> 49ae3a37adSRobert Watson 50ae3a37adSRobert Watson #include "kvm_private.h" 51e92324a2SMatthew Dillon 52bf0e1ee3SPeter Wemm #define NL_SWAPBLIST 0 53bf0e1ee3SPeter Wemm #define NL_SWDEVT 1 54bf0e1ee3SPeter Wemm #define NL_NSWDEV 2 55bf0e1ee3SPeter Wemm #define NL_DMMAX 3 56e92324a2SMatthew Dillon 57e92324a2SMatthew Dillon static int kvm_swap_nl_cached = 0; 58ae3a37adSRobert Watson static int unswdev; /* number of found swap dev's */ 59e92324a2SMatthew Dillon static int dmmax; 60e92324a2SMatthew Dillon 61ae3a37adSRobert Watson static int kvm_getswapinfo_sysctl(kvm_t *, struct kvm_swap *, int, int); 62e04a7c4aSThomas Moestl static int getsysctl(kvm_t *, char *, void *, size_t); 63e92324a2SMatthew Dillon 64ae3a37adSRobert Watson #define GETSWDEVNAME(dev, str, flags) \ 65ae3a37adSRobert Watson if (dev == NODEV) { \ 66ae3a37adSRobert Watson strlcpy(str, "[NFS swap]", sizeof(str)); \ 67ae3a37adSRobert Watson } else { \ 68ae3a37adSRobert Watson snprintf( \ 69ae3a37adSRobert Watson str, sizeof(str),"%s%s", \ 70ae3a37adSRobert Watson ((flags & SWIF_DEV_PREFIX) ? _PATH_DEV : ""), \ 71ae3a37adSRobert Watson devname(dev, S_IFCHR) \ 72ae3a37adSRobert Watson ); \ 73ae3a37adSRobert Watson } 74ae3a37adSRobert Watson 75e92324a2SMatthew Dillon int 76e92324a2SMatthew Dillon kvm_getswapinfo( 77e92324a2SMatthew Dillon kvm_t *kd, 78e92324a2SMatthew Dillon struct kvm_swap *swap_ary, 79e92324a2SMatthew Dillon int swap_max, 80e92324a2SMatthew Dillon int flags 81e92324a2SMatthew Dillon ) { 82e92324a2SMatthew Dillon 83e92324a2SMatthew Dillon /* 84e92324a2SMatthew Dillon * clear cache 85e92324a2SMatthew Dillon */ 86e92324a2SMatthew Dillon if (kd == NULL) { 87e92324a2SMatthew Dillon kvm_swap_nl_cached = 0; 88e92324a2SMatthew Dillon return(0); 89e92324a2SMatthew Dillon } 90e92324a2SMatthew Dillon 91ae3a37adSRobert Watson if (ISALIVE(kd)) { 92ae3a37adSRobert Watson return kvm_getswapinfo_sysctl(kd, swap_ary, swap_max, flags); 93ae3a37adSRobert Watson } else { 945d6fec5bSPoul-Henning Kamp return -1; 95ae3a37adSRobert Watson } 96ae3a37adSRobert Watson } 97ae3a37adSRobert Watson 98ae3a37adSRobert Watson #define GETSYSCTL(kd, name, var) \ 99ae3a37adSRobert Watson getsysctl(kd, name, &(var), sizeof(var)) 100e04a7c4aSThomas Moestl 101e04a7c4aSThomas Moestl /* The maximum MIB length for vm.swap_info and an additional device number */ 102e04a7c4aSThomas Moestl #define SWI_MAXMIB 3 103ae3a37adSRobert Watson 104ae3a37adSRobert Watson int 105ae3a37adSRobert Watson kvm_getswapinfo_sysctl( 106ae3a37adSRobert Watson kvm_t *kd, 107ae3a37adSRobert Watson struct kvm_swap *swap_ary, 108ae3a37adSRobert Watson int swap_max, 109ae3a37adSRobert Watson int flags 110ae3a37adSRobert Watson ) { 111e04a7c4aSThomas Moestl int ti, ttl; 112e04a7c4aSThomas Moestl size_t mibi, len; 113e04a7c4aSThomas Moestl int soid[SWI_MAXMIB]; 114e04a7c4aSThomas Moestl struct xswdev xsd; 115e04a7c4aSThomas Moestl struct kvm_swap tot; 116ae3a37adSRobert Watson 117ae3a37adSRobert Watson if (!GETSYSCTL(kd, "vm.dmmax", dmmax)) 118ae3a37adSRobert Watson return -1; 119ae3a37adSRobert Watson 120e04a7c4aSThomas Moestl mibi = SWI_MAXMIB - 1; 121e04a7c4aSThomas Moestl if (sysctlnametomib("vm.swap_info", soid, &mibi) == -1) { 122e04a7c4aSThomas Moestl _kvm_err(kd, kd->program, "sysctlnametomib failed: %s", 123e04a7c4aSThomas Moestl strerror(errno)); 124e04a7c4aSThomas Moestl return -1; 125e04a7c4aSThomas Moestl } 126e04a7c4aSThomas Moestl bzero(&tot, sizeof(tot)); 127e04a7c4aSThomas Moestl for (unswdev = 0;; unswdev++) { 128e04a7c4aSThomas Moestl soid[mibi] = unswdev; 129e04a7c4aSThomas Moestl len = sizeof(xsd); 130e04a7c4aSThomas Moestl if (sysctl(soid, mibi + 1, &xsd, &len, NULL, 0) == -1) { 131e04a7c4aSThomas Moestl if (errno == ENOENT) 132e04a7c4aSThomas Moestl break; 133e04a7c4aSThomas Moestl _kvm_err(kd, kd->program, "cannot read sysctl: %s.", 134e04a7c4aSThomas Moestl strerror(errno)); 135e04a7c4aSThomas Moestl return -1; 136e04a7c4aSThomas Moestl } 137e04a7c4aSThomas Moestl if (len != sizeof(xsd)) { 138e04a7c4aSThomas Moestl _kvm_err(kd, kd->program, "struct xswdev has unexpected " 139e04a7c4aSThomas Moestl "size; kernel and libkvm out of sync?"); 140e04a7c4aSThomas Moestl return -1; 141e04a7c4aSThomas Moestl } 142e04a7c4aSThomas Moestl if (xsd.xsw_version != XSWDEV_VERSION) { 143e04a7c4aSThomas Moestl _kvm_err(kd, kd->program, "struct xswdev version " 144e04a7c4aSThomas Moestl "mismatch; kernel and libkvm out of sync?"); 145ae3a37adSRobert Watson return -1; 146ae3a37adSRobert Watson } 147ae3a37adSRobert Watson 148e04a7c4aSThomas Moestl ttl = xsd.xsw_nblks - dmmax; 149e04a7c4aSThomas Moestl if (unswdev < swap_max - 1) { 150e04a7c4aSThomas Moestl bzero(&swap_ary[unswdev], sizeof(swap_ary[unswdev])); 151e04a7c4aSThomas Moestl swap_ary[unswdev].ksw_total = ttl; 152e04a7c4aSThomas Moestl swap_ary[unswdev].ksw_used = xsd.xsw_used; 153e04a7c4aSThomas Moestl swap_ary[unswdev].ksw_flags = xsd.xsw_flags; 154e04a7c4aSThomas Moestl GETSWDEVNAME(xsd.xsw_dev, swap_ary[unswdev].ksw_devname, 155e04a7c4aSThomas Moestl flags); 156e04a7c4aSThomas Moestl } 157e04a7c4aSThomas Moestl tot.ksw_total += ttl; 158e04a7c4aSThomas Moestl tot.ksw_used += xsd.xsw_used; 159e04a7c4aSThomas Moestl } 160ae3a37adSRobert Watson 161e04a7c4aSThomas Moestl ti = unswdev; 162e04a7c4aSThomas Moestl if (ti >= swap_max) 163e04a7c4aSThomas Moestl ti = swap_max - 1; 164e04a7c4aSThomas Moestl if (ti >= 0) 165e04a7c4aSThomas Moestl swap_ary[ti] = tot; 166ae3a37adSRobert Watson 167ae3a37adSRobert Watson return(ti); 168ae3a37adSRobert Watson } 169ae3a37adSRobert Watson 170ae3a37adSRobert Watson static int 171ae3a37adSRobert Watson getsysctl ( 172ae3a37adSRobert Watson kvm_t *kd, 173ae3a37adSRobert Watson char *name, 174ae3a37adSRobert Watson void *ptr, 175e04a7c4aSThomas Moestl size_t len 176ae3a37adSRobert Watson ) { 177e04a7c4aSThomas Moestl size_t nlen = len; 178ae3a37adSRobert Watson if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { 179e04a7c4aSThomas Moestl _kvm_err(kd, kd->program, "cannot read sysctl %s:%s", name, 180e04a7c4aSThomas Moestl strerror(errno)); 181ae3a37adSRobert Watson return (0); 182ae3a37adSRobert Watson } 183ae3a37adSRobert Watson if (nlen != len) { 184ae3a37adSRobert Watson _kvm_err(kd, kd->program, "sysctl %s has unexpected size", name); 185ae3a37adSRobert Watson return (0); 186ae3a37adSRobert Watson } 187ae3a37adSRobert Watson return (1); 188ae3a37adSRobert Watson } 189