1 /*
2 * Copyright (c) 2007-2012 Willem Dijkstra
3 * Copyright (c) 2004 Matthew Gream
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32 /*
33 * Get current disk transfer statistics from kernel and return them in
34 * symon_buf as
35 *
36 * total nr of transfers : total seeks : total bytes transferred
37 */
38
39 #include "conf.h"
40
41 #include <sys/param.h>
42 #include <sys/sysctl.h>
43 #include <sys/disk.h>
44
45 #ifdef HAS_HW_IOSTATS
46 #include <sys/iostat.h>
47 #endif
48
49 #include <limits.h>
50 #include <string.h>
51 #include <stdlib.h>
52
53 #include "error.h"
54 #include "symon.h"
55 #include "xmalloc.h"
56
57 /* Globals for this module start with io_ */
58 static int io_dks = 0;
59 static int io_maxdks = 0;
60
61 #ifndef HAS_HW_IOSTATS
62 static struct disk_sysctl *io_dkstats = NULL;
63 void
gets_io()64 gets_io()
65 {
66 int mib[3];
67 size_t size;
68
69 /* read size */
70 mib[0] = CTL_HW;
71 mib[1] = HW_DISKSTATS;
72 mib[2] = sizeof (struct disk_sysctl);
73 size = 0;
74 if (sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
75 fatal("%s:%d: io can't get hw.diskstats"
76 __FILE__, __LINE__);
77 }
78 io_dks = size / sizeof (struct disk_sysctl);
79
80 /* adjust buffer if necessary */
81 if (io_dks > io_maxdks) {
82 io_maxdks = io_dks;
83
84 if (io_maxdks > SYMON_MAX_DOBJECTS) {
85 fatal("%s:%d: dynamic object limit (%d) exceeded for diskstat structures",
86 __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
87 }
88
89 io_dkstats = xrealloc(io_dkstats, io_maxdks * sizeof(struct disk_sysctl));
90 }
91
92 /* read structure */
93 size = io_maxdks * sizeof(struct disk_sysctl);
94 if (sysctl(mib, 3, io_dkstats, &size, NULL, 0) < 0) {
95 fatal("%s:%d: io can't get hw.diskstats"
96 __FILE__, __LINE__);
97 }
98 }
99 #else
100 static struct io_sysctl *io_dkstats = NULL;
101 void
gets_io()102 gets_io()
103 {
104 int mib[3];
105 size_t size;
106
107 /* read size */
108 mib[0] = CTL_HW;
109 mib[1] = HW_IOSTATS;
110 mib[2] = sizeof(struct io_sysctl);
111 size = 0;
112 if (sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
113 fatal("%s:%d: io can't get hw.iostats"
114 __FILE__, __LINE__);
115 }
116
117 io_dks = size / sizeof (struct io_sysctl);
118
119 /* adjust buffer if necessary */
120 if (io_dks > io_maxdks) {
121 io_maxdks = io_dks;
122
123 if (io_maxdks > SYMON_MAX_DOBJECTS) {
124 fatal("%s:%d: dynamic object limit (%d) exceeded for diskstat structures",
125 __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
126 }
127
128 io_dkstats = xrealloc(io_dkstats, io_maxdks * sizeof(struct io_sysctl));
129 }
130
131 /* read structure */
132 size = io_maxdks * sizeof(struct io_sysctl);
133 if (sysctl(mib, 3, io_dkstats, &size, NULL, 0) < 0) {
134 fatal("%s:%d: io can't get hw.iostats"
135 __FILE__, __LINE__);
136 }
137 }
138 #endif
139 void
init_io(struct stream * st)140 init_io(struct stream *st)
141 {
142 info("started module io(%.200s)", st->arg);
143 }
144
145 int
get_io(char * symon_buf,int maxlen,struct stream * st)146 get_io(char *symon_buf, int maxlen, struct stream *st)
147 {
148 int i;
149
150 #ifndef HAS_HW_IOSTATS
151 for (i = 0; i < io_maxdks; i++)
152 if (strncmp(io_dkstats[i].dk_name, st->arg,
153 sizeof(io_dkstats[i].dk_name)) == 0)
154 return snpack(symon_buf, maxlen, st->arg, MT_IO2,
155 io_dkstats[i].dk_rxfer,
156 io_dkstats[i].dk_wxfer,
157 io_dkstats[i].dk_seek,
158 io_dkstats[i].dk_rbytes,
159 io_dkstats[i].dk_wbytes);
160 #else
161 for (i = 0; i < io_maxdks; i++)
162 if (strncmp(io_dkstats[i].name, st->arg,
163 sizeof(io_dkstats[i].name)) == 0)
164 return snpack(symon_buf, maxlen, st->arg, MT_IO2,
165 io_dkstats[i].rxfer,
166 io_dkstats[i].wxfer,
167 io_dkstats[i].seek,
168 io_dkstats[i].rbytes,
169 io_dkstats[i].wbytes);
170 #endif
171
172 return 0;
173 }
174