ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/disk_stats.c
(Generate patch)

Comparing projects/libstatgrab/src/libstatgrab/disk_stats.c (file contents):
Revision 1.62 by ats, Mon Apr 5 18:10:11 2004 UTC vs.
Revision 1.82 by tdb, Wed Jul 13 13:01:24 2005 UTC

# Line 1 | Line 1
1   /*
2 < * i-scream central monitoring system
2 > * i-scream libstatgrab
3   * http://www.i-scream.org
4   * Copyright (C) 2000-2004 i-scream
5   *
# Line 37 | Line 37
37   #include <sys/mnttab.h>
38   #include <sys/statvfs.h>
39   #include <kstat.h>
40 < #define VALID_FS_TYPES {"ufs", "tmpfs"}
40 > #define VALID_FS_TYPES {"ufs", "tmpfs", "vxfs"}
41   #endif
42  
43   #if defined(LINUX) || defined(CYGWIN)
44   #include <mntent.h>
45   #include <sys/vfs.h>
46 + #include <sys/statvfs.h>
47   #endif
48  
49   #ifdef LINUX
50   #define VALID_FS_TYPES {"adfs", "affs", "befs", "bfs", "efs", "ext2", \
51 <                        "ext3", "vxfs", "hfs", "hfsplus", "hpfs", "jffs", \
52 <                        "jffs2", "minix", "msdos", "ntfs", "qnx4", "ramfs", \
53 <                        "rootfs", "reiserfs", "sysv", "v7", "udf", "ufs", \
54 <                        "umsdos", "vfat", "xfs", "jfs"}
51 >                        "ext3", "vxfs", "hfs", "hfsplus", "hpfs", "jffs", \
52 >                        "jffs2", "minix", "msdos", "ntfs", "qnx4", "ramfs", \
53 >                        "rootfs", "reiserfs", "sysv", "v7", "udf", "ufs", \
54 >                        "umsdos", "vfat", "xfs", "jfs", "nfs"}
55   #endif
56  
57   #ifdef CYGWIN
# Line 66 | Line 67
67   #include <sys/dkstat.h>
68   #include <devstat.h>
69   #define VALID_FS_TYPES {"hpfs", "msdosfs", "ntfs", "udf", "ext2fs", \
70 <                        "ufs", "mfs"}
70 >                        "ufs", "mfs", "nfs"}
71   #endif
72   #if defined(NETBSD) || defined(OPENBSD)
73   #include <sys/param.h>
74   #include <sys/sysctl.h>
75   #include <sys/disk.h>
76   #define VALID_FS_TYPES {"ffs", "mfs", "msdos", "lfs", "adosfs", "ext2fs", \
77 <                        "ntfs"}
77 >                        "ntfs", "nfs"}
78   #endif
79  
80 + #ifdef HPUX
81 + #include <sys/param.h>
82 + #include <sys/pstat.h>
83 + #include <sys/types.h>
84 + #include <sys/stat.h>
85 + #include <sys/vfs.h>
86 + #include <mntent.h>
87 + #include <dirent.h>
88 + #include <stdio.h>
89 + #include <time.h>
90 + #define VALID_FS_TYPES {"vxfs", "hfs"}
91 + #define DISK_BATCH 30
92 + #endif
93 +
94 + #ifdef ALLBSD
95 + #define SG_MP_FSTYPENAME(mp) (mp)->f_fstypename
96 + #define SG_MP_DEVNAME(mp)    (mp)->f_mntfromname
97 + #define SG_MP_MOUNTP(mp)     (mp)->f_mntonname
98 + #define SG_FS_FRSIZE(fs)     (long long) (*(fs))->f_bsize
99 + #define SG_FS_BSIZE(fs)      (long long) (*(fs))->f_iosize
100 + #define SG_FS_BLOCKS(fs)     (long long) (*(fs))->f_blocks
101 + #define SG_FS_BFREE(fs)      (long long) (*(fs))->f_bfree
102 + #define SG_FS_BAVAIL(fs)     (long long) (*(fs))->f_bavail
103 + #define SG_FS_FILES(fs)      (long long) (*(fs))->f_files
104 + #define SG_FS_FFREE(fs)      (long long) (*(fs))->f_ffree
105 + #define SG_FS_FAVAIL(fs)     -1LL
106 + #endif
107 + #if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
108 + #define SG_MP_FSTYPENAME(mp) (mp)->mnt_type
109 + #define SG_MP_DEVNAME(mp)    (mp)->mnt_fsname
110 + #define SG_MP_MOUNTP(mp)     (mp)->mnt_dir
111 + #define SG_FS_FRSIZE(fs)     (long long) (fs).f_frsize
112 + #define SG_FS_BSIZE(fs)      (long long) (fs).f_bsize
113 + #define SG_FS_BLOCKS(fs)     (long long) (fs).f_blocks
114 + #define SG_FS_BFREE(fs)      (long long) (fs).f_bfree
115 + #define SG_FS_BAVAIL(fs)     (long long) (fs).f_bavail
116 + #define SG_FS_FILES(fs)      (long long) (fs).f_files
117 + #define SG_FS_FFREE(fs)      (long long) (fs).f_ffree
118 + #define SG_FS_FAVAIL(fs)     (long long) (fs).f_favail
119 + #endif
120 + #ifdef SOLARIS
121 + #define SG_MP_FSTYPENAME(mp) (mp).mnt_fstype
122 + #define SG_MP_DEVNAME(mp)    (mp).mnt_special
123 + #define SG_MP_MOUNTP(mp)     (mp).mnt_mountp
124 + #define SG_FS_FRSIZE(fs)     (long long) (fs).f_frsize
125 + #define SG_FS_BSIZE(fs)      (long long) (fs).f_bsize
126 + #define SG_FS_BLOCKS(fs)     (long long) (fs).f_blocks
127 + #define SG_FS_BFREE(fs)      (long long) (fs).f_bfree
128 + #define SG_FS_BAVAIL(fs)     (long long) (fs).f_bavail
129 + #define SG_FS_FILES(fs)      (long long) (fs).f_files
130 + #define SG_FS_FFREE(fs)      (long long) (fs).f_ffree
131 + #define SG_FS_FAVAIL(fs)     (long long) (fs).f_favail
132 + #endif
133 +
134   static void disk_stat_init(sg_fs_stats *d) {
135          d->device_name = NULL;
136          d->fs_type = NULL;
# Line 92 | Line 147 | static int is_valid_fs_type(const char *type) {
147          const char *types[] = VALID_FS_TYPES;
148          int i;
149  
150 <        for (i = 0; i < (sizeof types / sizeof *types); i++) {
150 >        for (i = 0; i < (int) (sizeof types / sizeof *types); i++) {
151                  if (strcmp(types[i], type) == 0) {
152                          return 1;
153                  }
# Line 102 | Line 157 | static int is_valid_fs_type(const char *type) {
157  
158   sg_fs_stats *sg_get_fs_stats(int *entries){
159          VECTOR_DECLARE_STATIC(disk_stats, sg_fs_stats, 10,
160 <                              disk_stat_init, disk_stat_destroy);
160 >                              disk_stat_init, disk_stat_destroy);
161  
107        int valid_type;
162          int num_disks=0;
163 < #if defined(LINUX) || defined (SOLARIS) || defined(CYGWIN)
163 > #if defined(LINUX) || defined (SOLARIS) || defined(CYGWIN) || defined(HPUX)
164          FILE *f;
165   #endif
166  
# Line 116 | Line 170 | sg_fs_stats *sg_get_fs_stats(int *entries){
170          struct mnttab mp;
171          struct statvfs fs;
172   #endif
173 < #if defined(LINUX) || defined(CYGWIN)
173 > #if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
174          struct mntent *mp;
175 <        struct statfs fs;
175 >        struct statvfs fs;
176   #endif
177   #ifdef ALLBSD
178          int nummnt;
179 <        struct statfs *mp;
179 > #ifdef HAVE_STATVFS
180 >        struct statvfs *mp, **fs;
181 > #else
182 >        struct statfs *mp, **fs;
183   #endif
184 + #endif
185  
186   #ifdef ALLBSD
187 <        nummnt=getmntinfo(&mp , MNT_LOCAL);
187 >        nummnt=getmntinfo(&mp, MNT_WAIT);
188          if (nummnt<=0){
189 +                sg_set_error_with_errno(SG_ERROR_GETMNTINFO, NULL);
190                  return NULL;
191          }
192 <        for(;nummnt--; mp++){
134 <                valid_type = is_valid_fs_type(mp->f_fstypename);
192 >        for(fs = &mp; nummnt--; (*fs)++){
193   #endif
194  
195 < #if defined(LINUX) || defined(CYGWIN)
195 > #if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
196 > #ifdef MNT_MNTTAB
197 >        if ((f=setmntent(MNT_MNTTAB, "r" ))==NULL){
198 > #else
199          if ((f=setmntent("/etc/mtab", "r" ))==NULL){
200 + #endif
201 +                sg_set_error(SG_ERROR_SETMNTENT, NULL);
202                  return NULL;
203          }
204  
205          while((mp=getmntent(f))){
206 <                if((statfs(mp->mnt_dir, &fs)) !=0){
206 >                if((statvfs(mp->mnt_dir, &fs)) !=0){
207                          continue;
208                  }      
209  
147                valid_type = is_valid_fs_type(mp->mnt_type);
210   #endif
211  
212   #ifdef SOLARIS
213          if ((f=fopen("/etc/mnttab", "r" ))==NULL){
214 +                sg_set_error_with_errno(SG_ERROR_OPEN, "/etc/mnttab");
215                  return NULL;
216          }
217          while((getmntent(f, &mp)) == 0){
218                  if ((statvfs(mp.mnt_mountp, &fs)) !=0){
219                          continue;
220                  }
158                valid_type = is_valid_fs_type(mp.mnt_fstype);
221   #endif
222  
223 <                if(valid_type){
223 >                if(is_valid_fs_type(SG_MP_FSTYPENAME(mp))){
224                          if (VECTOR_RESIZE(disk_stats, num_disks + 1) < 0) {
225                                  return NULL;
226                          }
227                          disk_ptr=disk_stats+num_disks;
228  
229 < #ifdef ALLBSD
230 <                        if (sg_update_string(&disk_ptr->device_name, mp->f_mntfromname) < 0) {
229 >                        /* Maybe make this char[bigenough] and do strncpy's and put a null in the end?
230 >                         * Downside is its a bit hungry for a lot of mounts, as MNT_MAX_SIZE would prob
231 >                         * be upwards of a k each
232 >                         */
233 >                        if (sg_update_string(&disk_ptr->device_name, SG_MP_DEVNAME(mp)) < 0) {
234                                  return NULL;
235                          }
236 <                        if (sg_update_string(&disk_ptr->fs_type, mp->f_fstypename) < 0) {
236 >                        if (sg_update_string(&disk_ptr->fs_type, SG_MP_FSTYPENAME(mp)) < 0) {
237                                  return NULL;
238                          }
239 <                        if (sg_update_string(&disk_ptr->mnt_point, mp->f_mntonname) < 0) {
239 >                        if (sg_update_string(&disk_ptr->mnt_point, SG_MP_MOUNTP(mp)) < 0) {
240                                  return NULL;
241                          }
242  
243 <                        disk_ptr->size = (long long)mp->f_bsize * (long long) mp->f_blocks;
244 <                        disk_ptr->avail = (long long)mp->f_bsize * (long long) mp->f_bavail;
245 <                        disk_ptr->used = (disk_ptr->size) - ((long long)mp->f_bsize * (long long)mp->f_bfree);
243 >                        disk_ptr->size  = SG_FS_FRSIZE(fs) * SG_FS_BLOCKS(fs);
244 >                        disk_ptr->avail = SG_FS_FRSIZE(fs) * SG_FS_BAVAIL(fs);
245 >                        disk_ptr->used  = (disk_ptr->size) - (SG_FS_FRSIZE(fs) * SG_FS_BFREE(fs));
246  
247 <                        disk_ptr->total_inodes=(long long)mp->f_files;
248 <                        disk_ptr->free_inodes=(long long)mp->f_ffree;
249 <                        /* Freebsd doesn't have a "available" inodes */
250 <                        disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
251 < #endif
187 < #if defined(LINUX) || defined(CYGWIN)
188 <                        if (sg_update_string(&disk_ptr->device_name, mp->mnt_fsname) < 0) {
189 <                                return NULL;
190 <                        }
191 <                                
192 <                        if (sg_update_string(&disk_ptr->fs_type, mp->mnt_type) < 0) {  
193 <                                return NULL;
194 <                        }
247 >                        disk_ptr->total_inodes = SG_FS_FILES(fs);
248 >                        disk_ptr->free_inodes  = SG_FS_FFREE(fs);
249 >                        /* Linux, FreeBSD don't have a "available" inodes */
250 >                        disk_ptr->used_inodes  = disk_ptr->total_inodes - disk_ptr->free_inodes;
251 >                        disk_ptr->avail_inodes = SG_FS_FAVAIL(fs);
252  
253 <                        if (sg_update_string(&disk_ptr->mnt_point, mp->mnt_dir) < 0) {
254 <                                return NULL;
255 <                        }
256 <                        disk_ptr->size = (long long)fs.f_bsize * (long long)fs.f_blocks;
257 <                        disk_ptr->avail = (long long)fs.f_bsize * (long long)fs.f_bavail;
258 <                        disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_bsize * (long long)fs.f_bfree);
253 >                        disk_ptr->io_size      = SG_FS_BSIZE(fs);
254 >                        disk_ptr->block_size   = SG_FS_FRSIZE(fs);
255 >                        disk_ptr->total_blocks = SG_FS_BLOCKS(fs);
256 >                        disk_ptr->free_blocks  = SG_FS_BFREE(fs);
257 >                        disk_ptr->avail_blocks = SG_FS_BAVAIL(fs);
258 >                        disk_ptr->used_blocks  = disk_ptr->total_blocks - disk_ptr->free_blocks;
259  
203                        disk_ptr->total_inodes=(long long)fs.f_files;
204                        disk_ptr->free_inodes=(long long)fs.f_ffree;
205                        /* Linux doesn't have a "available" inodes */
206                        disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
207 #endif
208
209 #ifdef SOLARIS
210                        /* Maybe make this char[bigenough] and do strncpy's and put a null in the end?
211                         * Downside is its a bit hungry for a lot of mounts, as MNT_MAX_SIZE would prob
212                         * be upwards of a k each
213                         */
214                        if (sg_update_string(&disk_ptr->device_name, mp.mnt_special) < 0) {
215                                return NULL;
216                        }
217
218                        if (sg_update_string(&disk_ptr->fs_type, mp.mnt_fstype) < 0) {
219                                return NULL;
220                        }
221        
222                        if (sg_update_string(&disk_ptr->mnt_point, mp.mnt_mountp) < 0) {
223                                return NULL;
224                        }
225                        
226                        disk_ptr->size = (long long)fs.f_frsize * (long long)fs.f_blocks;
227                        disk_ptr->avail = (long long)fs.f_frsize * (long long)fs.f_bavail;
228                        disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_frsize * (long long)fs.f_bfree);
229                
230                        disk_ptr->total_inodes=(long long)fs.f_files;
231                        disk_ptr->used_inodes=disk_ptr->total_inodes - (long long)fs.f_ffree;
232                        disk_ptr->free_inodes=(long long)fs.f_favail;
233 #endif
260                          num_disks++;
261                  }
262          }
# Line 238 | Line 264 | sg_fs_stats *sg_get_fs_stats(int *entries){
264          *entries=num_disks;    
265  
266          /* If this fails, there is very little i can do about it, so
267 <           I'll ignore it :) */
268 < #if defined(LINUX) || defined(CYGWIN)
267 >           I'll ignore it :) */
268 > #if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
269          endmntent(f);
270   #endif
271   #if defined(SOLARIS)
# Line 250 | Line 276 | sg_fs_stats *sg_get_fs_stats(int *entries){
276  
277   }
278  
279 + int sg_fs_compare_device_name(const void *va, const void *vb) {
280 +        const sg_fs_stats *a = (const sg_fs_stats *)va;
281 +        const sg_fs_stats *b = (const sg_fs_stats *)vb;
282 +
283 +        return strcmp(a->device_name, b->device_name);
284 + }
285 +
286 + int sg_fs_compare_mnt_point(const void *va, const void *vb) {
287 +        const sg_fs_stats *a = (const sg_fs_stats *)va;
288 +        const sg_fs_stats *b = (const sg_fs_stats *)vb;
289 +
290 +        return strcmp(a->mnt_point, b->mnt_point);
291 + }
292 +
293   static void diskio_stat_init(sg_disk_io_stats *d) {
294          d->disk_name = NULL;
295   }
# Line 259 | Line 299 | static void diskio_stat_destroy(sg_disk_io_stats *d) {
299   }
300  
301   VECTOR_DECLARE_STATIC(diskio_stats, sg_disk_io_stats, 10,
302 <                      diskio_stat_init, diskio_stat_destroy);
302 >                      diskio_stat_init, diskio_stat_destroy);
303  
304   #ifdef LINUX
305   typedef struct {
# Line 274 | Line 314 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
314          sg_disk_io_stats *diskio_stats_ptr;
315   #endif
316  
317 + #ifdef HPUX
318 +        long long rbytes = 0, wbytes = 0;
319 +        struct dirent *dinfo = NULL;
320 +        struct stat lstatinfo;
321 +        struct pst_diskinfo pstat_diskinfo[DISK_BATCH];
322 +        char fullpathbuf[1024] = {0};
323 +        dev_t diskid;
324 +        DIR *dh = NULL;
325 +        int diskidx = 0;
326 +        int num, i;
327 + #endif
328   #ifdef SOLARIS
329 <        kstat_ctl_t *kc;
330 <        kstat_t *ksp;
329 >        kstat_ctl_t *kc;
330 >        kstat_t *ksp;
331          kstat_io_t kios;
332   #endif
333   #ifdef LINUX
# Line 288 | Line 339 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
339          int i, n;
340          time_t now;
341          const char *format;
342 +        static regex_t not_part_re, part_re;
343 +        static int re_compiled = 0;
344   #endif
345   #if defined(FREEBSD) || defined(DFBSD)
346          static struct statinfo stats;
# Line 321 | Line 374 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
374  
375          num_diskio=0;
376  
377 + #ifdef HPUX
378 +        while (1) {
379 +                num = pstat_getdisk(pstat_diskinfo, sizeof pstat_diskinfo[0],
380 +                                    DISK_BATCH, diskidx);
381 +                if (num == -1) {
382 +                        sg_set_error_with_errno(SG_ERROR_PSTAT,
383 +                                                "pstat_getdisk");
384 +                        return NULL;
385 +                } else if (num == 0) {
386 +                        break;
387 +                }
388 +
389 +                for (i = 0; i < num; i++) {
390 +                        struct pst_diskinfo *di = &pstat_diskinfo[i];
391 +
392 +                        /* Skip "disabled" disks. */
393 +                        if (di->psd_status == 0) {
394 +                                continue;
395 +                        }
396 +        
397 +                        /* We can't seperate the reads from the writes, we'll
398 +                         * just give the same to each. (This value is in
399 +                         * 64-byte chunks according to the pstat header file,
400 +                         * and can wrap to be negative.)
401 +                         */
402 +                        rbytes = wbytes = ((unsigned long) di->psd_dkwds) * 64LL;
403 +        
404 +                        /* Skip unused disks. */
405 +                        if (rbytes == 0 && wbytes == 0) {
406 +                                continue;
407 +                        }
408 +        
409 +                        if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
410 +                                return NULL;
411 +                        }
412 +        
413 +                        diskio_stats_ptr = diskio_stats + num_diskio;
414 +        
415 +                        diskio_stats_ptr->read_bytes = rbytes;
416 +                        diskio_stats_ptr->write_bytes = wbytes;
417 +        
418 +                        diskio_stats_ptr->systime = time(NULL);
419 +        
420 +                        num_diskio++;
421 +        
422 +                        /* FIXME This should use a static cache, like the Linux
423 +                         * code below. */
424 +                        if (diskio_stats_ptr->disk_name == NULL) {
425 +                                dh = opendir("/dev/dsk");
426 +                                if (dh == NULL) {
427 +                                        continue;
428 +                                }
429 +        
430 +                                diskid = (di->psd_dev.psd_major << 24) | di->psd_dev.psd_minor;
431 +                                while (1) {
432 +                                        dinfo = readdir(dh);
433 +                                        if (dinfo == NULL) {
434 +                                                break;
435 +                                        }
436 +                                        snprintf(fullpathbuf, sizeof(fullpathbuf), "/dev/dsk/%s", dinfo->d_name);
437 +                                        if (lstat(fullpathbuf, &lstatinfo) < 0) {
438 +                                                continue;
439 +                                        }
440 +        
441 +                                        if (lstatinfo.st_rdev == diskid) {
442 +                                                if (sg_update_string(&diskio_stats_ptr->disk_name, dinfo->d_name) < 0) {
443 +                                                        return NULL;
444 +                                                }
445 +                                                break;
446 +                                        }
447 +                                }
448 +                                closedir(dh);
449 +        
450 +                                if (diskio_stats_ptr->disk_name == NULL) {
451 +                                        if (sg_update_string(&diskio_stats_ptr->disk_name, di->psd_hw_path.psh_name) < 0) {
452 +                                                return NULL;
453 +                                        }
454 +                                }
455 +                        }
456 +                }
457 +                diskidx = pstat_diskinfo[num - 1].psd_idx + 1;
458 +        }
459 + #endif
460   #ifdef OPENBSD
461          mib[0] = CTL_HW;
462          mib[1] = HW_DISKCOUNT;
463  
464          size = sizeof(diskcount);
465          if (sysctl(mib, MIBSIZE, &diskcount, &size, NULL, 0) < 0) {
466 +                sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKCOUNT");
467                  return NULL;
468          }
469  
# Line 334 | Line 471 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
471          mib[1] = HW_DISKNAMES;
472  
473          if (sysctl(mib, MIBSIZE, NULL, &size, NULL, 0) < 0) {
474 +                sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKNAMES");
475                  return NULL;
476          }
477  
478 <        disknames = malloc(size);
478 >        disknames = sg_malloc(size);
479          if (disknames == NULL) {
480                  return NULL;
481          }
482  
483          if (sysctl(mib, MIBSIZE, disknames, &size, NULL, 0) < 0) {
484 +                sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKNAMES");
485                  return NULL;
486          }
487  
488 <        dk_name = calloc(diskcount, sizeof(char *));
488 >        dk_name = sg_malloc(diskcount * sizeof(char *));
489          bufpp = disknames;
490          for (i = 0; i < diskcount && (name = strsep(&bufpp, ",")) != NULL; i++) {
491                  dk_name[i] = name;
# Line 361 | Line 500 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
500   #endif
501  
502          if (sysctl(mib, MIBSIZE, NULL, &size, NULL, 0) < 0) {
503 +                sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKSTATS");
504                  return NULL;
505          }
506  
# Line 370 | Line 510 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
510          num_disks = size / sizeof(struct diskstats);
511   #endif
512  
513 <        stats = malloc(size);
513 >        stats = sg_malloc(size);
514          if (stats == NULL) {
515                  return NULL;
516          }
517  
518          if (sysctl(mib, MIBSIZE, stats, &size, NULL, 0) < 0) {
519 +                sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKSTATS");
520                  return NULL;
521          }
522  
# Line 388 | Line 529 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
529                  rbytes = stats[i].dk_rbytes;
530                  wbytes = stats[i].dk_wbytes;
531   #else
532 <                /* Before 1.7, NetBSD merged reads and writes. */
532 >                /* Before 2.0, NetBSD merged reads and writes. */
533                  rbytes = wbytes = stats[i].dk_bytes;
534   #endif
535   #else
536 + #ifdef HAVE_DS_RBYTES
537 +                rbytes = stats[i].ds_rbytes;
538 +                wbytes = stats[i].ds_wbytes;
539 + #else
540 +                /* Before 3.5, OpenBSD merged reads and writes */
541                  rbytes = wbytes = stats[i].ds_bytes;
542   #endif
543 + #endif
544  
545                  /* Don't keep stats for disks that have never been used. */
546                  if (rbytes == 0 && wbytes == 0) {
# Line 429 | Line 576 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
576  
577   #if defined(FREEBSD) || defined(DFBSD)
578          if (!stats_init) {
579 <                stats.dinfo=malloc(sizeof(struct devinfo));
579 >                stats.dinfo=sg_malloc(sizeof(struct devinfo));
580                  if(stats.dinfo==NULL) return NULL;
581                  bzero(stats.dinfo, sizeof(struct devinfo));
582                  stats_init = 1;
583          }
584   #ifdef FREEBSD5
585 <        if ((devstat_getdevs(NULL, &stats)) < 0) return NULL;
585 >        if ((devstat_getdevs(NULL, &stats)) < 0) {
586 >                /* FIXME devstat functions return a string error in
587 >                   devstat_errbuf */
588 >                sg_set_error(SG_ERROR_DEVSTAT_GETDEVS, NULL);
589 >                return NULL;
590 >        }
591          /* Not aware of a get all devices, so i said 999. If we ever
592           * find a machine with more than 999 disks, then i'll change
593           * this number :)
594           */
595 <        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;
595 >        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) {
596 >                sg_set_error(SG_ERROR_DEVSTAT_SELECTDEVS, NULL);
597 >                return NULL;
598 >        }
599   #else
600 <        if ((getdevs(&stats)) < 0) return NULL;
600 >        if ((getdevs(&stats)) < 0) {
601 >                sg_set_error(SG_ERROR_DEVSTAT_GETDEVS, NULL);
602 >                return NULL;
603 >        }
604          /* Not aware of a get all devices, so i said 999. If we ever
605           * find a machine with more than 999 disks, then i'll change
606           * this number :)
607           */
608 <        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;
608 >        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) {
609 >                sg_set_error(SG_ERROR_DEVSTAT_SELECTDEVS, NULL);
610 >                return NULL;
611 >        }
612   #endif
613  
614          for(counter=0;counter<stats.dinfo->numdevs;counter++){
# Line 477 | Line 638 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
638   #endif
639                  if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
640                  if (asprintf((&diskio_stats_ptr->disk_name), "%s%d", dev_ptr->device_name, dev_ptr->unit_number) == -1) {
641 +                        sg_set_error_with_errno(SG_ERROR_ASPRINTF, NULL);
642                          return NULL;
643                  }
644                  diskio_stats_ptr->systime=time(NULL);
# Line 488 | Line 650 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
650   #endif
651   #ifdef SOLARIS
652          if ((kc = kstat_open()) == NULL) {
653 <                return NULL;
654 <        }
653 >                sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
654 >                return NULL;
655 >        }
656  
657          for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
658 <                if (!strcmp(ksp->ks_class, "disk")) {
658 >                if (!strcmp(ksp->ks_class, "disk")) {
659  
660                          if(ksp->ks_type != KSTAT_TYPE_IO) continue;
661                          /* We dont want metadevices appearins as num_diskio */
662                          if(strcmp(ksp->ks_module, "md")==0) continue;
663 <                        if((kstat_read(kc, ksp, &kios))==-1){  
663 >                        if((kstat_read(kc, ksp, &kios))==-1){  
664                          }
665                          
666                          if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
# Line 509 | Line 672 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
672                          diskio_stats_ptr->read_bytes=kios.nread;
673                          diskio_stats_ptr->write_bytes=kios.nwritten;
674                          if (sg_update_string(&diskio_stats_ptr->disk_name,
675 <                                             sg_get_svr_from_bsd(ksp->ks_name)) < 0) {
675 >                                             sg_get_svr_from_bsd(ksp->ks_name)) < 0) {
676                                  return NULL;
677                          }
678                          diskio_stats_ptr->systime=time(NULL);
# Line 539 | Line 702 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
702          if (f == NULL) goto out;
703          now = time(NULL);
704  
705 +        if (!re_compiled) {
706 +                if (regcomp(&part_re, "^(.*/)?[^/]*[0-9]$", REG_EXTENDED | REG_NOSUB) != 0) {
707 +                        sg_set_error(SG_ERROR_PARSE, NULL);
708 +                        goto out;
709 +                }
710 +                if (regcomp(&not_part_re, "^(.*/)?[^/0-9]+[0-9]+d[0-9]+$", REG_EXTENDED | REG_NOSUB) != 0) {
711 +                        sg_set_error(SG_ERROR_PARSE, NULL);
712 +                        goto out;
713 +                }
714 +                re_compiled = 1;
715 +        }
716 +
717          while ((line_ptr = sg_f_read_line(f, "")) != NULL) {
718                  char name[100];
544                char *s;
719                  long long rsect, wsect;
720  
721                  int nr = sscanf(line_ptr, format,
# Line 549 | Line 723 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
723                  if (nr < 3) continue;
724  
725                  /* Skip device names ending in numbers, since they're
726 <                   partitions. */
727 <                s = name;
728 <                while (*s != '\0') s++;
729 <                --s;
730 <                if (*s >= '0' && *s <= '9') continue;
726 >                   partitions, unless they match the c0d0 pattern that some
727 >                   RAID devices use. */
728 >                /* FIXME: For 2.6+, we should probably be using sysfs to detect
729 >                   this... */
730 >                if ((regexec(&part_re, name, 0, NULL, 0) == 0)
731 >                    && (regexec(&not_part_re, name, 0, NULL, 0) != 0)) {
732 >                        continue;
733 >                }
734  
735                  if (nr < 5) {
736                          has_pp_stats = 0;
# Line 656 | Line 833 | out:
833   #endif
834  
835   #ifdef CYGWIN
836 +        sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
837          return NULL;
838   #endif
839  
# Line 666 | Line 844 | out:
844  
845   sg_disk_io_stats *sg_get_disk_io_stats_diff(int *entries){
846          VECTOR_DECLARE_STATIC(diff, sg_disk_io_stats, 1,
847 <                              diskio_stat_init, diskio_stat_destroy);
847 >                              diskio_stat_init, diskio_stat_destroy);
848          sg_disk_io_stats *src = NULL, *dest;
849          int i, j, diff_count, new_count;
850  
# Line 726 | Line 904 | sg_disk_io_stats *sg_get_disk_io_stats_diff(int *entri
904  
905          *entries = diff_count;
906          return diff;
907 + }
908 +
909 + int sg_disk_io_compare_name(const void *va, const void *vb) {
910 +        const sg_disk_io_stats *a = (const sg_disk_io_stats *)va;
911 +        const sg_disk_io_stats *b = (const sg_disk_io_stats *)vb;
912 +
913 +        return strcmp(a->disk_name, b->disk_name);
914   }
915  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines