ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.22
Committed: Fri Sep 26 16:33:51 2003 UTC (20 years, 7 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.21: +150 -1 lines
Log Message:
Added drive mapping for solaris from the old sunos names, to the more
modern solaris names.

E.g.

ssd0 to c0t0d0s0

This is rather more useful :)

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     }
329     f_ptr++;
330     }
331     f_ptr = NULL;
332     fclose(f);
333    
334     dsk = opendir("/dev/dsk");
335     if (dsk == NULL){
336     free(file_lines);
337     return NULL;
338     }
339    
340     while((dsk_ent = readdir(dsk)) != NULL){
341     snprintf(link_path, sizeof(link_path), "/dev/dsk/%s", dsk_ent->d_name);
342     /* Ignore the non symlinks, e.g. ".." and "." */
343     if((readlink(link_path, linkpointer, PATH_MAX)) == -1) continue;
344     /* We are only intrested in the string past the ../../devices/ part */
345     p = strstr(linkpointer, "devices");
346     p+=8;
347    
348     /* We are not intrested in the :a etc slices */
349     q = strrchr(p, ':');
350     *q = '\0';
351    
352     /* char *p should not contain the info we need to look up in the
353     * path_to_inst file.
354     */
355    
356     for(f_ptr = file_lines; f_ptr != NULL; f_ptr++){
357     r = strstr(f_ptr->line, p);
358     if (r != NULL) break;
359     }
360    
361     if(r == NULL){
362     free(file_lines);
363     closedir(dsk);
364     return NULL;
365     }
366    
367     /* f_ptr should be pointing to the line of path_to_inst we are intrested in now */
368    
369     sscanf(r, "%*s %d \"%50s", &dev_num, dev_name);
370     q = strrchr(dev_name, '"');
371     if (q == NULL){
372     free(file_lines);
373     closedir(dsk);
374     return NULL;
375     }
376     *q = '\0';
377    
378     /* Nasty... Add the number to the end of the string.. This means
379     * dev_name now contains the sunos name.. E.g. ssd1
380     */
381     snprintf(dev_name, 50, "%s%d", dev_name, dev_num);
382     if (disk_mapping == NULL){
383     disk_mapping = malloc(sizeof(disk_mapping_t));
384     d_ptr = disk_mapping;
385     }else{
386     d_ptr->next = malloc(sizeof(disk_mapping_t));
387     d_ptr = d_ptr->next;
388     }
389    
390     if (d_ptr == NULL){
391     free(file_lines);
392     closedir(dsk);
393     return NULL;
394     }
395    
396     if( ((d_ptr->sunos_name = strdup(dev_name)) == NULL) ||
397     ((d_ptr->solaris_name = strdup(dsk_ent->d_name))==NULL) ){
398     free(file_lines);
399     closedir(dsk);
400     return NULL;
401     }
402     }
403     free(file_lines);
404     closedir(dsk);
405     }
406    
407     for(d_ptr = disk_mapping; d_ptr !=NULL; d_ptr=d_ptr->next){
408     if(!strcmp(sunos_name, d_ptr->sunos_name)){
409     return (strdup(d_ptr->solaris_name));
410     }
411     }
412    
413     /* If we really fail to find it.. Return the original name back */
414     return strdup(sunos_name);
415     }
416    
417     #endif
418    
419 pajs 1.4 diskio_stat_t *diskio_stat_malloc(int needed_entries, int *cur_entries, diskio_stat_t *diskio_stats){
420    
421     if(diskio_stats==NULL){
422    
423     if((diskio_stats=malloc(needed_entries * sizeof(diskio_stat_t)))==NULL){
424     return NULL;
425     }
426     diskio_stat_init(0, needed_entries, diskio_stats);
427     *cur_entries=needed_entries;
428    
429     return diskio_stats;
430     }
431    
432    
433     if(*cur_entries<needed_entries){
434     diskio_stats=realloc(diskio_stats, (sizeof(diskio_stat_t)*needed_entries));
435     if(diskio_stats==NULL){
436     return NULL;
437     }
438     diskio_stat_init(*cur_entries, needed_entries, diskio_stats);
439     *cur_entries=needed_entries;
440     }
441    
442     return diskio_stats;
443     }
444    
445     static diskio_stat_t *diskio_stats=NULL;
446 pajs 1.5 static int num_diskio=0;
447 pajs 1.4
448 ats 1.20 #ifdef LINUX
449     typedef struct {
450     int major;
451     int minor;
452     } partition;
453     #endif
454    
455 tdb 1.3 diskio_stat_t *get_diskio_stats(int *entries){
456 pajs 1.2
457 pajs 1.4 static int sizeof_diskio_stats=0;
458     diskio_stat_t *diskio_stats_ptr;
459    
460 pajs 1.10 #ifdef SOLARIS
461 pajs 1.4 kstat_ctl_t *kc;
462     kstat_t *ksp;
463     kstat_io_t kios;
464 pajs 1.10 #endif
465     #ifdef LINUX
466     FILE *f;
467     char *line_ptr;
468     int major, minor;
469     char dev_letter;
470 ats 1.20 int has_pp_stats = 1;
471     static partition *parts = NULL;
472     static int alloc_parts = 0;
473     int i, n;
474     time_t now;
475 pajs 1.10 #endif
476 pajs 1.17 #ifdef FREEBSD
477 ats 1.21 static struct statinfo stats;
478     static int stats_init = 0;
479 pajs 1.17 int counter;
480     struct device_selection *dev_sel = NULL;
481     int n_selected, n_selections;
482     long sel_gen;
483     struct devstat *dev_ptr;
484     #endif
485 pajs 1.10 num_diskio=0;
486 pajs 1.4
487 pajs 1.17 #ifdef FREEBSD
488 ats 1.21 if (!stats_init) {
489     stats.dinfo=malloc(sizeof(struct devinfo));
490     if(stats.dinfo==NULL) return NULL;
491     stats_init = 1;
492     }
493 pajs 1.17 if ((getdevs(&stats)) < 0) return NULL;
494     /* Not aware of a get all devices, so i said 999. If we ever
495     * find a machine with more than 999 disks, then i'll change
496     * this number :)
497     */
498     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;
499    
500     for(counter=0;counter<stats.dinfo->numdevs;counter++){
501     dev_ptr=&stats.dinfo->devices[dev_sel[counter].position];
502    
503     /* Throw away devices that have done nothing, ever.. Eg "odd"
504     * devices.. like mem, proc.. and also doesn't report floppy
505     * drives etc unless they are doing stuff :)
506     */
507     if((dev_ptr->bytes_read==0) && (dev_ptr->bytes_written==0)) continue;
508     if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
509     return NULL;
510     }
511     diskio_stats_ptr=diskio_stats+num_diskio;
512    
513     diskio_stats_ptr->read_bytes=dev_ptr->bytes_read;
514     diskio_stats_ptr->write_bytes=dev_ptr->bytes_written;
515     if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
516     asprintf((&diskio_stats_ptr->disk_name), "%s%d", dev_ptr->device_name, dev_ptr->unit_number);
517     diskio_stats_ptr->systime=time(NULL);
518    
519     num_diskio++;
520     }
521     free(dev_sel);
522     free(stats.dinfo);
523    
524     #endif
525 pajs 1.10 #ifdef SOLARIS
526 pajs 1.4 if ((kc = kstat_open()) == NULL) {
527     return NULL;
528     }
529    
530     for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
531     if (!strcmp(ksp->ks_class, "disk")) {
532    
533     if(ksp->ks_type != KSTAT_TYPE_IO) continue;
534 pajs 1.5 /* We dont want metadevices appearins as num_diskio */
535 pajs 1.4 if(strcmp(ksp->ks_module, "md")==0) continue;
536     if((kstat_read(kc, ksp, &kios))==-1){
537     }
538    
539 pajs 1.5 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
540 pajs 1.4 kstat_close(kc);
541     return NULL;
542     }
543 pajs 1.5 diskio_stats_ptr=diskio_stats+num_diskio;
544 pajs 1.4
545     diskio_stats_ptr->read_bytes=kios.nread;
546    
547     diskio_stats_ptr->write_bytes=kios.nwritten;
548    
549     if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
550    
551 pajs 1.22 diskio_stats_ptr->disk_name=drive_map(ksp->ks_name);
552 pajs 1.14 diskio_stats_ptr->systime=time(NULL);
553 pajs 1.5 num_diskio++;
554 pajs 1.4 }
555     }
556    
557     kstat_close(kc);
558 pajs 1.10 #endif
559 pajs 1.4
560 pajs 1.10 #ifdef LINUX
561 ats 1.20 num_diskio = 0;
562     n = 0;
563 pajs 1.10
564 ats 1.20 /* Read /proc/partitions to find what devices exist. Recent 2.4 kernels
565     have statistics in here too, so we can use those directly. */
566 pajs 1.10
567 ats 1.20 f = fopen("/proc/partitions", "r");
568     if (f == NULL) goto out;
569     now = time(NULL);
570    
571     while ((line_ptr = f_read_line(f, "")) != NULL) {
572     char name[20];
573     char *s;
574     long long rsect, wsect;
575    
576     int nr = sscanf(line_ptr,
577     " %d %d %*d %19s %*d %*d %lld %*d %*d %*d %lld",
578     &major, &minor, name, &rsect, &wsect);
579     if (nr < 3) continue;
580     if (nr < 5) {
581     has_pp_stats = 0;
582     rsect = 0;
583     wsect = 0;
584     }
585    
586     /* Skip device names ending in numbers, since they're
587     partitions. */
588     s = name;
589     while (*s != '\0') s++;
590     --s;
591     if (*s >= '0' && *s <= '9') continue;
592    
593     diskio_stats = diskio_stat_malloc(n + 1, &sizeof_diskio_stats,
594     diskio_stats);
595     if (diskio_stats == NULL) goto out;
596     if (n >= alloc_parts) {
597     alloc_parts += 16;
598     parts = realloc(parts, alloc_parts * sizeof *parts);
599     if (parts == NULL) {
600     alloc_parts = 0;
601     goto out;
602     }
603 pajs 1.11 }
604 pajs 1.12
605 ats 1.20 if (diskio_stats[n].disk_name != NULL)
606     free(diskio_stats[n].disk_name);
607     diskio_stats[n].disk_name = strdup(name);
608     diskio_stats[n].read_bytes = rsect * 512;
609     diskio_stats[n].write_bytes = wsect * 512;
610     diskio_stats[n].systime = now;
611     parts[n].major = major;
612     parts[n].minor = minor;
613 pajs 1.10
614 ats 1.20 n++;
615     }
616 pajs 1.10
617 ats 1.20 if (!has_pp_stats) {
618     /* This is an older kernel without stats in /proc/partitions.
619     Read what we can from /proc/stat instead. */
620    
621     f = fopen("/proc/stat", "r");
622     if (f == NULL) goto out;
623     now = time(NULL);
624    
625     line_ptr = f_read_line(f, "disk_io:");
626     if (line_ptr == NULL) goto out;
627    
628     while((line_ptr=strchr(line_ptr, ' '))!=NULL){
629     long long rsect, wsect;
630    
631     if (*++line_ptr == '\0') break;
632    
633     if((sscanf(line_ptr,
634     "(%d,%d):(%*d, %*d, %lld, %*d, %lld)",
635     &major, &minor, &rsect, &wsect)) != 4) {
636     continue;
637     }
638 pajs 1.10
639 ats 1.20 /* Find the corresponding device from earlier.
640     Just to add to the fun, "minor" is actually the disk
641     number, not the device minor, so we need to figure
642     out the real minor number based on the major!
643     This list is not exhaustive; if you're running
644     an older kernel you probably don't have fancy
645     I2O hardware anyway... */
646     switch (major) {
647     case 3:
648     case 21:
649 pajs 1.10 case 22:
650 ats 1.20 case 33:
651     case 34:
652     case 36:
653     case 56:
654     case 57:
655     case 88:
656     case 89:
657     case 90:
658     case 91:
659     minor *= 64;
660 pajs 1.11 break;
661 ats 1.20 case 9:
662     case 43:
663 pajs 1.11 break;
664 pajs 1.10 default:
665 ats 1.20 minor *= 16;
666 pajs 1.11 break;
667 ats 1.20 }
668     for (i = 0; i < n; i++) {
669     if (major == parts[i].major
670     && minor == parts[i].minor)
671     break;
672     }
673     if (i == n) continue;
674    
675     /* We read the number of blocks. Blocks are stored in
676     512 bytes */
677     diskio_stats[i].read_bytes = rsect * 512;
678     diskio_stats[i].write_bytes = wsect * 512;
679     diskio_stats[i].systime = now;
680 pajs 1.10 }
681     }
682 pajs 1.16
683 ats 1.20 num_diskio = n;
684     out:
685     if (f != NULL) fclose(f);
686 pajs 1.10
687     #endif
688 pajs 1.5 *entries=num_diskio;
689 pajs 1.4
690     return diskio_stats;
691 pajs 1.5 }
692    
693 pajs 1.6 diskio_stat_t *get_diskio_stats_diff(int *entries){
694 pajs 1.5 static diskio_stat_t *diskio_stats_diff=NULL;
695     static int sizeof_diskio_stats_diff=0;
696     diskio_stat_t *diskio_stats_diff_ptr, *diskio_stats_ptr;
697     int disks, x, y;
698    
699     if(diskio_stats==NULL){
700     diskio_stats_ptr=get_diskio_stats(&disks);
701     *entries=disks;
702     return diskio_stats_ptr;
703     }
704    
705     diskio_stats_diff=diskio_stat_malloc(num_diskio, &sizeof_diskio_stats_diff, diskio_stats_diff);
706     if(diskio_stats_diff==NULL){
707     return NULL;
708     }
709    
710     diskio_stats_diff_ptr=diskio_stats_diff;
711     diskio_stats_ptr=diskio_stats;
712    
713     for(disks=0;disks<num_diskio;disks++){
714     if(diskio_stats_diff_ptr->disk_name!=NULL){
715     free(diskio_stats_diff_ptr->disk_name);
716     }
717     diskio_stats_diff_ptr->disk_name=strdup(diskio_stats_ptr->disk_name);
718     diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes;
719     diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes;
720     diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime;
721    
722     diskio_stats_diff_ptr++;
723     diskio_stats_ptr++;
724     }
725    
726     diskio_stats_ptr=get_diskio_stats(&disks);
727     diskio_stats_diff_ptr=diskio_stats_diff;
728    
729     for(x=0;x<sizeof_diskio_stats_diff;x++){
730    
731     if((strcmp(diskio_stats_diff_ptr->disk_name, diskio_stats_ptr->disk_name))==0){
732     diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes-diskio_stats_diff_ptr->read_bytes;
733     diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes-diskio_stats_diff_ptr->write_bytes;
734     diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime-diskio_stats_diff_ptr->systime;
735     }else{
736     diskio_stats_ptr=diskio_stats;
737     for(y=0;y<disks;y++){
738     if((strcmp(diskio_stats_diff_ptr->disk_name, diskio_stats_ptr->disk_name))==0){
739     diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes-diskio_stats_diff_ptr->read_bytes;
740     diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes-diskio_stats_diff_ptr->write_bytes;
741     diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime-diskio_stats_diff_ptr->systime;
742    
743     break;
744     }
745    
746     diskio_stats_ptr++;
747     }
748     }
749    
750     diskio_stats_ptr++;
751     diskio_stats_diff_ptr++;
752    
753     }
754 pajs 1.8
755     *entries=sizeof_diskio_stats_diff;
756 pajs 1.5 return diskio_stats_diff;
757 pajs 1.2 }