ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.23
Committed: Fri Sep 26 22:30:48 2003 UTC (20 years, 7 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.22: +1 -0 lines
Log Message:
Bug fix on systems with large path_to_inst files.

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