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.19 by ats, Thu Aug 28 21:33:42 2003 UTC vs.
Revision 1.20 by ats, Thu Aug 28 23:05:56 2003 UTC

# Line 296 | Line 296 | diskio_stat_t *diskio_stat_malloc(int needed_entries,
296   static diskio_stat_t *diskio_stats=NULL;        
297   static int num_diskio=0;        
298  
299 + #ifdef LINUX
300 + typedef struct {
301 +        int major;
302 +        int minor;
303 + } partition;
304 + #endif
305 +
306   diskio_stat_t *get_diskio_stats(int *entries){
307  
308          static int sizeof_diskio_stats=0;
# Line 311 | Line 318 | diskio_stat_t *get_diskio_stats(int *entries){
318          char *line_ptr;
319          int major, minor;
320          char dev_letter;
321 +        int has_pp_stats = 1;
322 +        static partition *parts = NULL;
323 +        static int alloc_parts = 0;
324 +        int i, n;
325 +        time_t now;
326   #endif
327   #ifdef FREEBSD
328          struct statinfo stats;
# Line 393 | Line 405 | diskio_stat_t *get_diskio_stats(int *entries){
405   #endif
406  
407   #ifdef LINUX
408 <        f=fopen("/proc/stat", "r");
409 <        if(f==NULL){
410 <                *entries=0;
411 <                return NULL;
412 <        }
413 <        if((line_ptr=f_read_line(f, "disk_io:"))==NULL){
414 <                *entries=0;
415 <                fclose(f);
416 <                return NULL;
417 <        }
418 <        while((line_ptr=strchr(line_ptr, ' '))!=NULL){
419 <                line_ptr++;
420 <                if(*line_ptr=='\0'){
421 <                        break;
408 >        num_diskio = 0;
409 >        n = 0;
410 >
411 >        /* Read /proc/partitions to find what devices exist. Recent 2.4 kernels
412 >           have statistics in here too, so we can use those directly. */
413 >
414 >        f = fopen("/proc/partitions", "r");
415 >        if (f == NULL) goto out;
416 >        now = time(NULL);
417 >
418 >        while ((line_ptr = f_read_line(f, "")) != NULL) {
419 >                char name[20];
420 >                char *s;
421 >                long long rsect, wsect;
422 >
423 >                int nr = sscanf(line_ptr,
424 >                        " %d %d %*d %19s %*d %*d %lld %*d %*d %*d %lld",
425 >                        &major, &minor, name, &rsect, &wsect);
426 >                if (nr < 3) continue;
427 >                if (nr < 5) {
428 >                        has_pp_stats = 0;
429 >                        rsect = 0;
430 >                        wsect = 0;
431                  }
411                if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){
412                        fclose(f);
413                        *entries=0;
414                        return NULL;
415                }
416                diskio_stats_ptr=diskio_stats+num_diskio;
432  
433 +                /* Skip device names ending in numbers, since they're
434 +                   partitions. */
435 +                s = name;
436 +                while (*s != '\0') s++;
437 +                --s;
438 +                if (*s >= '0' && *s <= '9') continue;
439  
440 <                if((sscanf(line_ptr, "(%d,%d):(%*d, %*d, %lld, %*d, %lld)", \
441 <                        &major, \
442 <                        &minor, \
443 <                        &diskio_stats_ptr->read_bytes, \
444 <                        &diskio_stats_ptr->write_bytes))!=4) {
445 <                                continue;
440 >                diskio_stats = diskio_stat_malloc(n + 1, &sizeof_diskio_stats,
441 >                        diskio_stats);
442 >                if (diskio_stats == NULL) goto out;
443 >                if (n >= alloc_parts) {
444 >                        alloc_parts += 16;
445 >                        parts = realloc(parts, alloc_parts * sizeof *parts);
446 >                        if (parts == NULL) {
447 >                                alloc_parts = 0;
448 >                                goto out;
449 >                        }
450                  }
451  
452 <                /* We read the number of blocks. Blocks are stored in 512 bytes */
453 <                diskio_stats_ptr->read_bytes=diskio_stats_ptr->read_bytes*512;
454 <                diskio_stats_ptr->write_bytes=diskio_stats_ptr->write_bytes*512;
452 >                if (diskio_stats[n].disk_name != NULL)
453 >                        free(diskio_stats[n].disk_name);
454 >                diskio_stats[n].disk_name = strdup(name);
455 >                diskio_stats[n].read_bytes = rsect * 512;
456 >                diskio_stats[n].write_bytes = wsect * 512;
457 >                diskio_stats[n].systime = now;
458 >                parts[n].major = major;
459 >                parts[n].minor = minor;
460  
461 <                if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
461 >                n++;
462 >        }
463  
464 <                switch(major){
465 <                        case 2:
466 <                                if(minor==0){
436 <                                        diskio_stats_ptr->disk_name=strdup("fd0");
437 <                                }
438 <                                break;
464 >        if (!has_pp_stats) {
465 >                /* This is an older kernel without stats in /proc/partitions.
466 >                   Read what we can from /proc/stat instead. */
467  
468 <                        case 3:
469 <                                if(minor==0){
470 <                                        diskio_stats_ptr->disk_name=strdup("hda");
471 <                                }else{
472 <                                        diskio_stats_ptr->disk_name=strdup("hdb");
473 <                                }
474 <                                break;
468 >                f = fopen("/proc/stat", "r");
469 >                if (f == NULL) goto out;
470 >                now = time(NULL);
471 >        
472 >                line_ptr = f_read_line(f, "disk_io:");
473 >                if (line_ptr == NULL) goto out;
474 >        
475 >                while((line_ptr=strchr(line_ptr, ' '))!=NULL){
476 >                        long long rsect, wsect;
477  
478 +                        if (*++line_ptr == '\0') break;
479 +        
480 +                        if((sscanf(line_ptr,
481 +                                "(%d,%d):(%*d, %*d, %lld, %*d, %lld)",
482 +                                &major, &minor, &rsect, &wsect)) != 4) {
483 +                                        continue;
484 +                        }
485 +
486 +                        /* Find the corresponding device from earlier.
487 +                           Just to add to the fun, "minor" is actually the disk
488 +                           number, not the device minor, so we need to figure
489 +                           out the real minor number based on the major!
490 +                           This list is not exhaustive; if you're running
491 +                           an older kernel you probably don't have fancy
492 +                           I2O hardware anyway... */
493 +                        switch (major) {
494 +                        case 3:
495 +                        case 21:
496                          case 22:
497 <                                if(minor==0){
498 <                                        diskio_stats_ptr->disk_name=strdup("hdc");
499 <                                }else{
500 <                                        diskio_stats_ptr->disk_name=strdup("hdd");
501 <                                }
497 >                        case 33:
498 >                        case 34:
499 >                        case 36:
500 >                        case 56:
501 >                        case 57:
502 >                        case 88:
503 >                        case 89:
504 >                        case 90:
505 >                        case 91:
506 >                                minor *= 64;
507                                  break;
508 <                        case 8:
509 <                                dev_letter='a'+(minor/16);
457 <                                diskio_stats_ptr->disk_name=malloc(4);
458 <                                snprintf(diskio_stats_ptr->disk_name, 4, "sd%c", dev_letter);
508 >                        case 9:
509 >                        case 43:
510                                  break;
511                          default:
512 <                                /* I have no idea what it is then :) */
462 <                                diskio_stats_ptr->disk_name=malloc(16);
463 <                                snprintf(diskio_stats_ptr->disk_name, 16, "%d %d", major, minor);
512 >                                minor *= 16;
513                                  break;
514 <                }
514 >                        }
515 >                        for (i = 0; i < n; i++) {
516 >                                if (major == parts[i].major
517 >                                        && minor == parts[i].minor)
518 >                                        break;
519 >                        }
520 >                        if (i == n) continue;
521  
522 <                diskio_stats_ptr->systime=time(NULL);
523 <                num_diskio++;
522 >                        /* We read the number of blocks. Blocks are stored in
523 >                           512 bytes */
524 >                        diskio_stats[i].read_bytes = rsect * 512;
525 >                        diskio_stats[i].write_bytes = wsect * 512;
526 >                        diskio_stats[i].systime = now;
527 >                }
528          }
529  
530 <        fclose(f);
530 >        num_diskio = n;
531 > out:
532 >        if (f != NULL) fclose(f);
533  
534   #endif
535          *entries=num_diskio;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines