1110545Sphk/*- 2110545Sphk * Copyright (c) 2003 Poul-Henning Kamp 3110545Sphk * All rights reserved. 4110545Sphk * 5110545Sphk * Redistribution and use in source and binary forms, with or without 6110545Sphk * modification, are permitted provided that the following conditions 7110545Sphk * are met: 8110545Sphk * 1. Redistributions of source code must retain the above copyright 9110545Sphk * notice, this list of conditions and the following disclaimer. 10110545Sphk * 2. Redistributions in binary form must reproduce the above copyright 11110545Sphk * notice, this list of conditions and the following disclaimer in the 12110545Sphk * documentation and/or other materials provided with the distribution. 13110545Sphk * 3. The names of the authors may not be used to endorse or promote 14110545Sphk * products derived from this software without specific prior written 15110545Sphk * permission. 16110545Sphk * 17110545Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18110545Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19110545Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20110545Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21110545Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22110545Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23110545Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24110545Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25110545Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26110545Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27110545Sphk * SUCH DAMAGE. 28110545Sphk * 29110545Sphk * $FreeBSD$ 30110545Sphk */ 31110545Sphk 32110545Sphk#include <paths.h> 33110545Sphk#include <errno.h> 34110545Sphk#include <fcntl.h> 35110545Sphk#include <stdlib.h> 36110545Sphk#include <string.h> 37110545Sphk#include <unistd.h> 38110545Sphk#include <libgeom.h> 39110545Sphk 40110545Sphk#include <sys/mman.h> 41110545Sphk#include <sys/time.h> 42110545Sphk#include <sys/types.h> 43112372Sphk#include <sys/devicestat.h> 44110545Sphk 45110545Sphk 46110545Sphk/************************************************************/ 47110545Sphkstatic uint npages, pagesize, spp; 48110545Sphkstatic int statsfd = -1; 49110545Sphkstatic u_char *statp; 50110545Sphk 51110545Sphkvoid 52110545Sphkgeom_stats_close(void) 53110545Sphk{ 54110545Sphk if (statsfd == -1) 55110545Sphk return; 56110545Sphk munmap(statp, npages *pagesize); 57110545Sphk statp = NULL; 58110545Sphk close (statsfd); 59110545Sphk statsfd = -1; 60110545Sphk} 61110545Sphk 62110545Sphkvoid 63110545Sphkgeom_stats_resync(void) 64110545Sphk{ 65110545Sphk void *p; 66110545Sphk 67110545Sphk if (statsfd == -1) 68110545Sphk return; 69110545Sphk for (;;) { 70110545Sphk p = mmap(statp, (npages + 1) * pagesize, 71110545Sphk PROT_READ, 0, statsfd, 0); 72110545Sphk if (p == MAP_FAILED) 73110545Sphk break; 74110545Sphk else 75110545Sphk statp = p; 76110545Sphk npages++; 77110545Sphk } 78110545Sphk} 79110545Sphk 80110545Sphkint 81110545Sphkgeom_stats_open(void) 82110545Sphk{ 83110545Sphk int error; 84110545Sphk void *p; 85110545Sphk 86110545Sphk if (statsfd != -1) 87110545Sphk return (EBUSY); 88112372Sphk statsfd = open(_PATH_DEV DEVSTAT_DEVICE_NAME, O_RDONLY); 89110545Sphk if (statsfd < 0) 90110545Sphk return (errno); 91110545Sphk pagesize = getpagesize(); 92112372Sphk spp = pagesize / sizeof(struct devstat); 93110545Sphk p = mmap(NULL, pagesize, PROT_READ, 0, statsfd, 0); 94110545Sphk if (p == MAP_FAILED) { 95110545Sphk error = errno; 96110545Sphk close(statsfd); 97110545Sphk statsfd = -1; 98110545Sphk errno = error; 99110545Sphk return (error); 100110545Sphk } 101110545Sphk statp = p; 102110545Sphk npages = 1; 103110545Sphk geom_stats_resync(); 104110545Sphk return (0); 105110545Sphk} 106110545Sphk 107110545Sphkstruct snapshot { 108110545Sphk u_char *ptr; 109110545Sphk uint pages; 110110545Sphk uint pagesize; 111110545Sphk uint perpage; 112110545Sphk struct timespec time; 113110545Sphk /* used by getnext: */ 114110545Sphk uint u, v; 115110545Sphk}; 116110545Sphk 117110545Sphkvoid * 118110545Sphkgeom_stats_snapshot_get(void) 119110545Sphk{ 120110545Sphk struct snapshot *sp; 121110545Sphk 122110545Sphk sp = malloc(sizeof *sp); 123110545Sphk if (sp == NULL) 124110545Sphk return (NULL); 125110545Sphk memset(sp, 0, sizeof *sp); 126110545Sphk sp->ptr = malloc(pagesize * npages); 127110545Sphk if (sp->ptr == NULL) { 128110545Sphk free(sp); 129110545Sphk return (NULL); 130110545Sphk } 131110545Sphk memset(sp->ptr, 0, pagesize * npages); /* page in, cache */ 132110545Sphk clock_gettime(CLOCK_REALTIME, &sp->time); 133110545Sphk memset(sp->ptr, 0, pagesize * npages); /* page in, cache */ 134110545Sphk memcpy(sp->ptr, statp, pagesize * npages); 135110545Sphk sp->pages = npages; 136110545Sphk sp->perpage = spp; 137110545Sphk sp->pagesize = pagesize; 138110545Sphk return (sp); 139110545Sphk} 140110545Sphk 141110545Sphkvoid 142110545Sphkgeom_stats_snapshot_free(void *arg) 143110545Sphk{ 144110545Sphk struct snapshot *sp; 145110545Sphk 146110545Sphk sp = arg; 147110545Sphk free(sp->ptr); 148110545Sphk free(sp); 149110545Sphk} 150110545Sphk 151110545Sphkvoid 152110545Sphkgeom_stats_snapshot_timestamp(void *arg, struct timespec *tp) 153110545Sphk{ 154110545Sphk struct snapshot *sp; 155110545Sphk 156110545Sphk sp = arg; 157110545Sphk *tp = sp->time; 158110545Sphk} 159110545Sphk 160110545Sphkvoid 161110545Sphkgeom_stats_snapshot_reset(void *arg) 162110545Sphk{ 163110545Sphk struct snapshot *sp; 164110545Sphk 165110545Sphk sp = arg; 166110545Sphk sp->u = sp->v = 0; 167110545Sphk} 168110545Sphk 169112372Sphkstruct devstat * 170110545Sphkgeom_stats_snapshot_next(void *arg) 171110545Sphk{ 172112372Sphk struct devstat *gsp; 173110545Sphk struct snapshot *sp; 174110545Sphk 175110545Sphk sp = arg; 176112372Sphk gsp = (struct devstat *) 177110545Sphk (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp); 178110545Sphk if (++sp->v >= sp->perpage) { 179110545Sphk if (++sp->u >= sp->pages) 180110545Sphk return (NULL); 181110545Sphk else 182110545Sphk sp->v = 0; 183110545Sphk } 184110545Sphk return (gsp); 185110545Sphk} 186