linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
From: Jaegeuk Kim <jaegeuk@kernel.org>
To: linux-f2fs-devel@lists.sourceforge.net
Cc: Jaegeuk Kim <jaegeuk@motorola.com>
Subject: [PATCH 2/2] parse.f2fs: add a tool to parse IO traces made by runtime f2fs
Date: Sun, 21 Dec 2014 08:37:14 -0800	[thread overview]
Message-ID: <1419179834-3345-2-git-send-email-jaegeuk@kernel.org> (raw)
In-Reply-To: <1419179834-3345-1-git-send-email-jaegeuk@kernel.org>

From: Jaegeuk Kim <jaegeuk@motorola.com>

This patch adds parse.f2fs to retrieve process information and an amount
of data reads and writes from given IO trace got by f2fs.

Signed-off-by: Jaegeuk Kim <jaegeuk@motorola.com>
---
 tools/Makefile.am     |   3 +-
 tools/f2fs_io_parse.c | 322 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 tools/f2fs_io_parse.c

diff --git a/tools/Makefile.am b/tools/Makefile.am
index 1ead174..69a0bb1 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -2,6 +2,7 @@
 
 AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include
 AM_CFLAGS = -Wall
-sbin_PROGRAMS = f2fstat fibmap.f2fs
+sbin_PROGRAMS = f2fstat fibmap.f2fs parse.f2fs
 f2fstat_SOURCES = f2fstat.c
 fibmap_f2fs_SOURCES = fibmap.c
+parse_f2fs_SOURCES = f2fs_io_parse.c
diff --git a/tools/f2fs_io_parse.c b/tools/f2fs_io_parse.c
new file mode 100644
index 0000000..7f97270
--- /dev/null
+++ b/tools/f2fs_io_parse.c
@@ -0,0 +1,322 @@
+/*
+ * f2fs IO tracer
+ *
+ * Copyright (c) 2014 Motorola Mobility
+ * Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define _LARGEFILE64_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <locale.h>
+
+#define P_NAMELEN	16
+
+/* For global trace methods */
+enum show_type {
+	SHOW_PID,
+	SHOW_FTYPE,
+	SHOW_ALL,
+};
+
+enum trace_types {
+	TP_PID,
+	TP_IOS,
+	TP_MAX,
+};
+
+struct tps {
+	enum trace_types type;
+	const char *name;
+};
+
+struct tps trace_points[] = {
+	{ TP_PID,	"f2fs_trace_pid" },
+	{ TP_IOS,	"f2fs_trace_ios" },
+};
+
+/* For f2fs_trace_pid and f2fs_trace_ios */
+enum rw_type {
+	READ,
+	WRITE,
+	MAX_RW,
+};
+
+enum file_type {
+	__NORMAL_FILE,
+	__DIR_FILE,
+	__NODE_FILE,
+	__META_FILE,
+	__ATOMIC_FILE,
+	__VOLATILE_FILE,
+	__MISC_FILE,
+	__NR_FILES,
+};
+
+char *file_type_string[] = {
+	"User      ",
+	"Dir       ",
+	"Node      ",
+	"Meta      ",
+	"Atomic    ",
+	"Voltile   ",
+	"Misc      ",
+};
+
+struct pid_ent {
+	int pid;
+	char name[P_NAMELEN];
+	unsigned long long io[__NR_FILES][MAX_RW];
+	unsigned long long total_io[MAX_RW];
+	LIST_ENTRY(pid_ent) ptr;
+};
+
+/* global variables */
+int major = 0, minor = 0;
+int show_option = SHOW_ALL;
+unsigned long long total_io[__NR_FILES][MAX_RW];
+
+LIST_HEAD(plist, pid_ent) pid_info;
+
+/* Functions */
+static inline int atoh(char *str)
+{
+	int val;
+	sscanf(str, "%x", &val);
+	return val;
+}
+
+static void do_init()
+{
+	struct pid_ent *misc;
+
+	misc = calloc(1, sizeof(struct pid_ent));
+	assert(misc);
+
+	LIST_INIT(&pid_info);
+	LIST_INSERT_HEAD(&pid_info, misc, ptr);
+}
+
+void show_usage()
+{
+	printf("\nUsage: parse.f2fs [options] log_file\n");
+	printf("[options]:\n");
+	printf("  -a RW sorted by pid & file types\n");
+	printf("  -f RW sorted by file types\n");
+	printf("  -p RW sorted by pid\n");
+	printf("  -m major number\n");
+	printf("  -n minor number\n");
+	exit(1);
+}
+
+static int parse_options(int argc, char *argv[])
+{
+	const char *option_string = "fm:n:p";
+	int option = 0;
+
+	while ((option = getopt(argc, argv, option_string)) != EOF) {
+		switch (option) {
+		case 'f':
+			show_option = SHOW_FTYPE;
+			break;
+		case 'm':
+			major = atoh(optarg);
+			break;
+		case 'n':
+			minor = atoh(optarg);
+			break;
+		case 'p':
+			show_option = SHOW_PID;
+			break;
+		default:
+			printf("\tError: Unknown option %c\n", option);
+			show_usage();
+			break;
+		}
+	}
+	if ((optind + 1) != argc) {
+		printf("\tError: Log file is not specified.\n");
+		show_usage();
+	}
+	return optind;
+}
+
+struct pid_ent *get_pid_entry(int pid)
+{
+	struct pid_ent *entry;
+
+	LIST_FOREACH(entry, &pid_info, ptr) {
+		if (entry->pid == pid)
+			return entry;
+	}
+	return LIST_FIRST(&pid_info);
+}
+
+static void handle_tp_pid(char *ptr)
+{
+	struct pid_ent *pent;
+
+	pent = calloc(1, sizeof(struct pid_ent));
+	assert(pent);
+
+	ptr = strtok(NULL, " ");
+	pent->pid = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	strcpy(pent->name, ptr);
+
+	LIST_INSERT_HEAD(&pid_info, pent, ptr);
+}
+
+static void handle_tp_ios(char *ptr)
+{
+	int pid, type, rw, len;
+	struct pid_ent *p;
+
+	ptr = strtok(NULL, " ");
+	pid = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	ptr = strtok(NULL, " ");
+	type = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	rw = atoh(ptr);
+
+	ptr = strtok(NULL, " ");
+	/* unsigned long long blkaddr = atoh(ptr); */
+
+	ptr = strtok(NULL, " ");
+	len = atoh(ptr);
+
+	/* update per-pid stat */
+	p = get_pid_entry(pid);
+	p->io[type][rw & 0x1] += len;
+	p->total_io[rw & 0x1] += len;
+
+	/* update total stat */
+	total_io[type][rw & 0x1] += len;
+}
+
+static void do_parse(FILE *file)
+{
+	char line[300];
+	char *ptr;
+	int i;
+
+	while (fgets(line, sizeof(line), file) != NULL) {
+		ptr = strtok(line, ":");
+
+		ptr = strtok(NULL, " :");
+
+		for (i = 0; i < TP_MAX; i++) {
+			if (!strcmp(ptr, trace_points[i].name))
+				break;
+		}
+		if (i == TP_MAX)
+			continue;
+		ptr = strtok(NULL, " :");
+		if (major && major != atoh(ptr))
+			continue;
+		ptr = strtok(NULL, " :");
+		if (minor && minor != atoh(ptr))
+			continue;
+
+		switch (i) {
+		case TP_PID:
+			handle_tp_pid(ptr);
+			break;
+		case TP_IOS:
+			handle_tp_ios(ptr);
+			break;
+		}
+	}
+}
+
+static void __print_pid()
+{
+	struct pid_ent *entry;
+	int i;
+
+	setlocale(LC_ALL, "");
+	printf("%8s %16s %17s ||", "PID", "NAME", "R/W in 4KB");
+	for (i = 0; i < __NR_FILES; i++)
+		printf(" %17s |", file_type_string[i]);
+	printf("\n");
+
+	LIST_FOREACH(entry, &pid_info, ptr) {
+		printf("%8x %16s %'8lld %'8lld ||",
+				entry->pid, entry->name,
+				entry->total_io[READ],
+				entry->total_io[WRITE]);
+		for (i = 0; i < __NR_FILES; i++)
+			printf(" %'8lld %'8lld |",
+				entry->io[i][READ],
+				entry->io[i][WRITE]);
+		printf("\n");
+	}
+}
+
+static void __print_ftype()
+{
+	int i;
+
+	setlocale(LC_ALL, "");
+	printf("\n===== Data R/W in 4KB accoring to File types =====\n");
+	for (i = 0; i < __NR_FILES; i++)
+		printf(" %17s |", file_type_string[i]);
+	printf("\n");
+
+	for (i = 0; i < __NR_FILES; i++)
+		printf(" %'8lld %'8lld |",
+				total_io[i][READ],
+				total_io[i][WRITE]);
+	printf("\n");
+}
+
+static void do_print()
+{
+	switch (show_option) {
+	case SHOW_PID:
+		__print_pid();
+		break;
+	case SHOW_FTYPE:
+		__print_ftype();
+		break;
+	case SHOW_ALL:
+		__print_pid();
+		printf("\n\n");
+		__print_ftype();
+		break;
+	}
+}
+
+int main(int argc, char **argv)
+{
+	FILE *file;
+	int opt;
+
+	opt = parse_options(argc, argv);
+
+	file = fopen(argv[opt], "r");
+	if (!file) {
+		perror("open log file");
+		exit(EXIT_FAILURE);
+	}
+
+	do_init();
+
+	do_parse(file);
+
+	do_print();
+
+	fclose(file);
+	return 0;
+}
-- 
2.1.1


------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk

      reply	other threads:[~2014-12-21 16:37 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-21 16:37 [PATCH 1/2] dump.f2fs: dump owner of data given block address Jaegeuk Kim
2014-12-21 16:37 ` Jaegeuk Kim [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1419179834-3345-2-git-send-email-jaegeuk@kernel.org \
    --to=jaegeuk@kernel.org \
    --cc=jaegeuk@motorola.com \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).