ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.38
Committed: Fri Oct 24 17:46:44 2003 UTC (20 years, 6 months ago) by ats
Content type: text/plain
Branch: MAIN
Changes since 1.37: +20 -11 lines
Log Message:
Support disk IO statistics on Linux 2.6.
Remove a couple of unused variables.

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