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