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