Blame sysdeps/linux/fsusage.c

Packit Service 407539
#include <config.h>
Packit Service 407539
#include <glibtop.h>
Packit Service 407539
#include <glibtop/fsusage.h>
Packit Service 407539
#include <glibtop/error.h>
Packit Service 407539
Packit Service 407539
#include "glibtop_private.h"
Packit Service 407539
Packit Service 407539
#include <glib.h>
Packit Service 407539
Packit Service 407539
#include <unistd.h>
Packit Service 407539
#include <sys/types.h>
Packit Service 407539
#include <sys/stat.h>
Packit Service 407539
#include <linux/kdev_t.h>
Packit Service 407539
#include <sys/statvfs.h>
Packit Service 407539
#include <stdio.h>
Packit Service 407539
#include <string.h>
Packit Service 407539
#include <stdlib.h>
Packit Service 407539
#include <errno.h>
Packit Service 407539
#include <mntent.h>
Packit Service 407539
Packit Service 407539
Packit Service 407539
/*
Packit Service 407539
 * Linux 2.6.x
Packit Service 407539
 * linux/Documentation/iostats.txt
Packit Service 407539
 */
Packit Service 407539
Packit Service 407539
Packit Service 407539
Packit Service 407539
Packit Service 407539
static gboolean
Packit Service 407539
get_device(glibtop* server, const char *mountpoint,
Packit Service 407539
	   char* device, size_t device_size)
Packit Service 407539
{
Packit Service 407539
	const struct mntent *mnt;
Packit Service 407539
	FILE *fp;
Packit Service 407539
	gboolean found = FALSE;
Packit Service 407539
Packit Service 407539
	if (!(fp = setmntent(MOUNTED, "r"))) {
Packit Service 407539
		glibtop_warn_io_r(server, "Could not open %s", MOUNTED);
Packit Service 407539
		goto out;
Packit Service 407539
	}
Packit Service 407539
Packit Service 407539
	while ((mnt = getmntent(fp)))
Packit Service 407539
	{
Packit Service 407539
		/* There can be multiple root mount entries, skip the unuseful one */
Packit Service 407539
		if (!strcmp(mnt->mnt_fsname, "rootfs"))
Packit Service 407539
			continue;
Packit Service 407539
Packit Service 407539
		if (!strcmp(mountpoint, mnt->mnt_dir)) {
Packit Service 407539
			if (!strncmp(mnt->mnt_fsname, "/dev/", 5)) {
Packit Service 407539
				g_strlcpy(device, mnt->mnt_fsname + 5, device_size);
Packit Service 407539
				found = TRUE;
Packit Service 407539
			}
Packit Service 407539
			break;
Packit Service 407539
		}
Packit Service 407539
	}
Packit Service 407539
Packit Service 407539
	endmntent(fp);
Packit Service 407539
out:
Packit Service 407539
	return found;
Packit Service 407539
}
Packit Service 407539
Packit Service 407539
Packit Service 407539
/*
Packit Service 407539
  TRUE if device is like "hda3" and then set prefix to "hda".
Packit Service 407539
 */
Packit Service 407539
static gboolean
Packit Service 407539
is_partition(const char* device, char* prefix, size_t prefix_size)
Packit Service 407539
{
Packit Service 407539
	g_strlcpy(prefix, device, prefix_size);
Packit Service 407539
Packit Service 407539
	for ( ; *prefix; prefix++) {
Packit Service 407539
		if (isdigit(*prefix)) {
Packit Service 407539
			*prefix = '\0';
Packit Service 407539
			return TRUE;
Packit Service 407539
		}
Packit Service 407539
	}
Packit Service 407539
Packit Service 407539
	return FALSE;
Packit Service 407539
}
Packit Service 407539
Packit Service 407539
Packit Service 407539
/*
Packit Service 407539
  Bug #539360.
Packit Service 407539
  /sys/.../stat format is partially defined in
Packit Service 407539
  linux/Documentation/block/stat.txt (looks outdated).  Before linux
Packit Service 407539
  2.5.25, /sys/block/%s/stat and /sys/block/%s/%s/stat were not the
Packit Service 407539
  same, but the following commit changed the latter to have the same
Packit Service 407539
  format and broke compatibility.
Packit Service 407539
Packit Service 407539
  Commit 34e8beac92c27d292938065f8375842d2840767c
Packit Service 407539
  Author: Jerome Marchand <jmarchan@redhat.com>
Packit Service 407539
  Date:   Fri Feb 8 11:04:55 2008 +0100
Packit Service 407539
Packit Service 407539
    Enhanced partition statistics: sysfs
Packit Service 407539
Packit Service 407539
    Reports enhanced partition statistics in sysfs.
Packit Service 407539
Packit Service 407539
    Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
Packit Service 407539
Packit Service 407539
    fs/partitions/check.c |   22 +++++++++++++++++++---
Packit Service 407539
    1 files changed, 19 insertions(+), 3 deletions(-)
Packit Service 407539
Packit Service 407539
 */
Packit Service 407539
Packit Service 407539
static void
Packit Service 407539
get_sys_path(glibtop* server, const char *device, char **stat_path, const char **parse_format)
Packit Service 407539
{
Packit Service 407539
	const char* linux_2_6_25_format = "%*llu %*llu %llu %*llu"
Packit Service 407539
					  "%*llu %*llu %llu %*llu";
Packit Service 407539
Packit Service 407539
	char prefix[32];
Packit Service 407539
Packit Service 407539
	if (is_partition(device, prefix, sizeof prefix)) {
Packit Service 407539
Packit Service 407539
		*stat_path = g_strdup_printf("/sys/block/%s/%s/stat",
Packit Service 407539
					     prefix, device);
Packit Service 407539
		if (server->os_version_code < LINUX_VERSION_CODE(2, 6, 25))
Packit Service 407539
			*parse_format = "%*llu %llu %*llu %llu";
Packit Service 407539
		else
Packit Service 407539
			*parse_format = linux_2_6_25_format;
Packit Service 407539
	}
Packit Service 407539
	else
Packit Service 407539
	{
Packit Service 407539
		*stat_path = g_strdup_printf("/sys/block/%s/stat", device);
Packit Service 407539
		if (server->os_version_code < LINUX_VERSION_CODE(2, 6, 25))
Packit Service 407539
			*parse_format = "%*llu %*llu %llu %*llu %*llu %*llu %llu";
Packit Service 407539
		else
Packit Service 407539
			*parse_format = linux_2_6_25_format;
Packit Service 407539
	}
Packit Service 407539
}
Packit Service 407539
Packit Service 407539
Packit Service 407539
Packit Service 407539
static void linux_2_6_0(glibtop *server, glibtop_fsusage *buf, const char *path)
Packit Service 407539
{
Packit Service 407539
	char *filename = NULL;
Packit Service 407539
	const char *format;
Packit Service 407539
	int ret;
Packit Service 407539
	char buffer[BUFSIZ];
Packit Service 407539
	char device[64];
Packit Service 407539
Packit Service 407539
	if (!get_device(server, path, device, sizeof device))
Packit Service 407539
		goto out;
Packit Service 407539
Packit Service 407539
	get_sys_path(server, device, &filename, &format);
Packit Service 407539
Packit Service 407539
	ret = try_file_to_buffer(buffer, sizeof buffer, "%s", filename);
Packit Service 407539
Packit Service 407539
	if (ret < 0) goto out;
Packit Service 407539
Packit Service 407539
	if (sscanf(buffer, format, &buf->read, &buf->write) != 2) {
Packit Service 407539
		glibtop_warn_io_r(server, "Could not parse %s", filename);
Packit Service 407539
		goto out;
Packit Service 407539
	}
Packit Service 407539
Packit Service 407539
	buf->flags |= (1 << GLIBTOP_FSUSAGE_READ) | (1 << GLIBTOP_FSUSAGE_WRITE);
Packit Service 407539
 out:
Packit Service 407539
	g_free(filename);
Packit Service 407539
}
Packit Service 407539
Packit Service 407539
Packit Service 407539
static void linux_2_4_0(glibtop *server, glibtop_fsusage *buf, const char *path)
Packit Service 407539
{
Packit Service 407539
}
Packit Service 407539
Packit Service 407539
Packit Service 407539
static void
Packit Service 407539
get_fsusage_read_write(glibtop *server, glibtop_fsusage *buf, const char *path)
Packit Service 407539
{
Packit Service 407539
  if(server->os_version_code >= LINUX_VERSION_CODE(2, 6, 0))
Packit Service 407539
    {
Packit Service 407539
      linux_2_6_0(server, buf, path);
Packit Service 407539
    }
Packit Service 407539
  else if(server->os_version_code >= LINUX_VERSION_CODE(2, 4, 0))
Packit Service 407539
    {
Packit Service 407539
      linux_2_4_0(server, buf, path);
Packit Service 407539
    }
Packit Service 407539
}
Packit Service 407539
Packit Service 407539
Packit Service 407539
/* the following comes from sysdeps/common/mountlist.c if copyright matters...
Packit Service 407539
 */
Packit Service 407539
Packit Service 407539
static const unsigned long _glibtop_sysdeps_fsusage =
Packit Service 407539
(1L << GLIBTOP_FSUSAGE_BLOCKS) + (1L << GLIBTOP_FSUSAGE_BFREE)
Packit Service 407539
+ (1L << GLIBTOP_FSUSAGE_BAVAIL) + (1L << GLIBTOP_FSUSAGE_FILES)
Packit Service 407539
+ (1L << GLIBTOP_FSUSAGE_FFREE) + (1L << GLIBTOP_FSUSAGE_BLOCK_SIZE);
Packit Service 407539
Packit Service 407539
Packit Service 407539
Packit Service 407539
void
Packit Service 407539
glibtop_get_fsusage_s(glibtop *server, glibtop_fsusage *buf, const char *path)
Packit Service 407539
{
Packit Service 407539
  struct statvfs fsd;
Packit Service 407539
Packit Service 407539
  memset(buf, 0, sizeof(glibtop_fsusage));
Packit Service 407539
Packit Service 407539
  if (statvfs(path, &fsd) < 0) {
Packit Service 407539
    glibtop_warn_r(server, "statvfs '%s' failed: %s", path, strerror (errno));
Packit Service 407539
    return;
Packit Service 407539
  }
Packit Service 407539
Packit Service 407539
  buf->blocks = fsd.f_blocks;
Packit Service 407539
  buf->bfree  = fsd.f_bfree;
Packit Service 407539
  buf->bavail = (fsd.f_bavail > fsd.f_bfree) ? 0 : fsd.f_bavail;
Packit Service 407539
  buf->files  = fsd.f_files;
Packit Service 407539
  buf->ffree  = fsd.f_ffree;
Packit Service 407539
  buf->block_size = fsd.f_bsize;
Packit Service 407539
  buf->flags = _glibtop_sysdeps_fsusage;
Packit Service 407539
Packit Service 407539
  /* setting additional flags is delegated */
Packit Service 407539
  get_fsusage_read_write(server, buf, path);
Packit Service 407539
}