ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.42
Committed: Wed Nov 12 01:36:19 2003 UTC (20 years, 6 months ago) by ats
Content type: text/plain
Branch: MAIN
Changes since 1.41: +4 -0 lines
Log Message:
Make libstatgrab functions return NULL for stats that can't be fetched
on cygwin.

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