ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.48
Committed: Fri Jan 16 15:54:54 2004 UTC (20 years, 4 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.47: +13 -12 lines
Log Message:
Alter the licensing of libstatgrab. The library part is now under the
LGPL, whilst the tools/examples are under the GPL. Both licenses are
included in the distribution (and are both now in CVS). Also made a
minor alteration to the webpage where it said everything was licensed
under the GPL.

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2004 i-scream
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 * 02111-1307 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include "statgrab.h"
31
32 #ifdef SOLARIS
33 #include <sys/mnttab.h>
34 #include <sys/statvfs.h>
35 #include <kstat.h>
36 #define VALID_FS_TYPES {"ufs", "tmpfs"}
37 #endif
38
39 #if defined(LINUX) || defined(CYGWIN)
40 #include <mntent.h>
41 #include <sys/vfs.h>
42 #include "tools.h"
43 #endif
44
45 #ifdef LINUX
46 #define VALID_FS_TYPES {"adfs", "affs", "befs", "bfs", "efs", "ext2", \
47 "ext3", "vxfs", "hfs", "hfsplus", "hpfs", "jffs", \
48 "jffs2", "minix", "msdos", "ntfs", "qnx4", "ramfs", \
49 "rootfs", "reiserfs", "sysv", "v7", "udf", "ufs", \
50 "umsdos", "vfat", "xfs", "jfs"}
51 #endif
52
53 #ifdef CYGWIN
54 #define VALID_FS_TYPES {"user"}
55 #endif
56
57 #ifdef ALLBSD
58 #include <sys/param.h>
59 #include <sys/ucred.h>
60 #include <sys/mount.h>
61 #endif
62 #ifdef FREEBSD
63 #include <sys/dkstat.h>
64 #include <devstat.h>
65 #define VALID_FS_TYPES {"hpfs", "msdosfs", "ntfs", "udf", "ext2fs", \
66 "ufs", "mfs"}
67 #endif
68 #ifdef NETBSD
69 #include <sys/param.h>
70 #include <sys/sysctl.h>
71 #include <sys/disk.h>
72 #define VALID_FS_TYPES {"ffs", "mfs", "msdos", "lfs", "adosfs", "ext2fs", \
73 "ntfs"}
74 #endif
75
76 #define START_VAL 1
77
78 char *copy_string(char *orig_ptr, const char *newtext){
79
80 /* Maybe free if not NULL, and strdup rather than realloc and strcpy? */
81 orig_ptr=realloc(orig_ptr, (1+strlen(newtext)));
82 if(orig_ptr==NULL){
83 return NULL;
84 }
85 strcpy(orig_ptr, newtext);
86
87 return orig_ptr;
88 }
89
90
91 void init_disk_stat(int start, int end, disk_stat_t *disk_stats){
92
93 for(disk_stats+=start; start<=end; start++){
94 disk_stats->device_name=NULL;
95 disk_stats->fs_type=NULL;
96 disk_stats->mnt_point=NULL;
97
98 disk_stats++;
99 }
100 }
101
102 int is_valid_fs_type(const char *type) {
103 const char *types[] = VALID_FS_TYPES;
104 int i;
105
106 for (i = 0; i < (sizeof types / sizeof *types); i++) {
107 if (strcmp(types[i], type) == 0) {
108 return 1;
109 }
110 }
111 return 0;
112 }
113
114 disk_stat_t *get_disk_stats(int *entries){
115
116 static disk_stat_t *disk_stats;
117 static int watermark=-1;
118
119 int valid_type;
120 int num_disks=0;
121 #if defined(LINUX) || defined (SOLARIS) || defined(CYGWIN)
122 FILE *f;
123 #endif
124
125 disk_stat_t *disk_ptr;
126
127 #ifdef SOLARIS
128 struct mnttab mp;
129 struct statvfs fs;
130 #endif
131 #if defined(LINUX) || defined(CYGWIN)
132 struct mntent *mp;
133 struct statfs fs;
134 #endif
135 #ifdef ALLBSD
136 int nummnt;
137 struct statfs *mp;
138 #endif
139
140 if(watermark==-1){
141 disk_stats=malloc(START_VAL * sizeof(disk_stat_t));
142 if(disk_stats==NULL){
143 return NULL;
144 }
145 watermark=START_VAL;
146 init_disk_stat(0, watermark-1, disk_stats);
147 }
148 #ifdef ALLBSD
149 nummnt=getmntinfo(&mp , MNT_LOCAL);
150 if (nummnt<=0){
151 return NULL;
152 }
153 for(;nummnt--; mp++){
154 valid_type = is_valid_fs_type(mp->f_fstypename);
155 #endif
156
157 #if defined(LINUX) || defined(CYGWIN)
158 if ((f=setmntent("/etc/mtab", "r" ))==NULL){
159 return NULL;
160 }
161
162 while((mp=getmntent(f))){
163 if((statfs(mp->mnt_dir, &fs)) !=0){
164 continue;
165 }
166
167 valid_type = is_valid_fs_type(mp->mnt_type);
168 #endif
169
170 #ifdef SOLARIS
171 if ((f=fopen("/etc/mnttab", "r" ))==NULL){
172 return NULL;
173 }
174 while((getmntent(f, &mp)) == 0){
175 if ((statvfs(mp.mnt_mountp, &fs)) !=0){
176 continue;
177 }
178 valid_type = is_valid_fs_type(mp.mnt_fstype);
179 #endif
180
181 if(valid_type){
182 if(num_disks>watermark-1){
183 disk_ptr=disk_stats;
184 if((disk_stats=realloc(disk_stats, (watermark*2 * sizeof(disk_stat_t))))==NULL){
185 disk_stats=disk_ptr;
186 return NULL;
187 }
188
189 watermark=watermark*2;
190 init_disk_stat(num_disks, watermark-1, disk_stats);
191 }
192
193 disk_ptr=disk_stats+num_disks;
194 #ifdef ALLBSD
195 if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp->f_mntfromname))==NULL){
196 return NULL;
197 }
198
199 if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp->f_fstypename))==NULL){
200 return NULL;
201 }
202
203 if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp->f_mntonname))==NULL){
204 return NULL;
205 }
206
207 disk_ptr->size = (long long)mp->f_bsize * (long long) mp->f_blocks;
208 disk_ptr->avail = (long long)mp->f_bsize * (long long) mp->f_bavail;
209 disk_ptr->used = (disk_ptr->size) - ((long long)mp->f_bsize * (long long)mp->f_bfree);
210
211 disk_ptr->total_inodes=(long long)mp->f_files;
212 disk_ptr->free_inodes=(long long)mp->f_ffree;
213 /* Freebsd doesn't have a "available" inodes */
214 disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
215 #endif
216 #if defined(LINUX) || defined(CYGWIN)
217 if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp->mnt_fsname))==NULL){
218 return NULL;
219 }
220
221 if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp->mnt_type))==NULL){
222 return NULL;
223 }
224
225 if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp->mnt_dir))==NULL){
226 return NULL;
227 }
228 disk_ptr->size = (long long)fs.f_bsize * (long long)fs.f_blocks;
229 disk_ptr->avail = (long long)fs.f_bsize * (long long)fs.f_bavail;
230 disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_bsize * (long long)fs.f_bfree);
231
232 disk_ptr->total_inodes=(long long)fs.f_files;
233 disk_ptr->free_inodes=(long long)fs.f_ffree;
234 /* Linux doesn't have a "available" inodes */
235 disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
236 #endif
237
238 #ifdef SOLARIS
239 /* Memory leak in event of realloc failing */
240 /* Maybe make this char[bigenough] and do strncpy's and put a null in the end?
241 * Downside is its a bit hungry for a lot of mounts, as MNT_MAX_SIZE would prob
242 * be upwards of a k each
243 */
244 if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp.mnt_special))==NULL){
245 return NULL;
246 }
247
248 if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp.mnt_fstype))==NULL){
249 return NULL;
250 }
251
252 if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp.mnt_mountp))==NULL){
253 return NULL;
254 }
255
256 disk_ptr->size = (long long)fs.f_frsize * (long long)fs.f_blocks;
257 disk_ptr->avail = (long long)fs.f_frsize * (long long)fs.f_bavail;
258 disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_frsize * (long long)fs.f_bfree);
259
260 disk_ptr->total_inodes=(long long)fs.f_files;
261 disk_ptr->used_inodes=disk_ptr->total_inodes - (long long)fs.f_ffree;
262 disk_ptr->free_inodes=(long long)fs.f_favail;
263 #endif
264 num_disks++;
265 }
266 }
267
268 *entries=num_disks;
269
270 /* If this fails, there is very little i can do about it, so
271 I'll ignore it :) */
272 #if defined(LINUX) || defined(CYGWIN)
273 endmntent(f);
274 #endif
275 #if defined(SOLARIS)
276 fclose(f);
277 #endif
278
279 return disk_stats;
280
281 }
282 void diskio_stat_init(int start, int end, diskio_stat_t *diskio_stats){
283
284 for(diskio_stats+=start; start<end; start++){
285 diskio_stats->disk_name=NULL;
286
287 diskio_stats++;
288 }
289 }
290
291 diskio_stat_t *diskio_stat_malloc(int needed_entries, int *cur_entries, diskio_stat_t *diskio_stats){
292
293 if(diskio_stats==NULL){
294
295 if((diskio_stats=malloc(needed_entries * sizeof(diskio_stat_t)))==NULL){
296 return NULL;
297 }
298 diskio_stat_init(0, needed_entries, diskio_stats);
299 *cur_entries=needed_entries;
300
301 return diskio_stats;
302 }
303
304
305 if(*cur_entries<needed_entries){
306 diskio_stats=realloc(diskio_stats, (sizeof(diskio_stat_t)*needed_entries));
307 if(diskio_stats==NULL){
308 return NULL;
309 }
310 diskio_stat_init(*cur_entries, needed_entries, diskio_stats);
311 *cur_entries=needed_entries;
312 }
313
314 return diskio_stats;
315 }
316
317 static diskio_stat_t *diskio_stats=NULL;
318 static int num_diskio=0;
319
320 #ifdef LINUX
321 typedef struct {
322 int major;
323 int minor;
324 } partition;
325 #endif
326
327 diskio_stat_t *get_diskio_stats(int *entries){
328
329 static int sizeof_diskio_stats=0;
330 #ifndef LINUX
331 diskio_stat_t *diskio_stats_ptr;
332 #endif
333
334 #ifdef SOLARIS
335 kstat_ctl_t *kc;
336 kstat_t *ksp;
337 kstat_io_t kios;
338 #endif
339 #ifdef LINUX
340 FILE *f;
341 char *line_ptr;
342 int major, minor;
343 int has_pp_stats = 1;
344 static partition *parts = NULL;
345 static int alloc_parts = 0;
346 int i, n;
347 time_t now;
348 const char *format;
349 #endif
350 #ifdef FREEBSD
351 static struct statinfo stats;
352 static int stats_init = 0;
353 int counter;
354 struct device_selection *dev_sel = NULL;
355 int n_selected, n_selections;
356 long sel_gen;
357 struct devstat *dev_ptr;
358 #endif
359 #ifdef NETBSD
360 struct disk_sysctl *stats;
361 int num_disks, i;
362 int mib[3];
363 size_t size;
364 #endif
365
366 num_diskio=0;
367
368 #ifdef NETBSD
369 mib[0] = CTL_HW;
370 mib[1] = HW_DISKSTATS;
371 mib[2] = sizeof(struct disk_sysctl);
372
373 if (sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
374 return NULL;
375 }
376 num_disks = size / sizeof(struct disk_sysctl);
377
378 stats = malloc(size);
379 if (stats == NULL) {
380 return NULL;
381 }
382
383 if (sysctl(mib, 3, stats, &size, NULL, 0) < 0) {
384 return NULL;
385 }
386
387 for (i = 0; i < num_disks; i++) {
388 u_int64_t rbytes, wbytes;
389
390 #ifdef HAVE_DK_RBYTES
391 rbytes = stats[i].dk_rbytes;
392 wbytes = stats[i].dk_wbytes;
393 #else
394 /* Before 1.7, NetBSD merged reads and writes. */
395 rbytes = wbytes = stats[i].dk_bytes;
396 #endif
397
398 /* Don't keep stats for disks that have never been used. */
399 if (rbytes == 0 && wbytes == 0) {
400 continue;
401 }
402
403 diskio_stats = diskio_stat_malloc(num_diskio + 1,
404 &sizeof_diskio_stats,
405 diskio_stats);
406 if (diskio_stats == NULL) {
407 return NULL;
408 }
409 diskio_stats_ptr = diskio_stats + num_diskio;
410
411 diskio_stats_ptr->read_bytes = rbytes;
412 diskio_stats_ptr->write_bytes = wbytes;
413 if (diskio_stats_ptr->disk_name != NULL) {
414 free(diskio_stats_ptr->disk_name);
415 }
416 diskio_stats_ptr->disk_name = strdup(stats[i].dk_name);
417 diskio_stats_ptr->systime = time(NULL);
418
419 num_diskio++;
420 }
421
422 free(stats);
423 #endif
424
425 #ifdef FREEBSD
426 if (!stats_init) {
427 stats.dinfo=malloc(sizeof(struct devinfo));
428 if(stats.dinfo==NULL) return NULL;
429 bzero(stats.dinfo, sizeof(struct devinfo));
430 stats_init = 1;
431 }
432 #ifdef FREEBSD5
433 if ((devstat_getdevs(NULL, &stats)) < 0) return NULL;
434 /* Not aware of a get all devices, so i said 999. If we ever
435 * find a machine with more than 999 disks, then i'll change
436 * this number :)
437 */
438 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;
439 #else
440 if ((getdevs(&stats)) < 0) return NULL;
441 /* Not aware of a get all devices, so i said 999. If we ever
442 * find a machine with more than 999 disks, then i'll change
443 * this number :)
444 */
445 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;
446 #endif
447
448 for(counter=0;counter<stats.dinfo->numdevs;counter++){
449 dev_ptr=&stats.dinfo->devices[dev_sel[counter].position];
450
451 /* Throw away devices that have done nothing, ever.. Eg "odd"
452 * devices.. like mem, proc.. and also doesn't report floppy
453 * drives etc unless they are doing stuff :)
454 */
455 #ifdef FREEBSD5
456 if((dev_ptr->bytes[DEVSTAT_READ]==0) && (dev_ptr->bytes[DEVSTAT_WRITE]==0)) continue;
457 #else
458 if((dev_ptr->bytes_read==0) && (dev_ptr->bytes_written==0)) continue;
459 #endif
460 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
461 return NULL;
462 }
463 diskio_stats_ptr=diskio_stats+num_diskio;
464
465 #ifdef FREEBSD5
466 diskio_stats_ptr->read_bytes=dev_ptr->bytes[DEVSTAT_READ];
467 diskio_stats_ptr->write_bytes=dev_ptr->bytes[DEVSTAT_WRITE];
468 #else
469 diskio_stats_ptr->read_bytes=dev_ptr->bytes_read;
470 diskio_stats_ptr->write_bytes=dev_ptr->bytes_written;
471 #endif
472 if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
473 asprintf((&diskio_stats_ptr->disk_name), "%s%d", dev_ptr->device_name, dev_ptr->unit_number);
474 diskio_stats_ptr->systime=time(NULL);
475
476 num_diskio++;
477 }
478 free(dev_sel);
479
480 #endif
481 #ifdef SOLARIS
482 if ((kc = kstat_open()) == NULL) {
483 return NULL;
484 }
485
486 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
487 if (!strcmp(ksp->ks_class, "disk")) {
488
489 if(ksp->ks_type != KSTAT_TYPE_IO) continue;
490 /* We dont want metadevices appearins as num_diskio */
491 if(strcmp(ksp->ks_module, "md")==0) continue;
492 if((kstat_read(kc, ksp, &kios))==-1){
493 }
494
495 if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
496 kstat_close(kc);
497 return NULL;
498 }
499 diskio_stats_ptr=diskio_stats+num_diskio;
500
501 diskio_stats_ptr->read_bytes=kios.nread;
502
503 diskio_stats_ptr->write_bytes=kios.nwritten;
504
505 if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
506
507 diskio_stats_ptr->disk_name=strdup((char *) get_svr_from_bsd(ksp->ks_name));
508 diskio_stats_ptr->systime=time(NULL);
509 num_diskio++;
510 }
511 }
512
513 kstat_close(kc);
514 #endif
515
516 #ifdef LINUX
517 num_diskio = 0;
518 n = 0;
519
520 /* Read /proc/partitions to find what devices exist. Recent 2.4 kernels
521 have statistics in here too, so we can use those directly.
522 2.6 kernels have /proc/diskstats instead with almost (but not quite)
523 the same format. */
524
525 f = fopen("/proc/diskstats", "r");
526 format = " %d %d %19s %*d %*d %lld %*d %*d %*d %lld";
527 if (f == NULL) {
528 f = fopen("/proc/partitions", "r");
529 format = " %d %d %*d %19s %*d %*d %lld %*d %*d %*d %lld";
530 }
531 if (f == NULL) goto out;
532 now = time(NULL);
533
534 while ((line_ptr = f_read_line(f, "")) != NULL) {
535 char name[20];
536 char *s;
537 long long rsect, wsect;
538
539 int nr = sscanf(line_ptr, format,
540 &major, &minor, name, &rsect, &wsect);
541 if (nr < 3) continue;
542
543 /* Skip device names ending in numbers, since they're
544 partitions. */
545 s = name;
546 while (*s != '\0') s++;
547 --s;
548 if (*s >= '0' && *s <= '9') continue;
549
550 if (nr < 5) {
551 has_pp_stats = 0;
552 rsect = 0;
553 wsect = 0;
554 }
555
556 diskio_stats = diskio_stat_malloc(n + 1, &sizeof_diskio_stats,
557 diskio_stats);
558 if (diskio_stats == NULL) goto out;
559 if (n >= alloc_parts) {
560 alloc_parts += 16;
561 parts = realloc(parts, alloc_parts * sizeof *parts);
562 if (parts == NULL) {
563 alloc_parts = 0;
564 goto out;
565 }
566 }
567
568 if (diskio_stats[n].disk_name != NULL)
569 free(diskio_stats[n].disk_name);
570 diskio_stats[n].disk_name = strdup(name);
571 diskio_stats[n].read_bytes = rsect * 512;
572 diskio_stats[n].write_bytes = wsect * 512;
573 diskio_stats[n].systime = now;
574 parts[n].major = major;
575 parts[n].minor = minor;
576
577 n++;
578 }
579
580 fclose(f);
581 f = NULL;
582
583 if (!has_pp_stats) {
584 /* This is an older kernel where /proc/partitions doesn't
585 contain stats. Read what we can from /proc/stat instead, and
586 fill in the appropriate bits of the list allocated above. */
587
588 f = fopen("/proc/stat", "r");
589 if (f == NULL) goto out;
590 now = time(NULL);
591
592 line_ptr = f_read_line(f, "disk_io:");
593 if (line_ptr == NULL) goto out;
594
595 while((line_ptr=strchr(line_ptr, ' '))!=NULL){
596 long long rsect, wsect;
597
598 if (*++line_ptr == '\0') break;
599
600 if((sscanf(line_ptr,
601 "(%d,%d):(%*d, %*d, %lld, %*d, %lld)",
602 &major, &minor, &rsect, &wsect)) != 4) {
603 continue;
604 }
605
606 /* Find the corresponding device from earlier.
607 Just to add to the fun, "minor" is actually the disk
608 number, not the device minor, so we need to figure
609 out the real minor number based on the major!
610 This list is not exhaustive; if you're running
611 an older kernel you probably don't have fancy
612 I2O hardware anyway... */
613 switch (major) {
614 case 3:
615 case 21:
616 case 22:
617 case 33:
618 case 34:
619 case 36:
620 case 56:
621 case 57:
622 case 88:
623 case 89:
624 case 90:
625 case 91:
626 minor *= 64;
627 break;
628 case 9:
629 case 43:
630 break;
631 default:
632 minor *= 16;
633 break;
634 }
635 for (i = 0; i < n; i++) {
636 if (major == parts[i].major
637 && minor == parts[i].minor)
638 break;
639 }
640 if (i == n) continue;
641
642 /* We read the number of blocks. Blocks are stored in
643 512 bytes */
644 diskio_stats[i].read_bytes = rsect * 512;
645 diskio_stats[i].write_bytes = wsect * 512;
646 diskio_stats[i].systime = now;
647 }
648 }
649
650 num_diskio = n;
651 out:
652 if (f != NULL) fclose(f);
653 #endif
654
655 #ifdef CYGWIN
656 return NULL;
657 #endif
658
659 *entries=num_diskio;
660
661 return diskio_stats;
662 }
663
664 diskio_stat_t *get_diskio_stats_diff(int *entries){
665 static diskio_stat_t *diskio_stats_diff=NULL;
666 static int sizeof_diskio_stats_diff=0;
667 diskio_stat_t *diskio_stats_diff_ptr, *diskio_stats_ptr;
668 int disks, x, y;
669
670 if(diskio_stats==NULL){
671 diskio_stats_ptr=get_diskio_stats(&disks);
672 *entries=disks;
673 return diskio_stats_ptr;
674 }
675
676 diskio_stats_diff=diskio_stat_malloc(num_diskio, &sizeof_diskio_stats_diff, diskio_stats_diff);
677 if(diskio_stats_diff==NULL){
678 return NULL;
679 }
680
681 diskio_stats_diff_ptr=diskio_stats_diff;
682 diskio_stats_ptr=diskio_stats;
683
684 for(disks=0;disks<num_diskio;disks++){
685 if(diskio_stats_diff_ptr->disk_name!=NULL){
686 free(diskio_stats_diff_ptr->disk_name);
687 }
688 diskio_stats_diff_ptr->disk_name=strdup(diskio_stats_ptr->disk_name);
689 diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes;
690 diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes;
691 diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime;
692
693 diskio_stats_diff_ptr++;
694 diskio_stats_ptr++;
695 }
696
697 diskio_stats_ptr=get_diskio_stats(&disks);
698 if (diskio_stats_ptr == NULL) {
699 return NULL;
700 }
701 diskio_stats_diff_ptr=diskio_stats_diff;
702
703 for(x=0;x<sizeof_diskio_stats_diff;x++){
704
705 if((strcmp(diskio_stats_diff_ptr->disk_name, diskio_stats_ptr->disk_name))==0){
706 diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes-diskio_stats_diff_ptr->read_bytes;
707 diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes-diskio_stats_diff_ptr->write_bytes;
708 diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime-diskio_stats_diff_ptr->systime;
709 }else{
710 diskio_stats_ptr=diskio_stats;
711 for(y=0;y<disks;y++){
712 if((strcmp(diskio_stats_diff_ptr->disk_name, diskio_stats_ptr->disk_name))==0){
713 diskio_stats_diff_ptr->read_bytes=diskio_stats_ptr->read_bytes-diskio_stats_diff_ptr->read_bytes;
714 diskio_stats_diff_ptr->write_bytes=diskio_stats_ptr->write_bytes-diskio_stats_diff_ptr->write_bytes;
715 diskio_stats_diff_ptr->systime=diskio_stats_ptr->systime-diskio_stats_diff_ptr->systime;
716
717 break;
718 }
719
720 diskio_stats_ptr++;
721 }
722 }
723
724 diskio_stats_ptr++;
725 diskio_stats_diff_ptr++;
726
727 }
728
729 *entries=sizeof_diskio_stats_diff;
730 return diskio_stats_diff;
731 }