1e13db587SPoul-Henning Kamp /*- 2eb8f8877SWarner Losh * SPDX-License-Identifier: BSD-3-Clause 35e53a4f9SPedro F. Giffuni * 4e13db587SPoul-Henning Kamp * Copyright (c) 2003 Poul-Henning Kamp 5e13db587SPoul-Henning Kamp * All rights reserved. 6e13db587SPoul-Henning Kamp * 7e13db587SPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 8e13db587SPoul-Henning Kamp * modification, are permitted provided that the following conditions 9e13db587SPoul-Henning Kamp * are met: 10e13db587SPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 11e13db587SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 12e13db587SPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright 13e13db587SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the 14e13db587SPoul-Henning Kamp * documentation and/or other materials provided with the distribution. 15e13db587SPoul-Henning Kamp * 3. The names of the authors may not be used to endorse or promote 16e13db587SPoul-Henning Kamp * products derived from this software without specific prior written 17e13db587SPoul-Henning Kamp * permission. 18e13db587SPoul-Henning Kamp * 19e13db587SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20e13db587SPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21e13db587SPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22e13db587SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23e13db587SPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24e13db587SPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25e13db587SPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26e13db587SPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27e13db587SPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28e13db587SPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29e13db587SPoul-Henning Kamp * SUCH DAMAGE. 30e13db587SPoul-Henning Kamp */ 31e13db587SPoul-Henning Kamp 32ae0cf296SEnji Cooper #include <sys/types.h> 33ab63da35SAlan Somers #include <sys/ioctl.h> 34ab63da35SAlan Somers #include <sys/disk.h> 35ae0cf296SEnji Cooper #include <sys/devicestat.h> 36ae0cf296SEnji Cooper #include <sys/mman.h> 37ae0cf296SEnji Cooper #include <sys/time.h> 38ab63da35SAlan Somers #include <err.h> 39e13db587SPoul-Henning Kamp #include <errno.h> 40e13db587SPoul-Henning Kamp #include <fcntl.h> 41ae0cf296SEnji Cooper #include <paths.h> 42e13db587SPoul-Henning Kamp #include <stdlib.h> 43e13db587SPoul-Henning Kamp #include <string.h> 44e13db587SPoul-Henning Kamp #include <unistd.h> 45e13db587SPoul-Henning Kamp #include <libgeom.h> 46e13db587SPoul-Henning Kamp 47e13db587SPoul-Henning Kamp /************************************************************/ 483bacccb6SEnji Cooper static uint npages, spp; 493bacccb6SEnji Cooper static int pagesize, statsfd = -1; 50e13db587SPoul-Henning Kamp static u_char *statp; 51e13db587SPoul-Henning Kamp 52e13db587SPoul-Henning Kamp void 53e13db587SPoul-Henning Kamp geom_stats_close(void) 54e13db587SPoul-Henning Kamp { 55e13db587SPoul-Henning Kamp if (statsfd == -1) 56e13db587SPoul-Henning Kamp return; 57*d06fe346SMark Johnston if (statp != NULL) { 58*d06fe346SMark Johnston if (munmap(statp, npages * pagesize) != 0) 59*d06fe346SMark Johnston err(1, "munmap"); 60e13db587SPoul-Henning Kamp statp = NULL; 61*d06fe346SMark Johnston } 62e13db587SPoul-Henning Kamp close(statsfd); 63e13db587SPoul-Henning Kamp statsfd = -1; 64e13db587SPoul-Henning Kamp } 65e13db587SPoul-Henning Kamp 66e13db587SPoul-Henning Kamp void 67e13db587SPoul-Henning Kamp geom_stats_resync(void) 68e13db587SPoul-Henning Kamp { 69e13db587SPoul-Henning Kamp void *p; 70ab63da35SAlan Somers off_t mediasize; 71ab63da35SAlan Somers int error; 72e13db587SPoul-Henning Kamp 73e13db587SPoul-Henning Kamp if (statsfd == -1) 74e13db587SPoul-Henning Kamp return; 75ab63da35SAlan Somers error = ioctl(statsfd, DIOCGMEDIASIZE, &mediasize); 76ab63da35SAlan Somers if (error) 77ab63da35SAlan Somers err(1, "DIOCGMEDIASIZE(" _PATH_DEV DEVSTAT_DEVICE_NAME ")"); 78ab63da35SAlan Somers 79*d06fe346SMark Johnston if (statp != NULL && munmap(statp, npages * pagesize) != 0) 80*d06fe346SMark Johnston err(1, "munmap"); 81*d06fe346SMark Johnston p = mmap(NULL, mediasize, PROT_READ, MAP_SHARED, statsfd, 0); 82e13db587SPoul-Henning Kamp if (p == MAP_FAILED) 83*d06fe346SMark Johnston err(1, "mmap(/dev/devstat)"); 84e13db587SPoul-Henning Kamp statp = p; 85ab63da35SAlan Somers npages = mediasize / pagesize; 86e13db587SPoul-Henning Kamp } 87e13db587SPoul-Henning Kamp 88e13db587SPoul-Henning Kamp int 89e13db587SPoul-Henning Kamp geom_stats_open(void) 90e13db587SPoul-Henning Kamp { 91e13db587SPoul-Henning Kamp if (statsfd != -1) 92e13db587SPoul-Henning Kamp return (EBUSY); 932892a228SPoul-Henning Kamp statsfd = open(_PATH_DEV DEVSTAT_DEVICE_NAME, O_RDONLY); 94e13db587SPoul-Henning Kamp if (statsfd < 0) 95e13db587SPoul-Henning Kamp return (errno); 96e13db587SPoul-Henning Kamp pagesize = getpagesize(); 972892a228SPoul-Henning Kamp spp = pagesize / sizeof(struct devstat); 98e13db587SPoul-Henning Kamp npages = 1; 99e13db587SPoul-Henning Kamp geom_stats_resync(); 100e13db587SPoul-Henning Kamp return (0); 101e13db587SPoul-Henning Kamp } 102e13db587SPoul-Henning Kamp 103e13db587SPoul-Henning Kamp struct snapshot { 104e13db587SPoul-Henning Kamp u_char *ptr; 105e13db587SPoul-Henning Kamp uint pages; 106e13db587SPoul-Henning Kamp uint pagesize; 107e13db587SPoul-Henning Kamp uint perpage; 108e13db587SPoul-Henning Kamp struct timespec time; 109e13db587SPoul-Henning Kamp /* used by getnext: */ 110e13db587SPoul-Henning Kamp uint u, v; 111e13db587SPoul-Henning Kamp }; 112e13db587SPoul-Henning Kamp 113e13db587SPoul-Henning Kamp void * 114e13db587SPoul-Henning Kamp geom_stats_snapshot_get(void) 115e13db587SPoul-Henning Kamp { 116e13db587SPoul-Henning Kamp struct snapshot *sp; 117e13db587SPoul-Henning Kamp 118e13db587SPoul-Henning Kamp sp = malloc(sizeof *sp); 119e13db587SPoul-Henning Kamp if (sp == NULL) 120e13db587SPoul-Henning Kamp return (NULL); 121e13db587SPoul-Henning Kamp memset(sp, 0, sizeof *sp); 122e13db587SPoul-Henning Kamp sp->ptr = malloc(pagesize * npages); 123e13db587SPoul-Henning Kamp if (sp->ptr == NULL) { 124e13db587SPoul-Henning Kamp free(sp); 125e13db587SPoul-Henning Kamp return (NULL); 126e13db587SPoul-Henning Kamp } 127f05b724eSAlan Somers explicit_bzero(sp->ptr, pagesize * npages); /* page in, cache */ 128e13db587SPoul-Henning Kamp clock_gettime(CLOCK_REALTIME, &sp->time); 129e13db587SPoul-Henning Kamp memcpy(sp->ptr, statp, pagesize * npages); 130e13db587SPoul-Henning Kamp sp->pages = npages; 131e13db587SPoul-Henning Kamp sp->perpage = spp; 132e13db587SPoul-Henning Kamp sp->pagesize = pagesize; 133e13db587SPoul-Henning Kamp return (sp); 134e13db587SPoul-Henning Kamp } 135e13db587SPoul-Henning Kamp 136e13db587SPoul-Henning Kamp void 137e13db587SPoul-Henning Kamp geom_stats_snapshot_free(void *arg) 138e13db587SPoul-Henning Kamp { 139e13db587SPoul-Henning Kamp struct snapshot *sp; 140e13db587SPoul-Henning Kamp 141e13db587SPoul-Henning Kamp sp = arg; 142e13db587SPoul-Henning Kamp free(sp->ptr); 143e13db587SPoul-Henning Kamp free(sp); 144e13db587SPoul-Henning Kamp } 145e13db587SPoul-Henning Kamp 146e13db587SPoul-Henning Kamp void 147e13db587SPoul-Henning Kamp geom_stats_snapshot_timestamp(void *arg, struct timespec *tp) 148e13db587SPoul-Henning Kamp { 149e13db587SPoul-Henning Kamp struct snapshot *sp; 150e13db587SPoul-Henning Kamp 151e13db587SPoul-Henning Kamp sp = arg; 152e13db587SPoul-Henning Kamp *tp = sp->time; 153e13db587SPoul-Henning Kamp } 154e13db587SPoul-Henning Kamp 155e13db587SPoul-Henning Kamp void 156e13db587SPoul-Henning Kamp geom_stats_snapshot_reset(void *arg) 157e13db587SPoul-Henning Kamp { 158e13db587SPoul-Henning Kamp struct snapshot *sp; 159e13db587SPoul-Henning Kamp 160e13db587SPoul-Henning Kamp sp = arg; 161e13db587SPoul-Henning Kamp sp->u = sp->v = 0; 162e13db587SPoul-Henning Kamp } 163e13db587SPoul-Henning Kamp 1642892a228SPoul-Henning Kamp struct devstat * 165e13db587SPoul-Henning Kamp geom_stats_snapshot_next(void *arg) 166e13db587SPoul-Henning Kamp { 1672892a228SPoul-Henning Kamp struct devstat *gsp; 168e13db587SPoul-Henning Kamp struct snapshot *sp; 169e13db587SPoul-Henning Kamp 170e13db587SPoul-Henning Kamp sp = arg; 1712892a228SPoul-Henning Kamp gsp = (struct devstat *) 172e13db587SPoul-Henning Kamp (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp); 173e13db587SPoul-Henning Kamp if (++sp->v >= sp->perpage) { 174e13db587SPoul-Henning Kamp if (++sp->u >= sp->pages) 175e13db587SPoul-Henning Kamp return (NULL); 176e13db587SPoul-Henning Kamp else 177e13db587SPoul-Henning Kamp sp->v = 0; 178e13db587SPoul-Henning Kamp } 179e13db587SPoul-Henning Kamp return (gsp); 180e13db587SPoul-Henning Kamp } 181