ia64/xen-unstable

view tools/xenstat/libxenstat/src/xenstat_linux.c @ 17824:f70dff36213b

xenstat: some cleanups
sprintf -> snprintf
malloc(n * m) -> calloc(n, m)
get rid of a cast

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 10 14:15:53 2008 +0100 (2008-06-10)
parents 7a0f1bf86516
children 7338f6301067
line source
1 /* libxenstat: statistics-collection library for Xen
2 * Copyright (C) International Business Machines Corp., 2005
3 * Authors: Josh Triplett <josh@kernel.org>
4 * Judy Fischbach <jfisch@cs.pdx.edu>
5 * David Hendricks <cro_marmot@comcast.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 */
18 /*
19 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
20 * Use is subject to license terms.
21 */
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
32 #include "xenstat_priv.h"
34 #define SYSFS_VBD_PATH "/sys/devices/xen-backend/"
36 struct priv_data {
37 FILE *procnetdev;
38 DIR *sysfsvbd;
39 };
41 static struct priv_data *
42 get_priv_data(xenstat_handle *handle)
43 {
44 if (handle->priv != NULL)
45 return handle->priv;
47 handle->priv = malloc(sizeof(struct priv_data));
48 if (handle->priv == NULL)
49 return (NULL);
51 ((struct priv_data *)handle->priv)->procnetdev = NULL;
52 ((struct priv_data *)handle->priv)->sysfsvbd = NULL;
54 return handle->priv;
55 }
57 /* Expected format of /proc/net/dev */
58 static const char PROCNETDEV_HEADER[] =
59 "Inter-| Receive |"
60 " Transmit\n"
61 " face |bytes packets errs drop fifo frame compressed multicast|"
62 "bytes packets errs drop fifo colls carrier compressed\n";
64 /* Collect information about networks */
65 int xenstat_collect_networks(xenstat_node * node)
66 {
67 struct priv_data *priv = get_priv_data(node->handle);
69 if (priv == NULL) {
70 perror("Allocation error");
71 return 0;
72 }
74 /* Open and validate /proc/net/dev if we haven't already */
75 if (priv->procnetdev == NULL) {
76 char header[sizeof(PROCNETDEV_HEADER)];
77 priv->procnetdev = fopen("/proc/net/dev", "r");
78 if (priv->procnetdev == NULL) {
79 perror("Error opening /proc/net/dev");
80 return 0;
81 }
83 /* Validate the format of /proc/net/dev */
84 if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1,
85 priv->procnetdev) != 1) {
86 perror("Error reading /proc/net/dev header");
87 return 0;
88 }
89 header[sizeof(PROCNETDEV_HEADER) - 1] = '\0';
90 if (strcmp(header, PROCNETDEV_HEADER) != 0) {
91 fprintf(stderr,
92 "Unexpected /proc/net/dev format\n");
93 return 0;
94 }
95 }
97 /* Fill in networks */
98 /* FIXME: optimize this */
99 fseek(priv->procnetdev, sizeof(PROCNETDEV_HEADER) - 1,
100 SEEK_SET);
101 while (1) {
102 xenstat_domain *domain;
103 xenstat_network net;
104 unsigned int domid;
105 int ret = fscanf(priv->procnetdev,
106 "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u"
107 "%llu%llu%llu%llu%*u%*u%*u%*u\n",
108 &domid, &net.id,
109 &net.tbytes, &net.tpackets, &net.terrs,
110 &net.tdrop,
111 &net.rbytes, &net.rpackets, &net.rerrs,
112 &net.rdrop);
113 if (ret == EOF)
114 break;
115 if (ret != 10) {
116 unsigned int c;
117 do {
118 c = fgetc(priv->procnetdev);
119 } while (c != '\n' && c != EOF);
120 if (c == EOF)
121 break;
122 continue;
123 }
125 /* FIXME: this does a search for the domid */
126 domain = xenstat_node_domain(node, domid);
127 if (domain == NULL) {
128 fprintf(stderr,
129 "Found interface vif%u.%u but domain %u"
130 " does not exist.\n", domid, net.id,
131 domid);
132 continue;
133 }
134 if (domain->networks == NULL) {
135 domain->num_networks = 1;
136 domain->networks = malloc(sizeof(xenstat_network));
137 } else {
138 struct xenstat_network *tmp;
139 domain->num_networks++;
140 tmp = realloc(domain->networks,
141 domain->num_networks *
142 sizeof(xenstat_network));
143 if (tmp == NULL)
144 free(domain->networks);
145 domain->networks = tmp;
146 }
147 if (domain->networks == NULL)
148 return 0;
149 domain->networks[domain->num_networks - 1] = net;
150 }
152 return 1;
153 }
155 /* Free network information in handle */
156 void xenstat_uninit_networks(xenstat_handle * handle)
157 {
158 struct priv_data *priv = get_priv_data(handle);
159 if (priv != NULL && priv->procnetdev != NULL)
160 fclose(priv->procnetdev);
161 }
163 static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap)
164 {
165 static char file_name[80];
166 int fd, num_read;
168 snprintf(file_name, sizeof(file_name), "%s/%s/%s",
169 SYSFS_VBD_PATH, vbd_directory, what);
170 fd = open(file_name, O_RDONLY, 0);
171 if (fd==-1) return -1;
172 num_read = read(fd, ret, cap - 1);
173 close(fd);
174 if (num_read<=0) return -1;
175 ret[num_read] = '\0';
176 return num_read;
177 }
179 /* Collect information about VBDs */
180 int xenstat_collect_vbds(xenstat_node * node)
181 {
182 struct dirent *dp;
183 struct priv_data *priv = get_priv_data(node->handle);
185 char *sys_prefix = "statistics/";
187 /* 23 = "statistics/" + "xxxx_xx_req" */
188 char ooreq[23], rdreq[23], wrreq[23];
189 char *stat_prefix = NULL;
191 if (priv == NULL) {
192 perror("Allocation error");
193 return 0;
194 }
196 if (priv->sysfsvbd == NULL) {
197 priv->sysfsvbd = opendir(SYSFS_VBD_PATH);
198 if (priv->sysfsvbd == NULL) {
199 perror("Error opening " SYSFS_VBD_PATH);
200 return 0;
201 }
202 }
204 rewinddir(priv->sysfsvbd);
206 for(dp = readdir(priv->sysfsvbd); dp != NULL ;
207 dp = readdir(priv->sysfsvbd)) {
208 xenstat_domain *domain;
209 xenstat_vbd vbd;
210 unsigned int domid;
211 int ret;
212 char buf[256];
214 ret = sscanf(dp->d_name, "%3s-%u-%u", buf, &domid, &vbd.dev);
215 if (ret != 3)
216 continue;
219 if (strcmp(buf,"vbd") == 0){
220 stat_prefix = "";
221 vbd.back_type = 1;
222 } else if (strcmp(buf,"tap") == 0){
223 stat_prefix = "tap_";
224 vbd.back_type = 2;
225 } else {
226 continue;
227 }
229 domain = xenstat_node_domain(node, domid);
230 if (domain == NULL) {
231 fprintf(stderr,
232 "Found interface %s-%u-%u but domain %u"
233 " does not exist.\n",
234 buf, domid, vbd.dev, domid);
235 continue;
236 }
238 snprintf(ooreq, sizeof(ooreq), "%s%soo_req", sys_prefix, stat_prefix);
239 if((read_attributes_vbd(dp->d_name, ooreq, buf, 256)<=0)
240 || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1))
241 {
242 continue;
243 }
245 snprintf(rdreq, sizeof(rdreq),"%s%srd_req", sys_prefix, stat_prefix);
246 if((read_attributes_vbd(dp->d_name, rdreq, buf, 256)<=0)
247 || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1))
248 {
249 continue;
250 }
252 snprintf(wrreq, sizeof(wrreq),"%s%swr_req", sys_prefix, stat_prefix);
253 if((read_attributes_vbd(dp->d_name, wrreq, buf, 256)<=0)
254 || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1))
255 {
256 continue;
257 }
259 if (domain->vbds == NULL) {
260 domain->num_vbds = 1;
261 domain->vbds = malloc(sizeof(xenstat_vbd));
262 } else {
263 domain->num_vbds++;
264 domain->vbds = realloc(domain->vbds,
265 domain->num_vbds *
266 sizeof(xenstat_vbd));
267 }
268 if (domain->vbds == NULL)
269 return 0;
270 domain->vbds[domain->num_vbds - 1] = vbd;
271 }
273 return 1;
274 }
276 /* Free VBD information in handle */
277 void xenstat_uninit_vbds(xenstat_handle * handle)
278 {
279 struct priv_data *priv = get_priv_data(handle);
280 if (priv != NULL && priv->sysfsvbd != NULL)
281 closedir(priv->sysfsvbd);
282 }