implement disk i/o metrics

This commit is contained in:
Doug MacEachern 2004-12-07 05:06:03 +00:00
parent 5630d9a48a
commit 1a4f8ae004
4 changed files with 238 additions and 3 deletions

View File

@ -1,7 +1,7 @@
#include "sigar.h"
#include "sigar_private.h"
#include "sigar_os.h"
#include "sigar_util.h"
#include "sigar_os.h"
int sigar_get_multi_kstats(sigar_t *sigar,
kstat_list_t *kl,

View File

@ -1,7 +1,7 @@
#include "sigar.h"
#include "sigar_private.h"
#include "sigar_os.h"
#include "sigar_util.h"
#include "sigar_os.h"
#define my_pread(fd, ptr, type, offset) \
(pread(fd, ptr, sizeof(type), offset) == sizeof(type))

View File

@ -220,6 +220,8 @@ struct sigar_t {
proc_objname_func_t pobjname;
proc_dirname_func_t pdirname;
proc_exename_func_t pexename;
sigar_cache_t *fsdev;
};
#define kSTAT_uint(v, type) \

View File

@ -1,7 +1,7 @@
#include "sigar.h"
#include "sigar_private.h"
#include "sigar_os.h"
#include "sigar_util.h"
#include "sigar_os.h"
#include <sys/link.h>
#include <sys/lwp.h>
@ -92,6 +92,8 @@ int sigar_os_open(sigar_t **sig)
sigar->pfree = NULL;
sigar->pobjname = NULL;
sigar->fsdev = NULL;
return SIGAR_OK;
}
@ -127,6 +129,9 @@ int sigar_os_close(sigar_t *sigar)
if (sigar->plib) {
dlclose(sigar->plib);
}
if (sigar->fsdev) {
sigar_cache_destroy(sigar->fsdev);
}
free(sigar);
return SIGAR_OK;
}
@ -1116,11 +1121,223 @@ int sigar_file_system_list_get(sigar_t *sigar,
#define SIGAR_FS_BLOCKS_TO_BYTES(buf, f) \
((buf.f * (buf.f_frsize / 512)) >> 1)
typedef struct {
char device[PATH_MAX];
char name[8];
int instance;
} fsdev_path_t;
typedef struct {
char module[8];
int instance;
char partition;
} fs_kstat_t;
static fsdev_path_t *get_fsdev_paths(sigar_t *sigar,
sigar_file_system_list_t *fslist)
{
int i, ndisk, size;
char buffer[BUFSIZ], *ptr;
char *dev, *inst, *drv;
fsdev_path_t *paths, *mapping;
FILE *fp = fopen("/etc/path_to_inst", "r");
if (!fp) {
return NULL;
}
for (i=0, ndisk=0; i<fslist->number; i++) {
sigar_file_system_t *fsp = &fslist->data[i];
if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
ndisk++;
}
}
size = sizeof(*paths) * (ndisk+1);
mapping = paths = malloc(size);
memset(mapping, '\0', size);
while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
/* eat dust java */
char *q;
SIGAR_SKIP_SPACE(ptr);
if (*ptr == '#') {
continue;
}
if (*ptr == '"') {
ptr++;
}
dev = ptr;
if (!(q = strchr(ptr, '"'))) {
continue;
}
ptr = q+1;
*q = '\0';
SIGAR_SKIP_SPACE(ptr);
inst = ptr;
while (sigar_isdigit(*ptr)) {
ptr++;
}
*ptr = '\0';
ptr++;
SIGAR_SKIP_SPACE(ptr);
if (*ptr == '"') {
ptr++;
}
drv = ptr;
if (!(q = strchr(ptr, '"'))) {
continue;
}
*q = '\0';
if (!(strEQ(drv, "sd") ||
strEQ(drv, "ssd") ||
strEQ(drv, "st") ||
strEQ(drv, "cmdk")))
{
continue;
}
paths->instance = atoi(inst);
if (!kstat_lookup(sigar->kc, drv, paths->instance, NULL)) {
continue;
}
SIGAR_SSTRCPY(paths->device, dev);
SIGAR_SSTRCPY(paths->name, drv);
if (--ndisk < 0) {
/* XXX prevent overflow */
break;
}
paths++;
}
fclose(fp);
return mapping;
}
#define FSDEV_ID(sb) (sb.st_ino + sb.st_dev)
static int create_fsdev_cache(sigar_t *sigar)
{
fsdev_path_t *paths, *mapping;
sigar_file_system_list_t fslist;
int i, j;
int status;
sigar->fsdev = sigar_cache_new(15);
status = sigar_file_system_list_get(sigar, &fslist);
if (status != SIGAR_OK) {
return status;
}
if (!(mapping = get_fsdev_paths(sigar, &fslist))) {
return ENOENT;
}
for (i=0; i<fslist.number; i++) {
sigar_file_system_t *fsp = &fslist.data[i];
if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
char device[PATH_MAX+1], *ptr=device;
int len = readlink(fsp->dev_name, device, sizeof(device)-1);
char *s;
char partition;
if (len < 0) {
continue;
}
device[len] = '\0';
while (strnEQ(ptr, "../", 3)) {
ptr += 3;
}
if (strnEQ(ptr, "devices", 7)) {
ptr += 7;
}
if ((s = strchr(ptr, ':'))) {
partition = *(s+1);
}
for (j=0, paths=mapping; paths->name[0]; j++) {
if (strnEQ(paths->device, ptr, strlen(paths->device))) {
sigar_cache_entry_t *ent;
struct stat sb;
int retval = stat(fsp->dir_name, &sb);
fs_kstat_t *fs_kstat;
if (retval == 0) {
fs_kstat = malloc(sizeof(*fs_kstat));
/* e.g. sd9,g
* module == sd
* instance == 9
* partition == 8
*/
SIGAR_SSTRCPY(fs_kstat->module, paths->name);
fs_kstat->instance = paths->instance;
fs_kstat->partition = partition;
ent = sigar_cache_get(sigar->fsdev, FSDEV_ID(sb));
ent->value = fs_kstat;
}
break;
}
paths++;
}
}
}
sigar_file_system_list_destroy(sigar, &fslist);
return SIGAR_OK;
}
static int get_fs_kstat(sigar_t *sigar,
sigar_file_system_usage_t *fsusage,
fs_kstat_t *fsk)
{
kstat_t *ksp;
char *ptr;
kstat_chain_update(sigar->kc);
ksp = kstat_lookup(sigar->kc, fsk->module, fsk->instance, NULL);
if (!ksp) {
return ENXIO;
}
while (ksp) {
if (!strEQ(ksp->ks_module, fsk->module)) {
break; /* chain goes beyond our module */
}
if ((ptr = strchr(ksp->ks_name, ','))) {
if (*(ptr+1) == fsk->partition) {
kstat_io_t io;
kstat_read(sigar->kc, ksp, &io);
fsusage->disk_reads = io.reads;
fsusage->disk_writes = io.writes;
return SIGAR_OK;
}
}
ksp = ksp->ks_next;
}
return ENOENT;
}
int sigar_file_system_usage_get(sigar_t *sigar,
const char *dirname,
sigar_file_system_usage_t *fsusage)
{
struct statvfs buf;
struct stat sb;
sigar_cache_entry_t *ent;
if (statvfs(dirname, &buf) != 0) {
return errno;
@ -1135,6 +1352,22 @@ int sigar_file_system_usage_get(sigar_t *sigar,
SIGAR_DISK_STATS_NOTIMPL(fsusage);
if (!sigar->fsdev) {
if (create_fsdev_cache(sigar) != SIGAR_OK) {
return SIGAR_OK;
}
}
if (stat(dirname, &sb) < 0) {
return SIGAR_OK;
}
ent = sigar_cache_get(sigar->fsdev, FSDEV_ID(sb));
if (ent->value == NULL) {
return SIGAR_OK;
}
get_fs_kstat(sigar, fsusage, (fs_kstat_t *)ent->value);
return SIGAR_OK;
}