ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.49
Committed: Mon Jan 19 16:49:21 2004 UTC (20 years, 3 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: LIBSTATGRAB_0_8_1
Changes since 1.48: +2 -0 lines
Log Message:
A whole bunch of minor cosmetic changes.

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