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