ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.25
Committed: Tue Oct 7 20:32:50 2003 UTC (20 years, 7 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.24: +1 -0 lines
Log Message:
Further following of the manpage:

"getdevs() expects the statinfo structure to be allocated, and it also
expects the dinfo subelement to be allocated and zeroed prior to the
first invocation of getdevs()."

This finally makes saider work on FreeBSD.

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2003 i-scream
5 *
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 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "statgrab.h"
29
30 #ifdef SOLARIS
31 #include <sys/mnttab.h>
32 #include <sys/statvfs.h>
33 #include <kstat.h>
34 #include <sys/types.h>
35 #include <dirent.h>
36 #include <limits.h>
37 #include <unistd.h>
38 #define VALID_FS_TYPES {"ufs", "tmpfs"}
39 #endif
40
41 #ifdef LINUX
42 #include <sys/vfs.h>
43 #include <mntent.h>
44 #include "tools.h"
45 #define VALID_FS_TYPES {"ext2", "ext3", "xfs", "reiserfs", "vfat", "tmpfs"}
46 #endif
47
48 #ifdef FREEBSD
49 #include <sys/param.h>
50 #include <sys/ucred.h>
51 #include <sys/mount.h>
52 #include <sys/dkstat.h>
53 #include <devstat.h>
54 #define VALID_FS_TYPES {"ufs", "mfs"}
55 #endif
56 #define START_VAL 1
57
58 /* 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 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 #if defined(LINUX) || defined (SOLARIS)
112 FILE *f;
113 #endif
114
115 disk_stat_t *disk_ptr;
116
117 #ifdef SOLARIS
118 struct mnttab mp;
119 struct statvfs fs;
120 #endif
121 #ifdef LINUX
122 struct mntent *mp;
123 struct statfs fs;
124 #endif
125 #ifdef FREEBSD
126 int nummnt;
127 struct statfs *mp;
128 #endif
129
130 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 #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 #ifdef LINUX
154 if ((f=setmntent("/etc/mtab", "r" ))==NULL){
155 return NULL;
156 }
157
158 while((mp=getmntent(f))){
159 if((statfs(mp->mnt_dir, &fs)) !=0){
160 continue;
161 }
162
163 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 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 #endif
188
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 #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 #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 /* 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 * 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 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 #endif
272 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 #if defined(LINUX) || defined(SOLARIS)
280 fclose(f);
281 #endif
282
283 return disk_stats;
284
285 }
286 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 #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 f_ptr=file_lines+x;
329 }
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 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 static int num_diskio=0;
448
449 #ifdef LINUX
450 typedef struct {
451 int major;
452 int minor;
453 } partition;
454 #endif
455
456 diskio_stat_t *get_diskio_stats(int *entries){
457
458 static int sizeof_diskio_stats=0;
459 diskio_stat_t *diskio_stats_ptr;
460
461 #ifdef SOLARIS
462 kstat_ctl_t *kc;
463 kstat_t *ksp;
464 kstat_io_t kios;
465 #endif
466 #ifdef LINUX
467 FILE *f;
468 char *line_ptr;
469 int major, minor;
470 char dev_letter;
471 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 #endif
477 #ifdef FREEBSD
478 static struct statinfo stats;
479 static int stats_init = 0;
480 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 num_diskio=0;
487
488 #ifdef FREEBSD
489 if (!stats_init) {
490 stats.dinfo=malloc(sizeof(struct devinfo));
491 bzero(stats.dinfo, sizeof(struct devinfo));
492 if(stats.dinfo==NULL) return NULL;
493 stats_init = 1;
494 }
495 if ((getdevs(&stats)) < 0) return NULL;
496 /* Not aware of a get all devices, so i said 999. If we ever
497 * find a machine with more than 999 disks, then i'll change
498 * this number :)
499 */
500 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;
501
502 for(counter=0;counter<stats.dinfo->numdevs;counter++){
503 dev_ptr=&stats.dinfo->devices[dev_sel[counter].position];
504
505 /* Throw away devices that have done nothing, ever.. Eg "odd"
506 * devices.. like mem, proc.. and also doesn't report floppy
507 * drives etc unless they are doing stuff :)
508 */
509 if((dev_ptr->bytes_read==0) && (dev_ptr->bytes_written==0)) continue;
510 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
511 return NULL;
512 }
513 diskio_stats_ptr=diskio_stats+num_diskio;
514
515 diskio_stats_ptr->read_bytes=dev_ptr->bytes_read;
516 diskio_stats_ptr->write_bytes=dev_ptr->bytes_written;
517 if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
518 asprintf((&diskio_stats_ptr->disk_name), "%s%d", dev_ptr->device_name, dev_ptr->unit_number);
519 diskio_stats_ptr->systime=time(NULL);
520
521 num_diskio++;
522 }
523 free(dev_sel);
524
525 #endif
526 #ifdef SOLARIS
527 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 /* We dont want metadevices appearins as num_diskio */
536 if(strcmp(ksp->ks_module, "md")==0) continue;
537 if((kstat_read(kc, ksp, &kios))==-1){
538 }
539
540 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
541 kstat_close(kc);
542 return NULL;
543 }
544 diskio_stats_ptr=diskio_stats+num_diskio;
545
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 diskio_stats_ptr->disk_name=drive_map(ksp->ks_name);
553 diskio_stats_ptr->systime=time(NULL);
554 num_diskio++;
555 }
556 }
557
558 kstat_close(kc);
559 #endif
560
561 #ifdef LINUX
562 num_diskio = 0;
563 n = 0;
564
565 /* 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
568 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 }
605
606 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
615 n++;
616 }
617
618 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
640 /* 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 case 22:
651 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 break;
662 case 9:
663 case 43:
664 break;
665 default:
666 minor *= 16;
667 break;
668 }
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 }
682 }
683
684 num_diskio = n;
685 out:
686 if (f != NULL) fclose(f);
687
688 #endif
689 *entries=num_diskio;
690
691 return diskio_stats;
692 }
693
694 diskio_stat_t *get_diskio_stats_diff(int *entries){
695 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
756 *entries=sizeof_diskio_stats_diff;
757 return diskio_stats_diff;
758 }