ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
Revision: 1.34
Committed: Sun Oct 19 12:04:05 2003 UTC (20 years, 6 months ago) by ats
Content type: text/plain
Branch: MAIN
Changes since 1.33: +67 -3 lines
Log Message:
Implement diskio stats on NetBSD. Tested on 1.6, but should work on 1.6.1
(and give more useful output, since 1.6.1 seperates read and write statistics).

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