xref: /freebsd-src/lib/libgeom/geom_stats.c (revision d06fe346eccf0919a29d43599548e49c0d6a7a17)
1e13db587SPoul-Henning Kamp /*-
2eb8f8877SWarner Losh  * SPDX-License-Identifier: BSD-3-Clause
35e53a4f9SPedro F. Giffuni  *
4e13db587SPoul-Henning Kamp  * Copyright (c) 2003 Poul-Henning Kamp
5e13db587SPoul-Henning Kamp  * All rights reserved.
6e13db587SPoul-Henning Kamp  *
7e13db587SPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
8e13db587SPoul-Henning Kamp  * modification, are permitted provided that the following conditions
9e13db587SPoul-Henning Kamp  * are met:
10e13db587SPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
11e13db587SPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
12e13db587SPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
13e13db587SPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
14e13db587SPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
15e13db587SPoul-Henning Kamp  * 3. The names of the authors may not be used to endorse or promote
16e13db587SPoul-Henning Kamp  *    products derived from this software without specific prior written
17e13db587SPoul-Henning Kamp  *    permission.
18e13db587SPoul-Henning Kamp  *
19e13db587SPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20e13db587SPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21e13db587SPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22e13db587SPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23e13db587SPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24e13db587SPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25e13db587SPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26e13db587SPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27e13db587SPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28e13db587SPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29e13db587SPoul-Henning Kamp  * SUCH DAMAGE.
30e13db587SPoul-Henning Kamp  */
31e13db587SPoul-Henning Kamp 
32ae0cf296SEnji Cooper #include <sys/types.h>
33ab63da35SAlan Somers #include <sys/ioctl.h>
34ab63da35SAlan Somers #include <sys/disk.h>
35ae0cf296SEnji Cooper #include <sys/devicestat.h>
36ae0cf296SEnji Cooper #include <sys/mman.h>
37ae0cf296SEnji Cooper #include <sys/time.h>
38ab63da35SAlan Somers #include <err.h>
39e13db587SPoul-Henning Kamp #include <errno.h>
40e13db587SPoul-Henning Kamp #include <fcntl.h>
41ae0cf296SEnji Cooper #include <paths.h>
42e13db587SPoul-Henning Kamp #include <stdlib.h>
43e13db587SPoul-Henning Kamp #include <string.h>
44e13db587SPoul-Henning Kamp #include <unistd.h>
45e13db587SPoul-Henning Kamp #include <libgeom.h>
46e13db587SPoul-Henning Kamp 
47e13db587SPoul-Henning Kamp /************************************************************/
483bacccb6SEnji Cooper static uint npages, spp;
493bacccb6SEnji Cooper static int pagesize, statsfd = -1;
50e13db587SPoul-Henning Kamp static u_char *statp;
51e13db587SPoul-Henning Kamp 
52e13db587SPoul-Henning Kamp void
53e13db587SPoul-Henning Kamp geom_stats_close(void)
54e13db587SPoul-Henning Kamp {
55e13db587SPoul-Henning Kamp 	if (statsfd == -1)
56e13db587SPoul-Henning Kamp 		return;
57*d06fe346SMark Johnston 	if (statp != NULL) {
58*d06fe346SMark Johnston 		if (munmap(statp, npages * pagesize) != 0)
59*d06fe346SMark Johnston 			err(1, "munmap");
60e13db587SPoul-Henning Kamp 		statp = NULL;
61*d06fe346SMark Johnston 	}
62e13db587SPoul-Henning Kamp 	close(statsfd);
63e13db587SPoul-Henning Kamp 	statsfd = -1;
64e13db587SPoul-Henning Kamp }
65e13db587SPoul-Henning Kamp 
66e13db587SPoul-Henning Kamp void
67e13db587SPoul-Henning Kamp geom_stats_resync(void)
68e13db587SPoul-Henning Kamp {
69e13db587SPoul-Henning Kamp 	void *p;
70ab63da35SAlan Somers 	off_t mediasize;
71ab63da35SAlan Somers 	int error;
72e13db587SPoul-Henning Kamp 
73e13db587SPoul-Henning Kamp 	if (statsfd == -1)
74e13db587SPoul-Henning Kamp 		return;
75ab63da35SAlan Somers 	error = ioctl(statsfd, DIOCGMEDIASIZE, &mediasize);
76ab63da35SAlan Somers 	if (error)
77ab63da35SAlan Somers 		err(1, "DIOCGMEDIASIZE(" _PATH_DEV DEVSTAT_DEVICE_NAME ")");
78ab63da35SAlan Somers 
79*d06fe346SMark Johnston 	if (statp != NULL && munmap(statp, npages * pagesize) != 0)
80*d06fe346SMark Johnston 		err(1, "munmap");
81*d06fe346SMark Johnston 	p = mmap(NULL, mediasize, PROT_READ, MAP_SHARED, statsfd, 0);
82e13db587SPoul-Henning Kamp 	if (p == MAP_FAILED)
83*d06fe346SMark Johnston 		err(1, "mmap(/dev/devstat)");
84e13db587SPoul-Henning Kamp 	statp = p;
85ab63da35SAlan Somers 	npages = mediasize / pagesize;
86e13db587SPoul-Henning Kamp }
87e13db587SPoul-Henning Kamp 
88e13db587SPoul-Henning Kamp int
89e13db587SPoul-Henning Kamp geom_stats_open(void)
90e13db587SPoul-Henning Kamp {
91e13db587SPoul-Henning Kamp 	if (statsfd != -1)
92e13db587SPoul-Henning Kamp 		return (EBUSY);
932892a228SPoul-Henning Kamp 	statsfd = open(_PATH_DEV DEVSTAT_DEVICE_NAME, O_RDONLY);
94e13db587SPoul-Henning Kamp 	if (statsfd < 0)
95e13db587SPoul-Henning Kamp 		return (errno);
96e13db587SPoul-Henning Kamp 	pagesize = getpagesize();
972892a228SPoul-Henning Kamp 	spp = pagesize / sizeof(struct devstat);
98e13db587SPoul-Henning Kamp 	npages = 1;
99e13db587SPoul-Henning Kamp 	geom_stats_resync();
100e13db587SPoul-Henning Kamp 	return (0);
101e13db587SPoul-Henning Kamp }
102e13db587SPoul-Henning Kamp 
103e13db587SPoul-Henning Kamp struct snapshot {
104e13db587SPoul-Henning Kamp 	u_char		*ptr;
105e13db587SPoul-Henning Kamp 	uint		pages;
106e13db587SPoul-Henning Kamp 	uint		pagesize;
107e13db587SPoul-Henning Kamp 	uint		perpage;
108e13db587SPoul-Henning Kamp 	struct timespec	time;
109e13db587SPoul-Henning Kamp 	/* used by getnext: */
110e13db587SPoul-Henning Kamp 	uint		u, v;
111e13db587SPoul-Henning Kamp };
112e13db587SPoul-Henning Kamp 
113e13db587SPoul-Henning Kamp void *
114e13db587SPoul-Henning Kamp geom_stats_snapshot_get(void)
115e13db587SPoul-Henning Kamp {
116e13db587SPoul-Henning Kamp 	struct snapshot *sp;
117e13db587SPoul-Henning Kamp 
118e13db587SPoul-Henning Kamp 	sp = malloc(sizeof *sp);
119e13db587SPoul-Henning Kamp 	if (sp == NULL)
120e13db587SPoul-Henning Kamp 		return (NULL);
121e13db587SPoul-Henning Kamp 	memset(sp, 0, sizeof *sp);
122e13db587SPoul-Henning Kamp 	sp->ptr = malloc(pagesize * npages);
123e13db587SPoul-Henning Kamp 	if (sp->ptr == NULL) {
124e13db587SPoul-Henning Kamp 		free(sp);
125e13db587SPoul-Henning Kamp 		return (NULL);
126e13db587SPoul-Henning Kamp 	}
127f05b724eSAlan Somers 	explicit_bzero(sp->ptr, pagesize * npages); 	/* page in, cache */
128e13db587SPoul-Henning Kamp 	clock_gettime(CLOCK_REALTIME, &sp->time);
129e13db587SPoul-Henning Kamp 	memcpy(sp->ptr, statp, pagesize * npages);
130e13db587SPoul-Henning Kamp 	sp->pages = npages;
131e13db587SPoul-Henning Kamp 	sp->perpage = spp;
132e13db587SPoul-Henning Kamp 	sp->pagesize = pagesize;
133e13db587SPoul-Henning Kamp 	return (sp);
134e13db587SPoul-Henning Kamp }
135e13db587SPoul-Henning Kamp 
136e13db587SPoul-Henning Kamp void
137e13db587SPoul-Henning Kamp geom_stats_snapshot_free(void *arg)
138e13db587SPoul-Henning Kamp {
139e13db587SPoul-Henning Kamp 	struct snapshot *sp;
140e13db587SPoul-Henning Kamp 
141e13db587SPoul-Henning Kamp 	sp = arg;
142e13db587SPoul-Henning Kamp 	free(sp->ptr);
143e13db587SPoul-Henning Kamp 	free(sp);
144e13db587SPoul-Henning Kamp }
145e13db587SPoul-Henning Kamp 
146e13db587SPoul-Henning Kamp void
147e13db587SPoul-Henning Kamp geom_stats_snapshot_timestamp(void *arg, struct timespec *tp)
148e13db587SPoul-Henning Kamp {
149e13db587SPoul-Henning Kamp 	struct snapshot *sp;
150e13db587SPoul-Henning Kamp 
151e13db587SPoul-Henning Kamp 	sp = arg;
152e13db587SPoul-Henning Kamp 	*tp = sp->time;
153e13db587SPoul-Henning Kamp }
154e13db587SPoul-Henning Kamp 
155e13db587SPoul-Henning Kamp void
156e13db587SPoul-Henning Kamp geom_stats_snapshot_reset(void *arg)
157e13db587SPoul-Henning Kamp {
158e13db587SPoul-Henning Kamp 	struct snapshot *sp;
159e13db587SPoul-Henning Kamp 
160e13db587SPoul-Henning Kamp 	sp = arg;
161e13db587SPoul-Henning Kamp 	sp->u = sp->v = 0;
162e13db587SPoul-Henning Kamp }
163e13db587SPoul-Henning Kamp 
1642892a228SPoul-Henning Kamp struct devstat *
165e13db587SPoul-Henning Kamp geom_stats_snapshot_next(void *arg)
166e13db587SPoul-Henning Kamp {
1672892a228SPoul-Henning Kamp 	struct devstat *gsp;
168e13db587SPoul-Henning Kamp 	struct snapshot *sp;
169e13db587SPoul-Henning Kamp 
170e13db587SPoul-Henning Kamp 	sp = arg;
1712892a228SPoul-Henning Kamp 	gsp = (struct devstat *)
172e13db587SPoul-Henning Kamp 	    (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp);
173e13db587SPoul-Henning Kamp 	if (++sp->v >= sp->perpage) {
174e13db587SPoul-Henning Kamp 		if (++sp->u >= sp->pages)
175e13db587SPoul-Henning Kamp 			return (NULL);
176e13db587SPoul-Henning Kamp 		else
177e13db587SPoul-Henning Kamp 			sp->v = 0;
178e13db587SPoul-Henning Kamp 	}
179e13db587SPoul-Henning Kamp 	return (gsp);
180e13db587SPoul-Henning Kamp }
181