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.74 by ats, Mon Nov 1 20:36:46 2004 UTC vs.
Revision 1.82 by tdb, Wed Jul 13 13:01:24 2005 UTC

# Line 43 | Line 43
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
# Line 50 | Line 51
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"}
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
# Line 87 | Line 88
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 105 | 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 117 | Line 159 | 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);
161  
120        int valid_type;
162          int num_disks=0;
163   #if defined(LINUX) || defined (SOLARIS) || defined(CYGWIN) || defined(HPUX)
164          FILE *f;
# Line 131 | Line 172 | sg_fs_stats *sg_get_fs_stats(int *entries){
172   #endif
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   #ifdef HAVE_STATVFS
180 <        struct statvfs *mp;
180 >        struct statvfs *mp, **fs;
181   #else
182 <        struct statfs *mp;
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++){
152 <                valid_type = is_valid_fs_type(mp->f_fstypename);
192 >        for(fs = &mp; nummnt--; (*fs)++){
193   #endif
194  
195   #if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
# Line 163 | Line 203 | sg_fs_stats *sg_get_fs_stats(int *entries){
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  
170                valid_type = is_valid_fs_type(mp->mnt_type);
210   #endif
211  
212   #ifdef SOLARIS
# Line 179 | Line 218 | sg_fs_stats *sg_get_fs_stats(int *entries){
218                  if ((statvfs(mp.mnt_mountp, &fs)) !=0){
219                          continue;
220                  }
182                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  
191 #ifdef ALLBSD
192                        if (sg_update_string(&disk_ptr->device_name, mp->f_mntfromname) < 0) {
193                                return NULL;
194                        }
195                        if (sg_update_string(&disk_ptr->fs_type, mp->f_fstypename) < 0) {
196                                return NULL;
197                        }
198                        if (sg_update_string(&disk_ptr->mnt_point, mp->f_mntonname) < 0) {
199                                return NULL;
200                        }
201
202                        disk_ptr->size = (long long)mp->f_bsize * (long long) mp->f_blocks;
203                        disk_ptr->avail = (long long)mp->f_bsize * (long long) mp->f_bavail;
204                        disk_ptr->used = (disk_ptr->size) - ((long long)mp->f_bsize * (long long)mp->f_bfree);
205
206                        disk_ptr->total_inodes=(long long)mp->f_files;
207                        disk_ptr->free_inodes=(long long)mp->f_ffree;
208                        /* Freebsd doesn't have a "available" inodes */
209                        disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
210 #endif
211 #if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
212                        if (sg_update_string(&disk_ptr->device_name, mp->mnt_fsname) < 0) {
213                                return NULL;
214                        }
215                                
216                        if (sg_update_string(&disk_ptr->fs_type, mp->mnt_type) < 0) {  
217                                return NULL;
218                        }
219
220                        if (sg_update_string(&disk_ptr->mnt_point, mp->mnt_dir) < 0) {
221                                return NULL;
222                        }
223                        disk_ptr->size = (long long)fs.f_bsize * (long long)fs.f_blocks;
224                        disk_ptr->avail = (long long)fs.f_bsize * (long long)fs.f_bavail;
225                        disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_bsize * (long long)fs.f_bfree);
226
227                        disk_ptr->total_inodes=(long long)fs.f_files;
228                        disk_ptr->free_inodes=(long long)fs.f_ffree;
229                        /* Linux doesn't have a "available" inodes */
230                        disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
231 #endif
232
233 #ifdef SOLARIS
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, mp.mnt_special) < 0) {
233 >                        if (sg_update_string(&disk_ptr->device_name, SG_MP_DEVNAME(mp)) < 0) {
234                                  return NULL;
235                          }
236 <
242 <                        if (sg_update_string(&disk_ptr->fs_type, mp.mnt_fstype) < 0) {
236 >                        if (sg_update_string(&disk_ptr->fs_type, SG_MP_FSTYPENAME(mp)) < 0) {
237                                  return NULL;
238                          }
239 <        
246 <                        if (sg_update_string(&disk_ptr->mnt_point, mp.mnt_mountp) < 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)fs.f_frsize * (long long)fs.f_blocks;
244 <                        disk_ptr->avail = (long long)fs.f_frsize * (long long)fs.f_bavail;
245 <                        disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_frsize * (long long)fs.f_bfree);
246 <                
247 <                        disk_ptr->total_inodes=(long long)fs.f_files;
248 <                        disk_ptr->used_inodes=disk_ptr->total_inodes - (long long)fs.f_ffree;
249 <                        disk_ptr->free_inodes=(long long)fs.f_favail;
250 < #endif
242 >
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 = 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 >                        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 >
260                          num_disks++;
261                  }
262          }
# Line 316 | Line 318 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
318          long long rbytes = 0, wbytes = 0;
319          struct dirent *dinfo = NULL;
320          struct stat lstatinfo;
321 <        struct pst_diskinfo pstat_diskinfo;
321 >        struct pst_diskinfo pstat_diskinfo[DISK_BATCH];
322          char fullpathbuf[1024] = {0};
323          dev_t diskid;
324          DIR *dh = NULL;
325 <        int disknum = 0;
325 >        int diskidx = 0;
326 >        int num, i;
327   #endif
328   #ifdef SOLARIS
329          kstat_ctl_t *kc;
# Line 336 | 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 370 | Line 375 | sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
375          num_diskio=0;
376  
377   #ifdef HPUX
378 <
379 <        /* The "128" here is arbitrary, it can be increased to any number
380 <           at the expense of only more system calls to pstat(). */
381 <        for (disknum = 0; disknum < 128; disknum++) {
382 <                if (pstat_getdisk(&pstat_diskinfo, sizeof(pstat_diskinfo), 1, disknum) == -1) {
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 <                if (pstat_diskinfo.psd_idx != disknum) {
390 <                        continue;
383 <                }
389 >                for (i = 0; i < num; i++) {
390 >                        struct pst_diskinfo *di = &pstat_diskinfo[i];
391  
392 <                /* Skip "disabled" disks.. */
393 <                if (pstat_diskinfo.psd_status == 0) {
387 <                        continue;
388 <                }
389 <
390 <                /* We can't seperate the reads from the writes, we'll
391 <                   just give the same to each. */
392 <                rbytes = wbytes = (pstat_diskinfo.psd_dkwds * 64);
393 <
394 <                /* Skip unused disks. */
395 <                if (rbytes == 0 && wbytes == 0) {
396 <                        continue;
397 <                }
398 <
399 <                if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
400 <                        return NULL;
401 <                }
402 <
403 <                diskio_stats_ptr = diskio_stats + num_diskio;
404 <
405 <                diskio_stats_ptr->read_bytes = rbytes;
406 <                diskio_stats_ptr->write_bytes = wbytes;
407 <
408 <                diskio_stats_ptr->systime = time(NULL);
409 <
410 <                num_diskio++;
411 <
412 <                if (diskio_stats_ptr->disk_name == NULL) {
413 <                        dh = opendir("/dev/dsk");
414 <                        if (dh == NULL) {
392 >                        /* Skip "disabled" disks. */
393 >                        if (di->psd_status == 0) {
394                                  continue;
395                          }
396 <
397 <                        diskid = (pstat_diskinfo.psd_dev.psd_major << 24) | pstat_diskinfo.psd_dev.psd_minor;
398 <                        while (1) {
399 <                                dinfo = readdir(dh);
400 <                                if (dinfo == NULL) {
401 <                                        break;
402 <                                }
403 <                                snprintf(fullpathbuf, sizeof(fullpathbuf), "/dev/dsk/%s", dinfo->d_name);
404 <                                if (lstat(fullpathbuf, &lstatinfo) < 0) {
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 <                                if (lstatinfo.st_rdev == diskid) {
431 <                                        if (sg_update_string(&diskio_stats_ptr->disk_name, dinfo->d_name) < 0) {
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                                          }
433                                        break;
454                                  }
455                          }
436                        closedir(dh);
437
438                        if (diskio_stats_ptr->disk_name == NULL) {
439                                if (sg_update_string(&diskio_stats_ptr->disk_name, pstat_diskinfo.psd_hw_path.psh_name) < 0) {
440                                        return NULL;
441                                }
442                        }
456                  }
457 +                diskidx = pstat_diskinfo[num - 1].psd_idx + 1;
458          }
459   #endif
460   #ifdef OPENBSD
# Line 688 | 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];
693                char *s;
719                  long long rsect, wsect;
720  
721                  int nr = sscanf(line_ptr, format,
# Line 698 | 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;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines