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