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