diff options
-rw-r--r-- | sysdeps/linux/ChangeLog | 6 | ||||
-rw-r--r-- | sysdeps/linux/fsusage.c | 120 |
2 files changed, 81 insertions, 45 deletions
diff --git a/sysdeps/linux/ChangeLog b/sysdeps/linux/ChangeLog index 8de4e6b5..8641029e 100644 --- a/sysdeps/linux/ChangeLog +++ b/sysdeps/linux/ChangeLog @@ -1,3 +1,9 @@ +2005-01-13 Benoît Dejean <TazForEver@dlfp.org> + + * fsusage.c: (get_partition), (get_sys_path), (linux_2_6_0): Reworked. + Should works with IDE, SCSI. DM support is ready, but i don't know why + their /stat is empty ... + 2005-01-12 Benoît Dejean <TazForEver@dlfp.org> * procopenfiles.c: (get_all_sockets), diff --git a/sysdeps/linux/fsusage.c b/sysdeps/linux/fsusage.c index e6035577..1be17cf8 100644 --- a/sysdeps/linux/fsusage.c +++ b/sysdeps/linux/fsusage.c @@ -5,9 +5,10 @@ #include <glib.h> -#include <mntent.h> -#include <fcntl.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <linux/kdev_t.h> #include <stdio.h> #include <string.h> @@ -24,68 +25,97 @@ _glibtop_linux_get_fsusage_read_write(glibtop *server, * linux/Documentation/iostats.txt */ -static void linux_2_6_0(glibtop *server, glibtop_fsusage *buf, const char *path) + + + +static char * +get_partition(const char *mountpoint) { - FILE *mtab = setmntent("/etc/mtab", "r"); + FILE *partitions; + char *name = NULL; + char line[1024]; + struct stat statb; - struct mntent *emnt; + if(stat(mountpoint, &statb) == -1) + return NULL; - while((emnt = getmntent(mtab)) != NULL) - { - if(strcmp(emnt->mnt_dir, path) == 0) - { - char filename[64]; /* magic */ + g_return_val_if_fail((partitions = fopen("/proc/partitions", "r")), 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; - char buffer[1024]; /* magic */ - char *p; + name = g_strdup(dev); + break; + } - char device[32]; /* magic */ - unsigned partition; + fclose(partitions); + return name; +} + + +static char * +get_sys_path(const char *device) +{ + if(g_str_has_prefix(device, "hd") || g_str_has_prefix(device, "sd")) + { + char *prefix; + char *path; + size_t offset; - const char *devname = emnt->mnt_fsname; - size_t offset; + offset = strcspn(device, "0123456789"); - /* - we only deal with /dev block devices "/dev/<DEVICE><PARTITION>" - i don't know if other block devices such as network block - devices provide this kind of information. - */ + prefix = g_strdup(device); + prefix [offset] = '\0'; - if(!g_str_has_prefix(devname, "/dev/")) - break; + path = g_strdup_printf("/sys/block/%s/%s/stat", + prefix, device); - /* skip the "/dev/" */ - devname += sizeof "/dev/" - 1; + g_free(prefix); + return path; - g_strlcpy(device, devname, sizeof device); + } + else + { + return g_strdup_printf("/sys/block/%s/stat", device); + } +} - offset = strcspn(devname, "0123456789"); - partition = strtoul(devname + offset, NULL, 0); - device[offset] = '\0'; - if((size_t) g_snprintf(filename, sizeof filename, - "/sys/block/%s/%s%u/stat", - device, device, partition) >= sizeof filename) - break; +static void linux_2_6_0(glibtop *server, glibtop_fsusage *buf, const char *path) +{ + char *device; + char *filename; + int ret; + char buffer[BUFSIZ]; + char *p; + device = get_partition(path); + if(!device) return; - if(try_file_to_buffer(buffer, filename) < 0) - break; + filename = get_sys_path(device); + g_free(device); - p = buffer; - p = skip_token(p); - buf->read = strtoull(p, &p, 0); - p = skip_token(p); - buf->write = strtoull(p, &p, 0); + ret = try_file_to_buffer(buffer, filename); + g_free(filename); - buf->flags |= (1 << GLIBTOP_FSUSAGE_READ) | (1 << GLIBTOP_FSUSAGE_WRITE); + if(ret < 0) return; - break; - } - } + p = buffer; + p = skip_token(p); + buf->read = strtoull(p, &p, 0); + p = skip_token(p); + buf->write = strtoull(p, &p, 0); - endmntent(mtab); + buf->flags |= (1 << GLIBTOP_FSUSAGE_READ) | (1 << GLIBTOP_FSUSAGE_WRITE); } |