1/*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2003 Poul-Henning Kamp 5 * 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. The names of the authors may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/types.h> 33#include <sys/ioctl.h> 34#include <sys/disk.h> 35#include <sys/devicestat.h> 36#include <sys/mman.h> 37#include <sys/time.h> 38#include <err.h> 39#include <errno.h> 40#include <fcntl.h> 41#include <paths.h> 42#include <stdlib.h> 43#include <string.h> 44#include <unistd.h> 45#include <libgeom.h> 46 47/************************************************************/ 48static uint npages, spp; 49static int pagesize, statsfd = -1; 50static u_char *statp; 51 52void 53geom_stats_close(void) 54{ 55 if (statsfd == -1) 56 return; 57 munmap(statp, npages * pagesize); 58 statp = NULL; 59 close (statsfd); 60 statsfd = -1; 61} 62 63void 64geom_stats_resync(void) 65{ 66 void *p; 67 off_t mediasize; 68 int error; 69 70 if (statsfd == -1) 71 return; 72 error = ioctl(statsfd, DIOCGMEDIASIZE, &mediasize); 73 if (error) 74 err(1, "DIOCGMEDIASIZE(" _PATH_DEV DEVSTAT_DEVICE_NAME ")"); 75 76 munmap(statp, npages * pagesize); 77 p = mmap(statp, mediasize, PROT_READ, MAP_SHARED, statsfd, 0); 78 if (p == MAP_FAILED) 79 err(1, "mmap(/dev/devstat):"); 80 else { 81 statp = p; 82 npages = mediasize / pagesize; 83 } 84} 85 86int 87geom_stats_open(void) 88{ 89 int error; 90 void *p; 91 92 if (statsfd != -1) 93 return (EBUSY); 94 statsfd = open(_PATH_DEV DEVSTAT_DEVICE_NAME, O_RDONLY); 95 if (statsfd < 0) 96 return (errno); 97 pagesize = getpagesize(); 98 spp = pagesize / sizeof(struct devstat); 99 p = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, statsfd, 0); 100 if (p == MAP_FAILED) { 101 error = errno; 102 close(statsfd); 103 statsfd = -1; 104 errno = error; 105 return (error); 106 } 107 statp = p; 108 npages = 1; 109 geom_stats_resync(); 110 return (0); 111} 112 113struct snapshot { 114 u_char *ptr; 115 uint pages; 116 uint pagesize; 117 uint perpage; 118 struct timespec time; 119 /* used by getnext: */ 120 uint u, v; 121}; 122 123void * 124geom_stats_snapshot_get(void) 125{ 126 struct snapshot *sp; 127 128 sp = malloc(sizeof *sp); 129 if (sp == NULL) 130 return (NULL); 131 memset(sp, 0, sizeof *sp); 132 sp->ptr = malloc(pagesize * npages); 133 if (sp->ptr == NULL) { 134 free(sp); 135 return (NULL); 136 } 137 explicit_bzero(sp->ptr, pagesize * npages); /* page in, cache */ 138 clock_gettime(CLOCK_REALTIME, &sp->time); 139 memcpy(sp->ptr, statp, pagesize * npages); 140 sp->pages = npages; 141 sp->perpage = spp; 142 sp->pagesize = pagesize; 143 return (sp); 144} 145 146void 147geom_stats_snapshot_free(void *arg) 148{ 149 struct snapshot *sp; 150 151 sp = arg; 152 free(sp->ptr); 153 free(sp); 154} 155 156void 157geom_stats_snapshot_timestamp(void *arg, struct timespec *tp) 158{ 159 struct snapshot *sp; 160 161 sp = arg; 162 *tp = sp->time; 163} 164 165void 166geom_stats_snapshot_reset(void *arg) 167{ 168 struct snapshot *sp; 169 170 sp = arg; 171 sp->u = sp->v = 0; 172} 173 174struct devstat * 175geom_stats_snapshot_next(void *arg) 176{ 177 struct devstat *gsp; 178 struct snapshot *sp; 179 180 sp = arg; 181 gsp = (struct devstat *) 182 (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp); 183 if (++sp->v >= sp->perpage) { 184 if (++sp->u >= sp->pages) 185 return (NULL); 186 else 187 sp->v = 0; 188 } 189 return (gsp); 190} 191