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 /************************************************************/ 48 static uint npages, spp; 49 static int pagesize, statsfd = -1; 50 static u_char *statp; 51 52 void 53 geom_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 63 void 64 geom_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 86 int 87 geom_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 113 struct 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 123 void * 124 geom_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 146 void 147 geom_stats_snapshot_free(void *arg) 148 { 149 struct snapshot *sp; 150 151 sp = arg; 152 free(sp->ptr); 153 free(sp); 154 } 155 156 void 157 geom_stats_snapshot_timestamp(void *arg, struct timespec *tp) 158 { 159 struct snapshot *sp; 160 161 sp = arg; 162 *tp = sp->time; 163 } 164 165 void 166 geom_stats_snapshot_reset(void *arg) 167 { 168 struct snapshot *sp; 169 170 sp = arg; 171 sp->u = sp->v = 0; 172 } 173 174 struct devstat * 175 geom_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