ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.24
Committed: Tue Oct 7 19:58:37 2003 UTC (20 years, 7 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.23: +0 -1 lines
Log Message:
Don't free stats.dinfo. If it used to store state between calls of
getdevs it probably doesn't make sense to free it at the end of the
first call of the function :)

This follows Adam's last commit on this bit of which made sure we
didn't reinitialise stats.dinfo every time round the loop.

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    
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 }