2007-03-13 Benoît Dejean <benoit@placenet.org> * fsusage.c: (get_sys_path), (linux_2_6_0): Fixed stat parsing for md devices. Patch by Martin Bailey <martin@pcalpha.com>. svn path=/trunk/; revision=2566
144 lines
2.6 KiB
C
144 lines
2.6 KiB
C
#include <config.h>
|
|
#include <glibtop.h>
|
|
#include <glibtop/fsusage.h>
|
|
|
|
#include "glibtop_private.h"
|
|
|
|
#include <glib.h>
|
|
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <linux/kdev_t.h>
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
void
|
|
_glibtop_linux_get_fsusage_read_write(glibtop *server,
|
|
glibtop_fsusage *buf,
|
|
const char *path) G_GNUC_INTERNAL;
|
|
|
|
/*
|
|
* Linux 2.6.x
|
|
* linux/Documentation/iostats.txt
|
|
*/
|
|
|
|
|
|
|
|
|
|
static char *
|
|
get_partition(const char *mountpoint)
|
|
{
|
|
FILE *partitions;
|
|
char *name = NULL;
|
|
char line[1024];
|
|
struct stat statb;
|
|
|
|
if(stat(mountpoint, &statb) == -1)
|
|
return NULL;
|
|
|
|
if((partitions = fopen("/proc/partitions", "r")) == NULL)
|
|
return NULL;
|
|
|
|
while(fgets(line, sizeof line, partitions))
|
|
{
|
|
unsigned major, minor;
|
|
char dev[32];
|
|
|
|
if(sscanf(line, "%u %u %*u %31s", &major, &minor, dev) != 3)
|
|
continue;
|
|
|
|
if(MKDEV(major, minor) != statb.st_dev)
|
|
continue;
|
|
|
|
name = g_strdup(dev);
|
|
break;
|
|
}
|
|
|
|
fclose(partitions);
|
|
return name;
|
|
}
|
|
|
|
|
|
static void
|
|
get_sys_path(const char *device, char **stat_path, const char **parse_format)
|
|
{
|
|
if(g_str_has_prefix(device, "hd") || g_str_has_prefix(device, "sd"))
|
|
{
|
|
char *prefix;
|
|
char *path;
|
|
size_t offset;
|
|
|
|
offset = strcspn(device, "0123456789");
|
|
|
|
prefix = g_strdup(device);
|
|
prefix [offset] = '\0';
|
|
|
|
path = g_strdup_printf("/sys/block/%s/%s/stat",
|
|
prefix, device);
|
|
|
|
g_free(prefix);
|
|
|
|
*stat_path = path;
|
|
*parse_format = "%*llu %llu %*llu %llu";
|
|
}
|
|
else
|
|
{
|
|
*stat_path = g_strdup_printf("/sys/block/%s/stat", device);
|
|
*parse_format = "%*llu %*llu %llu %*llu %*llu %*llu %llu";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void linux_2_6_0(glibtop *server, glibtop_fsusage *buf, const char *path)
|
|
{
|
|
char *device;
|
|
char *filename;
|
|
const char *format;
|
|
int ret;
|
|
char buffer[BUFSIZ];
|
|
|
|
device = get_partition(path);
|
|
if(!device) return;
|
|
|
|
get_sys_path(device, &filename, &format);
|
|
g_free(device);
|
|
|
|
ret = try_file_to_buffer(buffer, filename);
|
|
|
|
if(ret < 0) return;
|
|
|
|
if (sscanf(buffer, format, &buf->read, &buf->write) != 2) {
|
|
glibtop_warn_io_r(server, "Could not parse %s", filename);
|
|
return;
|
|
}
|
|
|
|
g_free(filename);
|
|
|
|
buf->flags |= (1 << GLIBTOP_FSUSAGE_READ) | (1 << GLIBTOP_FSUSAGE_WRITE);
|
|
}
|
|
|
|
|
|
static void linux_2_4_0(glibtop *server, glibtop_fsusage *buf, const char *path)
|
|
{
|
|
}
|
|
|
|
|
|
void G_GNUC_INTERNAL
|
|
_glibtop_linux_get_fsusage_read_write(glibtop *server,
|
|
glibtop_fsusage *buf,
|
|
const char *path)
|
|
{
|
|
if(server->os_version_code >= LINUX_VERSION_CODE(2, 6, 0))
|
|
{
|
|
linux_2_6_0(server, buf, path);
|
|
}
|
|
else if(server->os_version_code >= LINUX_VERSION_CODE(2, 4, 0))
|
|
{
|
|
linux_2_4_0(server, buf, path);
|
|
}
|
|
}
|