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

# 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 if(stats.dinfo==NULL) return NULL;
492 stats_init = 1;
493 }
494 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 #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 }