geom_stats.c revision 110545
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: head/lib/libgeom/geom_stats.c 110545 2003-02-08 15:15:56Z phk $
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>
43110545Sphk
44110545Sphk#include <geom/geom_stats.h>
45110545Sphk#if 0
46110545Sphk#include <stdio.h>
47110545Sphk#include <stdint.h>
48110545Sphk#include <err.h>
49110545Sphk#endif
50110545Sphk
51110545Sphk/************************************************************/
52110545Sphkstatic uint npages, pagesize, spp;
53110545Sphkstatic int statsfd = -1;
54110545Sphkstatic u_char *statp;
55110545Sphk
56110545Sphkvoid
57110545Sphkgeom_stats_close(void)
58110545Sphk{
59110545Sphk	if (statsfd == -1)
60110545Sphk		return;
61110545Sphk	munmap(statp, npages *pagesize);
62110545Sphk	statp = NULL;
63110545Sphk	close (statsfd);
64110545Sphk	statsfd = -1;
65110545Sphk}
66110545Sphk
67110545Sphkvoid
68110545Sphkgeom_stats_resync(void)
69110545Sphk{
70110545Sphk	void *p;
71110545Sphk
72110545Sphk	if (statsfd == -1)
73110545Sphk		return;
74110545Sphk	for (;;) {
75110545Sphk		p = mmap(statp, (npages + 1) * pagesize,
76110545Sphk		    PROT_READ, 0, statsfd, 0);
77110545Sphk		if (p == MAP_FAILED)
78110545Sphk			break;
79110545Sphk		else
80110545Sphk			statp = p;
81110545Sphk		npages++;
82110545Sphk	}
83110545Sphk}
84110545Sphk
85110545Sphkint
86110545Sphkgeom_stats_open(void)
87110545Sphk{
88110545Sphk	int error;
89110545Sphk	void *p;
90110545Sphk
91110545Sphk	if (statsfd != -1)
92110545Sphk		return (EBUSY);
93110545Sphk	statsfd = open(_PATH_DEV GEOM_STATS_DEVICE, O_RDONLY);
94110545Sphk	if (statsfd < 0)
95110545Sphk		return (errno);
96110545Sphk	pagesize = getpagesize();
97110545Sphk	spp = pagesize / sizeof(struct g_stat);
98110545Sphk	p = mmap(NULL, pagesize, PROT_READ, 0, statsfd, 0);
99110545Sphk	if (p == MAP_FAILED) {
100110545Sphk		error = errno;
101110545Sphk		close(statsfd);
102110545Sphk		statsfd = -1;
103110545Sphk		errno = error;
104110545Sphk		return (error);
105110545Sphk	}
106110545Sphk	statp = p;
107110545Sphk	npages = 1;
108110545Sphk	geom_stats_resync();
109110545Sphk	return (0);
110110545Sphk}
111110545Sphk
112110545Sphkstruct snapshot {
113110545Sphk	u_char		*ptr;
114110545Sphk	uint		pages;
115110545Sphk	uint		pagesize;
116110545Sphk	uint		perpage;
117110545Sphk	struct timespec	time;
118110545Sphk	/* used by getnext: */
119110545Sphk	uint		u, v;
120110545Sphk};
121110545Sphk
122110545Sphkvoid *
123110545Sphkgeom_stats_snapshot_get(void)
124110545Sphk{
125110545Sphk	struct snapshot *sp;
126110545Sphk
127110545Sphk	sp = malloc(sizeof *sp);
128110545Sphk	if (sp == NULL)
129110545Sphk		return (NULL);
130110545Sphk	memset(sp, 0, sizeof *sp);
131110545Sphk	sp->ptr = malloc(pagesize * npages);
132110545Sphk	if (sp->ptr == NULL) {
133110545Sphk		free(sp);
134110545Sphk		return (NULL);
135110545Sphk	}
136110545Sphk	memset(sp->ptr, 0, pagesize * npages); 	/* page in, cache */
137110545Sphk	clock_gettime(CLOCK_REALTIME, &sp->time);
138110545Sphk	memset(sp->ptr, 0, pagesize * npages); 	/* page in, cache */
139110545Sphk	memcpy(sp->ptr, statp, pagesize * npages);
140110545Sphk	sp->pages = npages;
141110545Sphk	sp->perpage = spp;
142110545Sphk	sp->pagesize = pagesize;
143110545Sphk	return (sp);
144110545Sphk}
145110545Sphk
146110545Sphkvoid
147110545Sphkgeom_stats_snapshot_free(void *arg)
148110545Sphk{
149110545Sphk	struct snapshot *sp;
150110545Sphk
151110545Sphk	sp = arg;
152110545Sphk	free(sp->ptr);
153110545Sphk	free(sp);
154110545Sphk}
155110545Sphk
156110545Sphkvoid
157110545Sphkgeom_stats_snapshot_timestamp(void *arg, struct timespec *tp)
158110545Sphk{
159110545Sphk	struct snapshot *sp;
160110545Sphk
161110545Sphk	sp = arg;
162110545Sphk	*tp = sp->time;
163110545Sphk}
164110545Sphk
165110545Sphkvoid
166110545Sphkgeom_stats_snapshot_reset(void *arg)
167110545Sphk{
168110545Sphk	struct snapshot *sp;
169110545Sphk
170110545Sphk	sp = arg;
171110545Sphk	sp->u = sp->v = 0;
172110545Sphk}
173110545Sphk
174110545Sphkstruct g_stat *
175110545Sphkgeom_stats_snapshot_next(void *arg)
176110545Sphk{
177110545Sphk	struct g_stat *gsp;
178110545Sphk	struct snapshot *sp;
179110545Sphk
180110545Sphk	sp = arg;
181110545Sphk	gsp = (struct g_stat *)
182110545Sphk	    (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp);
183110545Sphk	if (++sp->v >= sp->perpage) {
184110545Sphk		if (++sp->u >= sp->pages)
185110545Sphk			return (NULL);
186110545Sphk		else
187110545Sphk			sp->v = 0;
188110545Sphk	}
189110545Sphk	return (gsp);
190110545Sphk}
191