ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.39
Committed: Mon Nov 10 21:07:04 2003 UTC (20 years, 6 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.38: +10 -2 lines
Log Message:
Add support for cygwin. This is a bit limited, there's a few things that
can't be retrieved on cygwin such as load averages, diskio, network io,
and process stats. The package compiles and runs, and both saidar and
statgrab work.

Taken from a patch submitted by Ron Arts <raarts@netland.nl>. Thanks Ron!

File Contents

# User Rev Content
1 pajs 1.1 /*
2     * i-scream central monitoring system
3 tdb 1.18 * http://www.i-scream.org
4     * Copyright (C) 2000-2003 i-scream
5 pajs 1.1 *
6     * This program is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU General Public License
8     * as published by the Free Software Foundation; either version 2
9     * of the License, or (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19     */
20    
21     #ifdef HAVE_CONFIG_H
22     #include "config.h"
23     #endif
24    
25 pajs 1.17 #include <stdio.h>
26 pajs 1.1 #include <stdlib.h>
27     #include <string.h>
28 tdb 1.7 #include "statgrab.h"
29 pajs 1.1
30     #ifdef SOLARIS
31     #include <sys/mnttab.h>
32     #include <sys/statvfs.h>
33 pajs 1.4 #include <kstat.h>
34 pajs 1.1 #define VALID_FS_TYPES {"ufs", "tmpfs"}
35     #endif
36    
37 pajs 1.9 #ifdef LINUX
38 ats 1.30 #include <time.h>
39 pajs 1.9 #include <sys/vfs.h>
40     #include <mntent.h>
41 pajs 1.10 #include "tools.h"
42 tdb 1.39 #ifdef CYGWIN
43     #define VALID_FS_TYPES {"user"}
44     #else
45 ats 1.32 #define VALID_FS_TYPES {"adfs", "affs", "befs", "bfs", "efs", "ext2", \
46     "ext3", "vxfs", "hfs", "hfsplus", "hpfs", "jffs", \
47     "jffs2", "minix", "msdos", "ntfs", "qnx4", "ramfs", \
48     "rootfs", "reiserfs", "sysv", "v7", "udf", "ufs", \
49     "umsdos", "vfat", "xfs", "jfs"}
50 pajs 1.9 #endif
51 tdb 1.39 #endif
52 pajs 1.9
53 ats 1.31 #ifdef ALLBSD
54 pajs 1.16 #include <sys/param.h>
55     #include <sys/ucred.h>
56     #include <sys/mount.h>
57 ats 1.31 #endif
58     #ifdef FREEBSD
59 pajs 1.17 #include <sys/dkstat.h>
60     #include <devstat.h>
61 ats 1.36 #define VALID_FS_TYPES {"hpfs", "msdosfs", "ntfs", "udf", "ext2fs", \
62     "ufs", "mfs"}
63 pajs 1.16 #endif
64 ats 1.34 #ifdef NETBSD
65     #include <sys/param.h>
66     #include <sys/sysctl.h>
67     #include <sys/disk.h>
68 ats 1.35 #define VALID_FS_TYPES {"ffs", "mfs", "msdos", "lfs", "adosfs", "ext2fs", \
69     "ntfs"}
70 ats 1.34 #endif
71 ats 1.31
72 pajs 1.1 #define START_VAL 1
73    
74     char *copy_string(char *orig_ptr, const char *newtext){
75    
76     /* Maybe free if not NULL, and strdup rather than realloc and strcpy? */
77     orig_ptr=realloc(orig_ptr, (1+strlen(newtext)));
78     if(orig_ptr==NULL){
79     return NULL;
80     }
81     strcpy(orig_ptr, newtext);
82    
83     return orig_ptr;
84     }
85    
86    
87     void init_disk_stat(int start, int end, disk_stat_t *disk_stats){
88    
89     for(disk_stats+=start; start<=end; start++){
90     disk_stats->device_name=NULL;
91     disk_stats->fs_type=NULL;
92     disk_stats->mnt_point=NULL;
93    
94     disk_stats++;
95     }
96     }
97    
98     disk_stat_t *get_disk_stats(int *entries){
99    
100     static disk_stat_t *disk_stats;
101     static int watermark=-1;
102    
103     char *fs_types[] = VALID_FS_TYPES;
104     int x, valid_type;
105     int num_disks=0;
106 pajs 1.16 #if defined(LINUX) || defined (SOLARIS)
107 pajs 1.1 FILE *f;
108 pajs 1.16 #endif
109 pajs 1.1
110     disk_stat_t *disk_ptr;
111    
112 pajs 1.9 #ifdef SOLARIS
113 tdb 1.13 struct mnttab mp;
114 pajs 1.9 struct statvfs fs;
115     #endif
116     #ifdef LINUX
117     struct mntent *mp;
118     struct statfs fs;
119     #endif
120 ats 1.31 #ifdef ALLBSD
121 pajs 1.16 int nummnt;
122     struct statfs *mp;
123     #endif
124 pajs 1.9
125 pajs 1.1 if(watermark==-1){
126     disk_stats=malloc(START_VAL * sizeof(disk_stat_t));
127     if(disk_stats==NULL){
128     return NULL;
129     }
130     watermark=START_VAL;
131     init_disk_stat(0, watermark-1, disk_stats);
132     }
133 ats 1.31 #ifdef ALLBSD
134 pajs 1.16 nummnt=getmntinfo(&mp , MNT_LOCAL);
135     if (nummnt<=0){
136     return NULL;
137     }
138     for(;nummnt--; mp++){
139     valid_type=0;
140     for(x=0;x<((sizeof(fs_types))/(sizeof(char*)));x++){
141     if(strcmp(mp->f_fstypename, fs_types[x]) ==0){
142     valid_type=1;
143     break;
144     }
145     }
146     #endif
147    
148 pajs 1.9 #ifdef LINUX
149     if ((f=setmntent("/etc/mtab", "r" ))==NULL){
150     return NULL;
151     }
152 pajs 1.1
153 pajs 1.9 while((mp=getmntent(f))){
154     if((statfs(mp->mnt_dir, &fs)) !=0){
155     continue;
156     }
157 pajs 1.1
158 pajs 1.9 valid_type=0;
159     for(x=0;x<((sizeof(fs_types))/(sizeof(char*)));x++){
160     if(strcmp(mp->mnt_type, fs_types[x]) ==0){
161     valid_type=1;
162     break;
163     }
164     }
165     #endif
166    
167     #ifdef SOLARIS
168 pajs 1.1 if ((f=fopen("/etc/mnttab", "r" ))==NULL){
169     return NULL;
170     }
171     while((getmntent(f, &mp)) == 0){
172     if ((statvfs(mp.mnt_mountp, &fs)) !=0){
173     continue;
174     }
175     valid_type=0;
176     for(x=0;x<((sizeof(fs_types))/(sizeof(char*)));x++){
177     if(strcmp(mp.mnt_fstype, fs_types[x]) ==0){
178     valid_type=1;
179     break;
180     }
181     }
182 pajs 1.9 #endif
183 pajs 1.1
184     if(valid_type){
185     if(num_disks>watermark-1){
186     disk_ptr=disk_stats;
187     if((disk_stats=realloc(disk_stats, (watermark*2 * sizeof(disk_stat_t))))==NULL){
188     disk_stats=disk_ptr;
189     return NULL;
190     }
191    
192     watermark=watermark*2;
193     init_disk_stat(num_disks, watermark-1, disk_stats);
194     }
195    
196     disk_ptr=disk_stats+num_disks;
197 ats 1.31 #ifdef ALLBSD
198 pajs 1.16 if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp->f_mntfromname))==NULL){
199     return NULL;
200     }
201    
202     if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp->f_fstypename))==NULL){
203     return NULL;
204     }
205    
206     if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp->f_mntonname))==NULL){
207     return NULL;
208     }
209    
210     disk_ptr->size = (long long)mp->f_bsize * (long long) mp->f_blocks;
211     disk_ptr->avail = (long long)mp->f_bsize * (long long) mp->f_bavail;
212     disk_ptr->used = (disk_ptr->size) - ((long long)mp->f_bsize * (long long)mp->f_bfree);
213    
214     disk_ptr->total_inodes=(long long)mp->f_files;
215     disk_ptr->free_inodes=(long long)mp->f_ffree;
216     /* Freebsd doesn't have a "available" inodes */
217     disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
218     #endif
219 pajs 1.9 #ifdef LINUX
220     if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp->mnt_fsname))==NULL){
221     return NULL;
222     }
223    
224     if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp->mnt_type))==NULL){
225     return NULL;
226     }
227    
228     if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp->mnt_dir))==NULL){
229     return NULL;
230     }
231     disk_ptr->size = (long long)fs.f_bsize * (long long)fs.f_blocks;
232     disk_ptr->avail = (long long)fs.f_bsize * (long long)fs.f_bavail;
233     disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_bsize * (long long)fs.f_bfree);
234    
235     disk_ptr->total_inodes=(long long)fs.f_files;
236     disk_ptr->free_inodes=(long long)fs.f_ffree;
237     /* Linux doesn't have a "available" inodes */
238     disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
239     #endif
240    
241     #ifdef SOLARIS
242 pajs 1.1 /* Memory leak in event of realloc failing */
243     /* Maybe make this char[bigenough] and do strncpy's and put a null in the end?
244 pajs 1.9 * Downside is its a bit hungry for a lot of mounts, as MNT_MAX_SIZE would prob
245     * be upwards of a k each
246     */
247 pajs 1.1 if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp.mnt_special))==NULL){
248     return NULL;
249     }
250    
251     if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp.mnt_fstype))==NULL){
252     return NULL;
253     }
254    
255     if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp.mnt_mountp))==NULL){
256     return NULL;
257     }
258    
259     disk_ptr->size = (long long)fs.f_frsize * (long long)fs.f_blocks;
260     disk_ptr->avail = (long long)fs.f_frsize * (long long)fs.f_bavail;
261     disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_frsize * (long long)fs.f_bfree);
262    
263     disk_ptr->total_inodes=(long long)fs.f_files;
264     disk_ptr->used_inodes=disk_ptr->total_inodes - (long long)fs.f_ffree;
265     disk_ptr->free_inodes=(long long)fs.f_favail;
266 pajs 1.9 #endif
267 pajs 1.1 num_disks++;
268     }
269     }
270    
271     *entries=num_disks;
272    
273 tdb 1.39 /* If this fails, there is very little i can do about it, so
274     I'll ignore it :) */
275     #if defined(LINUX)
276     endmntent(f);
277     #endif
278     #if defined(SOLARIS)
279 pajs 1.1 fclose(f);
280 pajs 1.16 #endif
281 pajs 1.1
282     return disk_stats;
283    
284     }
285 pajs 1.4 void diskio_stat_init(int start, int end, diskio_stat_t *diskio_stats){
286    
287     for(diskio_stats+=start; start<end; start++){
288     diskio_stats->disk_name=NULL;
289    
290     diskio_stats++;
291     }
292     }
293    
294     diskio_stat_t *diskio_stat_malloc(int needed_entries, int *cur_entries, diskio_stat_t *diskio_stats){
295    
296     if(diskio_stats==NULL){
297    
298     if((diskio_stats=malloc(needed_entries * sizeof(diskio_stat_t)))==NULL){
299     return NULL;
300     }
301     diskio_stat_init(0, needed_entries, diskio_stats);
302     *cur_entries=needed_entries;
303    
304     return diskio_stats;
305     }
306    
307    
308     if(*cur_entries<needed_entries){
309     diskio_stats=realloc(diskio_stats, (sizeof(diskio_stat_t)*needed_entries));
310     if(diskio_stats==NULL){
311     return NULL;
312     }
313     diskio_stat_init(*cur_entries, needed_entries, diskio_stats);
314     *cur_entries=needed_entries;
315     }
316    
317     return diskio_stats;
318     }
319    
320     static diskio_stat_t *diskio_stats=NULL;
321 pajs 1.5 static int num_diskio=0;
322 pajs 1.4
323 ats 1.20 #ifdef LINUX
324     typedef struct {
325     int major;
326     int minor;
327     } partition;
328     #endif
329    
330 tdb 1.3 diskio_stat_t *get_diskio_stats(int *entries){
331 pajs 1.2
332 pajs 1.4 static int sizeof_diskio_stats=0;
333 ats 1.38 #ifndef LINUX
334 pajs 1.4 diskio_stat_t *diskio_stats_ptr;
335 ats 1.38 #endif
336 pajs 1.4
337 pajs 1.10 #ifdef SOLARIS
338 pajs 1.4 kstat_ctl_t *kc;
339     kstat_t *ksp;
340     kstat_io_t kios;
341 pajs 1.10 #endif
342     #ifdef LINUX
343     FILE *f;
344     char *line_ptr;
345     int major, minor;
346 ats 1.20 int has_pp_stats = 1;
347     static partition *parts = NULL;
348     static int alloc_parts = 0;
349     int i, n;
350     time_t now;
351 ats 1.38 const char *format;
352 pajs 1.10 #endif
353 pajs 1.17 #ifdef FREEBSD
354 ats 1.21 static struct statinfo stats;
355     static int stats_init = 0;
356 pajs 1.17 int counter;
357     struct device_selection *dev_sel = NULL;
358     int n_selected, n_selections;
359     long sel_gen;
360     struct devstat *dev_ptr;
361 ats 1.31 #endif
362     #ifdef NETBSD
363 ats 1.34 struct disk_sysctl *stats;
364     int num_disks, i;
365     int mib[3];
366     size_t size;
367 pajs 1.17 #endif
368 ats 1.34
369 pajs 1.10 num_diskio=0;
370 ats 1.34
371     #ifdef NETBSD
372     mib[0] = CTL_HW;
373     mib[1] = HW_DISKSTATS;
374     mib[2] = sizeof(struct disk_sysctl);
375    
376     if (sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
377     return NULL;
378     }
379     num_disks = size / sizeof(struct disk_sysctl);
380    
381     stats = malloc(size);
382     if (stats == NULL) {
383     return NULL;
384     }
385    
386     if (sysctl(mib, 3, stats, &size, NULL, 0) < 0) {
387     return NULL;
388     }
389    
390     for (i = 0; i < num_disks; i++) {
391     u_int64_t rbytes, wbytes;
392    
393     #ifdef HAVE_DK_RBYTES
394     rbytes = stats[i].dk_rbytes;
395     wbytes = stats[i].dk_wbytes;
396     #else
397 ats 1.37 /* Before 1.7, NetBSD merged reads and writes. */
398 ats 1.34 rbytes = wbytes = stats[i].dk_bytes;
399     #endif
400    
401     /* Don't keep stats for disks that have never been used. */
402     if (rbytes == 0 && wbytes == 0) {
403     continue;
404     }
405    
406     diskio_stats = diskio_stat_malloc(num_diskio + 1,
407     &sizeof_diskio_stats,
408     diskio_stats);
409     if (diskio_stats == NULL) {
410     return NULL;
411     }
412     diskio_stats_ptr = diskio_stats + num_diskio;
413    
414     diskio_stats_ptr->read_bytes = rbytes;
415     diskio_stats_ptr->write_bytes = wbytes;
416     if (diskio_stats_ptr->disk_name != NULL) {
417     free(diskio_stats_ptr->disk_name);
418     }
419     diskio_stats_ptr->disk_name = strdup(stats[i].dk_name);
420     diskio_stats_ptr->systime = time(NULL);
421    
422     num_diskio++;
423     }
424    
425     free(stats);
426     #endif
427 pajs 1.4
428 pajs 1.17 #ifdef FREEBSD
429 ats 1.21 if (!stats_init) {
430     stats.dinfo=malloc(sizeof(struct devinfo));
431 ats 1.33 if(stats.dinfo==NULL) return NULL;
432 tdb 1.25 bzero(stats.dinfo, sizeof(struct devinfo));
433 ats 1.21 stats_init = 1;
434     }
435 pajs 1.28 #ifdef FREEBSD5
436     if ((devstat_getdevs(NULL, &stats)) < 0) return NULL;
437 ats 1.29 /* Not aware of a get all devices, so i said 999. If we ever
438     * find a machine with more than 999 disks, then i'll change
439     * this number :)
440     */
441 pajs 1.28 if (devstat_selectdevs(&dev_sel, &n_selected, &n_selections, &sel_gen, stats.dinfo->generation, stats.dinfo->devices, stats.dinfo->numdevs, NULL, 0, NULL, 0, DS_SELECT_ONLY, 999, 1) < 0) return NULL;
442     #else
443 pajs 1.17 if ((getdevs(&stats)) < 0) return NULL;
444     /* Not aware of a get all devices, so i said 999. If we ever
445     * find a machine with more than 999 disks, then i'll change
446     * this number :)
447     */
448     if (selectdevs(&dev_sel, &n_selected, &n_selections, &sel_gen, stats.dinfo->generation, stats.dinfo->devices, stats.dinfo->numdevs, NULL, 0, NULL, 0, DS_SELECT_ONLY, 999, 1) < 0) return NULL;
449 pajs 1.27 #endif
450 pajs 1.17
451     for(counter=0;counter<stats.dinfo->numdevs;counter++){
452     dev_ptr=&stats.dinfo->devices[dev_sel[counter].position];
453    
454     /* Throw away devices that have done nothing, ever.. Eg "odd"
455     * devices.. like mem, proc.. and also doesn't report floppy
456     * drives etc unless they are doing stuff :)
457     */
458 pajs 1.27 #ifdef FREEBSD5
459     if((dev_ptr->bytes[DEVSTAT_READ]==0) && (dev_ptr->bytes[DEVSTAT_WRITE]==0)) continue;
460     #else
461 pajs 1.17 if((dev_ptr->bytes_read==0) && (dev_ptr->bytes_written==0)) continue;
462 pajs 1.27 #endif
463 pajs 1.17 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
464     return NULL;
465     }
466     diskio_stats_ptr=diskio_stats+num_diskio;
467 pajs 1.27
468     #ifdef FREEBSD5
469     diskio_stats_ptr->read_bytes=dev_ptr->bytes[DEVSTAT_READ];
470     diskio_stats_ptr->write_bytes=dev_ptr->bytes[DEVSTAT_WRITE];
471     #else
472 pajs 1.17 diskio_stats_ptr->read_bytes=dev_ptr->bytes_read;
473     diskio_stats_ptr->write_bytes=dev_ptr->bytes_written;
474 pajs 1.27 #endif
475 pajs 1.17 if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
476     asprintf((&diskio_stats_ptr->disk_name), "%s%d", dev_ptr->device_name, dev_ptr->unit_number);
477     diskio_stats_ptr->systime=time(NULL);
478    
479     num_diskio++;
480     }
481     free(dev_sel);
482    
483     #endif
484 pajs 1.10 #ifdef SOLARIS
485 pajs 1.4 if ((kc = kstat_open()) == NULL) {
486     return NULL;
487     }
488    
489     for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
490     if (!strcmp(ksp->ks_class, "disk")) {
491    
492     if(ksp->ks_type != KSTAT_TYPE_IO) continue;
493 pajs 1.5 /* We dont want metadevices appearins as num_diskio */
494 pajs 1.4 if(strcmp(ksp->ks_module, "md")==0) continue;
495     if((kstat_read(kc, ksp, &kios))==-1){
496     }
497    
498 pajs 1.5 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
499 pajs 1.4 kstat_close(kc);
500     return NULL;
501     }
502 pajs 1.5 diskio_stats_ptr=diskio_stats+num_diskio;
503 pajs 1.4
504     diskio_stats_ptr->read_bytes=kios.nread;
505    
506     diskio_stats_ptr->write_bytes=kios.nwritten;
507    
508     if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
509    
510 tdb 1.26 diskio_stats_ptr->disk_name=strdup(ksp->ks_name);
511 pajs 1.14 diskio_stats_ptr->systime=time(NULL);
512 pajs 1.5 num_diskio++;
513 pajs 1.4 }
514     }
515    
516     kstat_close(kc);
517 pajs 1.10 #endif
518 pajs 1.4
519 pajs 1.10 #ifdef LINUX
520 ats 1.20 num_diskio = 0;
521     n = 0;
522 pajs 1.10
523 ats 1.20 /* Read /proc/partitions to find what devices exist. Recent 2.4 kernels
524 ats 1.38 have statistics in here too, so we can use those directly.
525     2.6 kernels have /proc/diskstats instead with almost (but not quite)
526     the same format. */
527    
528     f = fopen("/proc/diskstats", "r");
529     format = " %d %d %19s %*d %*d %lld %*d %*d %*d %lld";
530     if (f == NULL) {
531     f = fopen("/proc/partitions", "r");
532     format = " %d %d %*d %19s %*d %*d %lld %*d %*d %*d %lld";
533     }
534 ats 1.20 if (f == NULL) goto out;
535     now = time(NULL);
536    
537     while ((line_ptr = f_read_line(f, "")) != NULL) {
538     char name[20];
539     char *s;
540     long long rsect, wsect;
541    
542 ats 1.38 int nr = sscanf(line_ptr, format,
543 ats 1.20 &major, &minor, name, &rsect, &wsect);
544     if (nr < 3) continue;
545    
546     /* Skip device names ending in numbers, since they're
547     partitions. */
548     s = name;
549     while (*s != '\0') s++;
550     --s;
551     if (*s >= '0' && *s <= '9') continue;
552 ats 1.38
553     if (nr < 5) {
554     has_pp_stats = 0;
555     rsect = 0;
556     wsect = 0;
557     }
558 ats 1.20
559     diskio_stats = diskio_stat_malloc(n + 1, &sizeof_diskio_stats,
560     diskio_stats);
561     if (diskio_stats == NULL) goto out;
562     if (n >= alloc_parts) {
563     alloc_parts += 16;
564     parts = realloc(parts, alloc_parts * sizeof *parts);
565     if (parts == NULL) {
566     alloc_parts = 0;
567     goto out;
568     }
569 pajs 1.11 }
570 pajs 1.12
571 ats 1.20 if (diskio_stats[n].disk_name != NULL)
572     free(diskio_stats[n].disk_name);
573     diskio_stats[n].disk_name = strdup(name);
574     diskio_stats[n].read_bytes = rsect * 512;
575     diskio_stats[n].write_bytes = wsect * 512;
576     diskio_stats[n].systime = now;
577     parts[n].major = major;
578     parts[n].minor = minor;
579 pajs 1.10
580 ats 1.20 n++;
581     }
582 pajs 1.10
583 ats 1.20 if (!has_pp_stats) {
584     /* This is an older kernel without stats in /proc/partitions.
585     Read what we can from /proc/stat instead. */
586    
587     f = fopen("/proc/stat", "r");
588     if (f == NULL) goto out;
589     now = time(NULL);
590    
591     line_ptr = f_read_line(f, "disk_io:");
592     if (line_ptr == NULL) goto out;
593    
594     while((line_ptr=strchr(line_ptr, ' '))!=NULL){
595     long long rsect, wsect;
596    
597     if (*++line_ptr == '\0') break;
598    
599     if((sscanf(line_ptr,
600     "(%d,%d):(%*d, %*d, %lld, %*d, %lld)",
601     &major, &minor, &rsect, &wsect)) != 4) {
602     continue;
603     }
604 pajs 1.10
605 ats 1.20 /* Find the corresponding device from earlier.
606     Just to add to the fun, "minor" is actually the disk
607     number, not the device minor, so we need to figure
608     out the real minor number based on the major!
609     This list is not exhaustive; if you're running
610     an older kernel you probably don't have fancy
611     I2O hardware anyway... */
612     switch (major) {
613     case 3:
614     case 21:
615 pajs 1.10 case 22:
616 ats 1.20 case 33:
617     case 34:
618     case 36:
619     case 56:
620     case 57:
621     case 88:
622     case 89:
623     case 90:
624     case 91:
625     minor *= 64;
626 pajs 1.11 break;
627 ats 1.20 case 9:
628     case 43:
629 pajs 1.11 break;
630 pajs 1.10 default:
631 ats 1.20 minor *= 16;
632 pajs 1.11 break;
633 ats 1.20 }
634     for (i = 0; i < n; i++) {
635     if (major == parts[i].major
636     && minor == parts[i].minor)
637     break;
638     }
639     if (i == n) continue;
640    
641     /* We read the number of blocks. Blocks are stored in
642     512 bytes */
643     diskio_stats[i].read_bytes = rsect * 512;
644     diskio_stats[i].write_bytes = wsect * 512;
645     diskio_stats[i].systime = now;
646 pajs 1.10 }
647     }
648 pajs 1.16
649 ats 1.20 num_diskio = n;
650     out:
651     if (f != NULL) fclose(f);
652 pajs 1.10
653     #endif
654 pajs 1.5 *entries=num_diskio;
655 pajs 1.4
656     return diskio_stats;
657 pajs 1.5 }
658    
659 pajs 1.6 diskio_stat_t *get_diskio_stats_diff(int *entries){
660 pajs 1.5 static diskio_stat_t *diskio_stats_diff=NULL;
661     static int sizeof_diskio_stats_diff=0;
662     diskio_stat_t *diskio_stats_diff_ptr, *diskio_stats_ptr;
663     int disks, x, y;
664    
665     if(diskio_stats==NULL){
666     diskio_stats_ptr=get_diskio_stats(&disks);
667     *entries=disks;
668     return diskio_stats_ptr;
669     }
670    
671     diskio_stats_diff=diskio_stat_malloc(num_diskio, &sizeof_diskio_stats_diff, diskio_stats_diff);
672     if(diskio_stats_diff==NULL){
673     return NULL;
674     }
675    
676     diskio_stats_diff_ptr=diskio_stats_diff;
677     diskio_stats_ptr=diskio_stats;
678    
679     for(disks=0;disks<num_diskio;disks++){
680     if(diskio_stats_diff_ptr->disk_name!=NULL){
681     free(diskio_stats_diff_ptr->disk_name);
682     }
683     diskio_stats_diff_ptr->disk_name=strdup(diskio_stats_ptr->disk_name);
684     diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes;
685     diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes;
686     diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime;
687    
688     diskio_stats_diff_ptr++;
689     diskio_stats_ptr++;
690     }
691    
692     diskio_stats_ptr=get_diskio_stats(&disks);
693     diskio_stats_diff_ptr=diskio_stats_diff;
694    
695     for(x=0;x<sizeof_diskio_stats_diff;x++){
696    
697     if((strcmp(diskio_stats_diff_ptr->disk_name, diskio_stats_ptr->disk_name))==0){
698     diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes-diskio_stats_diff_ptr->read_bytes;
699     diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes-diskio_stats_diff_ptr->write_bytes;
700     diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime-diskio_stats_diff_ptr->systime;
701     }else{
702     diskio_stats_ptr=diskio_stats;
703     for(y=0;y<disks;y++){
704     if((strcmp(diskio_stats_diff_ptr->disk_name, diskio_stats_ptr->disk_name))==0){
705     diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes-diskio_stats_diff_ptr->read_bytes;
706     diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes-diskio_stats_diff_ptr->write_bytes;
707     diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime-diskio_stats_diff_ptr->systime;
708    
709     break;
710     }
711    
712     diskio_stats_ptr++;
713     }
714     }
715    
716     diskio_stats_ptr++;
717     diskio_stats_diff_ptr++;
718    
719     }
720 pajs 1.8
721     *entries=sizeof_diskio_stats_diff;
722 pajs 1.5 return diskio_stats_diff;
723 pajs 1.2 }