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 if (statp != NULL) { 58 if (munmap(statp, npages * pagesize) != 0) 59 err(1, "munmap"); 60 statp = NULL; 61 } 62 close(statsfd); 63 statsfd = -1; 64 } 65 66 void 67 geom_stats_resync(void) 68 { 69 void *p; 70 off_t mediasize; 71 int error; 72 73 if (statsfd == -1) 74 return; 75 error = ioctl(statsfd, DIOCGMEDIASIZE, &mediasize); 76 if (error) 77 err(1, "DIOCGMEDIASIZE(" _PATH_DEV DEVSTAT_DEVICE_NAME ")"); 78 79 if (statp != NULL && munmap(statp, npages * pagesize) != 0) 80 err(1, "munmap"); 81 p = mmap(NULL, mediasize, PROT_READ, MAP_SHARED, statsfd, 0); 82 if (p == MAP_FAILED) 83 err(1, "mmap(/dev/devstat)"); 84 statp = p; 85 npages = mediasize / pagesize; 86 } 87 88 int 89 geom_stats_open(void) 90 { 91 if (statsfd != -1) 92 return (EBUSY); 93 statsfd = open(_PATH_DEV DEVSTAT_DEVICE_NAME, O_RDONLY); 94 if (statsfd < 0) 95 return (errno); 96 pagesize = getpagesize(); 97 spp = pagesize / sizeof(struct devstat); 98 npages = 1; 99 geom_stats_resync(); 100 return (0); 101 } 102 103 struct snapshot { 104 u_char *ptr; 105 uint pages; 106 uint pagesize; 107 uint perpage; 108 struct timespec time; 109 /* used by getnext: */ 110 uint u, v; 111 }; 112 113 void * 114 geom_stats_snapshot_get(void) 115 { 116 struct snapshot *sp; 117 118 sp = malloc(sizeof *sp); 119 if (sp == NULL) 120 return (NULL); 121 memset(sp, 0, sizeof *sp); 122 sp->ptr = malloc(pagesize * npages); 123 if (sp->ptr == NULL) { 124 free(sp); 125 return (NULL); 126 } 127 explicit_bzero(sp->ptr, pagesize * npages); /* page in, cache */ 128 clock_gettime(CLOCK_REALTIME, &sp->time); 129 memcpy(sp->ptr, statp, pagesize * npages); 130 sp->pages = npages; 131 sp->perpage = spp; 132 sp->pagesize = pagesize; 133 return (sp); 134 } 135 136 void 137 geom_stats_snapshot_free(void *arg) 138 { 139 struct snapshot *sp; 140 141 sp = arg; 142 free(sp->ptr); 143 free(sp); 144 } 145 146 void 147 geom_stats_snapshot_timestamp(void *arg, struct timespec *tp) 148 { 149 struct snapshot *sp; 150 151 sp = arg; 152 *tp = sp->time; 153 } 154 155 void 156 geom_stats_snapshot_reset(void *arg) 157 { 158 struct snapshot *sp; 159 160 sp = arg; 161 sp->u = sp->v = 0; 162 } 163 164 struct devstat * 165 geom_stats_snapshot_next(void *arg) 166 { 167 struct devstat *gsp; 168 struct snapshot *sp; 169 170 sp = arg; 171 gsp = (struct devstat *) 172 (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp); 173 if (++sp->v >= sp->perpage) { 174 if (++sp->u >= sp->pages) 175 return (NULL); 176 else 177 sp->v = 0; 178 } 179 return (gsp); 180 } 181