geom_stats.c revision 112372
1193323Sed/*- 2193323Sed * Copyright (c) 2003 Poul-Henning Kamp 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 3. The names of the authors may not be used to endorse or promote 14193323Sed * products derived from this software without specific prior written 15193323Sed * permission. 16193323Sed * 17193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18201360Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27193323Sed * SUCH DAMAGE. 28193323Sed * 29193323Sed * $FreeBSD: head/lib/libgeom/geom_stats.c 112372 2003-03-18 09:53:46Z phk $ 30193323Sed */ 31193323Sed 32193323Sed#include <paths.h> 33193323Sed#include <errno.h> 34193323Sed#include <fcntl.h> 35193323Sed#include <stdlib.h> 36193323Sed#include <string.h> 37202375Srdivacky#include <unistd.h> 38193323Sed#include <libgeom.h> 39193323Sed 40193323Sed#include <sys/mman.h> 41193323Sed#include <sys/time.h> 42193323Sed#include <sys/types.h> 43193323Sed#include <sys/devicestat.h> 44193323Sed 45198090Srdivacky 46193323Sed/************************************************************/ 47193323Sedstatic uint npages, pagesize, spp; 48193323Sedstatic int statsfd = -1; 49193323Sedstatic u_char *statp; 50193323Sed 51193323Sedvoid 52193323Sedgeom_stats_close(void) 53193323Sed{ 54193323Sed if (statsfd == -1) 55193323Sed return; 56193323Sed munmap(statp, npages *pagesize); 57193323Sed statp = NULL; 58193323Sed close (statsfd); 59193323Sed statsfd = -1; 60193323Sed} 61193323Sed 62193323Sedvoid 63193323Sedgeom_stats_resync(void) 64193323Sed{ 65193323Sed void *p; 66193323Sed 67193323Sed if (statsfd == -1) 68193323Sed return; 69193323Sed for (;;) { 70193323Sed p = mmap(statp, (npages + 1) * pagesize, 71193323Sed PROT_READ, 0, statsfd, 0); 72193323Sed if (p == MAP_FAILED) 73193323Sed break; 74193323Sed else 75193323Sed statp = p; 76193323Sed npages++; 77193323Sed } 78193323Sed} 79193323Sed 80193323Sedint 81193323Sedgeom_stats_open(void) 82193323Sed{ 83193323Sed int error; 84193323Sed void *p; 85193323Sed 86193323Sed if (statsfd != -1) 87193323Sed return (EBUSY); 88193323Sed statsfd = open(_PATH_DEV DEVSTAT_DEVICE_NAME, O_RDONLY); 89193323Sed if (statsfd < 0) 90193323Sed return (errno); 91193323Sed pagesize = getpagesize(); 92193323Sed spp = pagesize / sizeof(struct devstat); 93193323Sed p = mmap(NULL, pagesize, PROT_READ, 0, statsfd, 0); 94193323Sed if (p == MAP_FAILED) { 95193323Sed error = errno; 96 close(statsfd); 97 statsfd = -1; 98 errno = error; 99 return (error); 100 } 101 statp = p; 102 npages = 1; 103 geom_stats_resync(); 104 return (0); 105} 106 107struct snapshot { 108 u_char *ptr; 109 uint pages; 110 uint pagesize; 111 uint perpage; 112 struct timespec time; 113 /* used by getnext: */ 114 uint u, v; 115}; 116 117void * 118geom_stats_snapshot_get(void) 119{ 120 struct snapshot *sp; 121 122 sp = malloc(sizeof *sp); 123 if (sp == NULL) 124 return (NULL); 125 memset(sp, 0, sizeof *sp); 126 sp->ptr = malloc(pagesize * npages); 127 if (sp->ptr == NULL) { 128 free(sp); 129 return (NULL); 130 } 131 memset(sp->ptr, 0, pagesize * npages); /* page in, cache */ 132 clock_gettime(CLOCK_REALTIME, &sp->time); 133 memset(sp->ptr, 0, pagesize * npages); /* page in, cache */ 134 memcpy(sp->ptr, statp, pagesize * npages); 135 sp->pages = npages; 136 sp->perpage = spp; 137 sp->pagesize = pagesize; 138 return (sp); 139} 140 141void 142geom_stats_snapshot_free(void *arg) 143{ 144 struct snapshot *sp; 145 146 sp = arg; 147 free(sp->ptr); 148 free(sp); 149} 150 151void 152geom_stats_snapshot_timestamp(void *arg, struct timespec *tp) 153{ 154 struct snapshot *sp; 155 156 sp = arg; 157 *tp = sp->time; 158} 159 160void 161geom_stats_snapshot_reset(void *arg) 162{ 163 struct snapshot *sp; 164 165 sp = arg; 166 sp->u = sp->v = 0; 167} 168 169struct devstat * 170geom_stats_snapshot_next(void *arg) 171{ 172 struct devstat *gsp; 173 struct snapshot *sp; 174 175 sp = arg; 176 gsp = (struct devstat *) 177 (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp); 178 if (++sp->v >= sp->perpage) { 179 if (++sp->u >= sp->pages) 180 return (NULL); 181 else 182 sp->v = 0; 183 } 184 return (gsp); 185} 186