disk metrics for 2.4 kernel

This commit is contained in:
Doug MacEachern 2004-12-05 20:34:51 +00:00
parent bb42c93df4
commit 72b3a4c55b
2 changed files with 103 additions and 19 deletions

View File

@ -24,6 +24,7 @@
#define PROC_PSTATUS "/status" #define PROC_PSTATUS "/status"
#define SYS_BLOCK "/sys/block" #define SYS_BLOCK "/sys/block"
#define PROC_PARTITIONS "/proc/partitions"
/* /*
* /proc/self/stat fields: * /proc/self/stat fields:
@ -130,6 +131,10 @@ int sigar_os_open(sigar_t **sigar)
if (stat(SYS_BLOCK, &sb) == 0) { if (stat(SYS_BLOCK, &sb) == 0) {
(*sigar)->iostat = IOSTAT_SYS; (*sigar)->iostat = IOSTAT_SYS;
} }
else if (stat(PROC_PARTITIONS, &sb) == 0) {
/* XXX file exists does not mean is has the fields */
(*sigar)->iostat = IOSTAT_PARTITIONS;
}
else { else {
(*sigar)->iostat = IOSTAT_NONE; (*sigar)->iostat = IOSTAT_NONE;
} }
@ -1006,42 +1011,57 @@ int sigar_file_system_list_get(sigar_t *sigar,
return SIGAR_OK; return SIGAR_OK;
} }
static int get_iostat_sys(sigar_t *sigar, static char *get_fsdev(sigar_t *sigar,
const char *dirname, const char *dirname,
sigar_file_system_usage_t *fsusage) char *fsdev)
{ {
/* open source is really great */ /* XXX cache this shit */
/* see how intuitive this is */
struct mntent ent; struct mntent ent;
char buf[1025]; /* buffer for strings within ent */ char buf[1025]; /* buffer for strings within ent */
char stat[1025];
FILE *fp; FILE *fp;
char *name, *fsdev = NULL, *ptr; char *ptr = NULL;
int partition, status;
if (!(fp = setmntent(MOUNTED, "r"))) { if (!(fp = setmntent(MOUNTED, "r"))) {
return errno; return NULL;
} }
while (getmntent_r(fp, &ent, buf, sizeof(buf))) { while (getmntent_r(fp, &ent, buf, sizeof(buf))) {
if (strEQ(ent.mnt_dir, dirname)) { if (strEQ(ent.mnt_dir, dirname)) {
fsdev = ent.mnt_fsname; ptr = ent.mnt_fsname;
break; break;
} }
} }
endmntent(fp); endmntent(fp);
if (!fsdev) { if (!ptr) {
return ENOENT; return NULL;
} }
if (!strnEQ(fsdev, "/dev/", 5)) { if (!strnEQ(ptr, "/dev/", 5)) {
return ENOENT; return NULL;
} }
fsdev += 5; ptr += 5;
name = fsdev;
strcpy(fsdev, ptr);
return ptr;
}
static int get_iostat_sys(sigar_t *sigar,
const char *dirname,
sigar_file_system_usage_t *fsusage)
{
char stat[1025], dev[1025];
char *name, *ptr, *fsdev;
int partition, status;
name = fsdev = get_fsdev(sigar, dirname, dev);
if (!name) {
return ENOENT;
}
while (!sigar_isdigit(*fsdev)) { while (!sigar_isdigit(*fsdev)) {
fsdev++; fsdev++;
@ -1052,12 +1072,12 @@ static int get_iostat_sys(sigar_t *sigar,
sprintf(stat, SYS_BLOCK "/%s/%s%d/stat", name, name, partition); sprintf(stat, SYS_BLOCK "/%s/%s%d/stat", name, name, partition);
status = sigar_file2str(stat, buf, sizeof(buf)); status = sigar_file2str(stat, dev, sizeof(dev));
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }
ptr = buf; ptr = dev;
ptr = sigar_skip_token(ptr); ptr = sigar_skip_token(ptr);
fsusage->disk_reads = sigar_strtoul(ptr); fsusage->disk_reads = sigar_strtoul(ptr);
ptr = sigar_skip_token(ptr); ptr = sigar_skip_token(ptr);
@ -1066,6 +1086,49 @@ static int get_iostat_sys(sigar_t *sigar,
return SIGAR_OK; return SIGAR_OK;
} }
static int get_iostat_procp(sigar_t *sigar,
const char *dirname,
sigar_file_system_usage_t *fsusage)
{
FILE *fp;
char buffer[1025], dev[1025];
char *name, *ptr;
int len;
name = get_fsdev(sigar, dirname, dev);
if (!name) {
return ENOENT;
}
len = strlen(name);
if (!(fp = fopen(PROC_PARTITIONS, "r"))) {
return errno;
}
(void)fgets(buffer, sizeof(buffer), fp); /* skip header */
while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
/* major, minor, #blocks */
ptr = sigar_skip_multiple_token(ptr, 3);
SIGAR_SKIP_SPACE(ptr);
if (strnEQ(ptr, name, len)) {
ptr = sigar_skip_token(ptr); /* name */
fsusage->disk_reads = sigar_strtoul(ptr); /* rio */
/* rmerge, rsect, ruse */
ptr = sigar_skip_multiple_token(ptr, 3);
fsusage->disk_writes = sigar_strtoul(ptr); /* wio */
fclose(fp);
return SIGAR_OK;
}
}
fclose(fp);
return ENOENT;
}
#include <sys/vfs.h> #include <sys/vfs.h>
#define SIGAR_FS_BLOCKS_TO_BYTES(buf, f) \ #define SIGAR_FS_BLOCKS_TO_BYTES(buf, f) \
@ -1088,10 +1151,30 @@ int sigar_file_system_usage_get(sigar_t *sigar,
fsusage->free_files = buf.f_ffree; fsusage->free_files = buf.f_ffree;
fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage); fsusage->use_percent = sigar_file_system_usage_calc_used(sigar, fsusage);
if (sigar->iostat == IOSTAT_SYS) { /*
* 2.2 has metrics /proc/stat, but wtf is the device mapping?
* 2.4 has /proc/partitions w/ the metrics.
* 2.6 has /proc/partitions w/o the metrics.
* instead the metrics are within the /proc-like /sys filesystem.
* also has /proc/diskstats
*/
switch (sigar->iostat) {
case IOSTAT_SYS:
if (get_iostat_sys(sigar, dirname, fsusage) == SIGAR_OK) { if (get_iostat_sys(sigar, dirname, fsusage) == SIGAR_OK) {
return SIGAR_OK; return SIGAR_OK;
} }
break;
case IOSTAT_PARTITIONS:
if (get_iostat_procp(sigar, dirname, fsusage) == SIGAR_OK) {
return SIGAR_OK;
}
break;
/*
* case IOSTAT_SOME_OTHER_WIERD_THING:
* break;
*/
case IOSTAT_NONE:
break;
} }
fsusage->disk_reads = fsusage->disk_writes = 0; fsusage->disk_reads = fsusage->disk_writes = 0;

View File

@ -32,6 +32,7 @@ typedef struct {
typedef enum { typedef enum {
IOSTAT_NONE, IOSTAT_NONE,
IOSTAT_PARTITIONS,
IOSTAT_SYS /* 2.6 */ IOSTAT_SYS /* 2.6 */
} linux_iostat_e; } linux_iostat_e;