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.72 by ats, Sun Jul 18 21:30:11 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
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 104 | 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  
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   #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++){
139 <                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  
153                valid_type = is_valid_fs_type(mp->mnt_type);
210   #endif
211  
212   #ifdef SOLARIS
# Line 162 | Line 218 | sg_fs_stats *sg_get_fs_stats(int *entries){
218                  if ((statvfs(mp.mnt_mountp, &fs)) !=0){
219                          continue;
220                  }
165                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  
174 #ifdef ALLBSD
175                        if (sg_update_string(&disk_ptr->device_name, mp->f_mntfromname) < 0) {
176                                return NULL;
177                        }
178                        if (sg_update_string(&disk_ptr->fs_type, mp->f_fstypename) < 0) {
179                                return NULL;
180                        }
181                        if (sg_update_string(&disk_ptr->mnt_point, mp->f_mntonname) < 0) {
182                                return NULL;
183                        }
184
185                        disk_ptr->size = (long long)mp->f_bsize * (long long) mp->f_blocks;
186                        disk_ptr->avail = (long long)mp->f_bsize * (long long) mp->f_bavail;
187                        disk_ptr->used = (disk_ptr->size) - ((long long)mp->f_bsize * (long long)mp->f_bfree);
188
189                        disk_ptr->total_inodes=(long long)mp->f_files;
190                        disk_ptr->free_inodes=(long long)mp->f_ffree;
191                        /* Freebsd doesn't have a "available" inodes */
192                        disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
193 #endif
194 #if defined(LINUX) || defined(CYGWIN)
195                        if (sg_update_string(&disk_ptr->device_name, mp->mnt_fsname) < 0) {
196                                return NULL;
197                        }
198                                
199                        if (sg_update_string(&disk_ptr->fs_type, mp->mnt_type) < 0) {  
200                                return NULL;
201                        }
202
203                        if (sg_update_string(&disk_ptr->mnt_point, mp->mnt_dir) < 0) {
204                                return NULL;
205                        }
206                        disk_ptr->size = (long long)fs.f_bsize * (long long)fs.f_blocks;
207                        disk_ptr->avail = (long long)fs.f_bsize * (long long)fs.f_bavail;
208                        disk_ptr->used = (disk_ptr->size) - ((long long)fs.f_bsize * (long long)fs.f_bfree);
209
210                        disk_ptr->total_inodes=(long long)fs.f_files;
211                        disk_ptr->free_inodes=(long long)fs.f_ffree;
212                        /* Linux doesn't have a "available" inodes */
213                        disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes;
214 #endif
215
216 #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 <
225 <                        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 <        
229 <                        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 246 | Line 265 | sg_fs_stats *sg_get_fs_stats(int *entries){
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)
268 > #if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
269          endmntent(f);
270   #endif
271   #if defined(SOLARIS)
# Line 295 | 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;
# Line 309 | 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 342 | 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;
# Line 587 | 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];
592                char *s;
719                  long long rsect, wsect;
720  
721                  int nr = sscanf(line_ptr, format,
# Line 597 | 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