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

# 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 }
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 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 static int num_diskio=0;
447
448 #ifdef LINUX
449 typedef struct {
450 int major;
451 int minor;
452 } partition;
453 #endif
454
455 diskio_stat_t *get_diskio_stats(int *entries){
456
457 static int sizeof_diskio_stats=0;
458 diskio_stat_t *diskio_stats_ptr;
459
460 #ifdef SOLARIS
461 kstat_ctl_t *kc;
462 kstat_t *ksp;
463 kstat_io_t kios;
464 #endif
465 #ifdef LINUX
466 FILE *f;
467 char *line_ptr;
468 int major, minor;
469 char dev_letter;
470 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 #endif
476 #ifdef FREEBSD
477 static struct statinfo stats;
478 static int stats_init = 0;
479 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 num_diskio=0;
486
487 #ifdef FREEBSD
488 if (!stats_init) {
489 stats.dinfo=malloc(sizeof(struct devinfo));
490 if(stats.dinfo==NULL) return NULL;
491 stats_init = 1;
492 }
493 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 #ifdef SOLARIS
526 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 /* We dont want metadevices appearins as num_diskio */
535 if(strcmp(ksp->ks_module, "md")==0) continue;
536 if((kstat_read(kc, ksp, &kios))==-1){
537 }
538
539 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
540 kstat_close(kc);
541 return NULL;
542 }
543 diskio_stats_ptr=diskio_stats+num_diskio;
544
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 diskio_stats_ptr->disk_name=drive_map(ksp->ks_name);
552 diskio_stats_ptr->systime=time(NULL);
553 num_diskio++;
554 }
555 }
556
557 kstat_close(kc);
558 #endif
559
560 #ifdef LINUX
561 num_diskio = 0;
562 n = 0;
563
564 /* 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
567 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 }
604
605 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
614 n++;
615 }
616
617 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
639 /* 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 case 22:
650 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 break;
661 case 9:
662 case 43:
663 break;
664 default:
665 minor *= 16;
666 break;
667 }
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 }
681 }
682
683 num_diskio = n;
684 out:
685 if (f != NULL) fclose(f);
686
687 #endif
688 *entries=num_diskio;
689
690 return diskio_stats;
691 }
692
693 diskio_stat_t *get_diskio_stats_diff(int *entries){
694 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
755 *entries=sizeof_diskio_stats_diff;
756 return diskio_stats_diff;
757 }