[PATCH 2/2] tools: add gfp mask decoder

From: Cody P Schafer
Date: Tue Jan 08 2013 - 18:24:26 EST


From: Cody P Schafer <jmesmon@xxxxxxxxx>

Allows decoding of gfp_masks printed, for example, when the oom-killer
is invoked.

Example usage:

[ 6.464753] kthreadd invoked oom-killer: gfp_mask=0x1000d0, order=1, oom_score_adj=0

$ ./gfp-decode 0x1000d0
GFP_KERNEL|GFP_KMEMCG

Internally, it reuses some of the ftrace structure for decoding the
gfp_mask.

Signed-off-by: Cody P Schafer <cody@xxxxxxxxxxxxxxxxxx>
---
tools/gfp-decode/.gitignore | 1 +
tools/gfp-decode/Makefile | 11 ++++++
tools/gfp-decode/gfp-decode.c | 89 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+)
create mode 100644 tools/gfp-decode/.gitignore
create mode 100644 tools/gfp-decode/Makefile
create mode 100644 tools/gfp-decode/gfp-decode.c

diff --git a/tools/gfp-decode/.gitignore b/tools/gfp-decode/.gitignore
new file mode 100644
index 0000000..eca2466
--- /dev/null
+++ b/tools/gfp-decode/.gitignore
@@ -0,0 +1 @@
+/gfp-decode
diff --git a/tools/gfp-decode/Makefile b/tools/gfp-decode/Makefile
new file mode 100644
index 0000000..51f375a
--- /dev/null
+++ b/tools/gfp-decode/Makefile
@@ -0,0 +1,11 @@
+include ../scripts/Makefile.include
+
+all: $(OUTPUT)gfp-decode
+
+CC = $(CROSS_COMPILE)gcc
+ALL_CFLAGS = $(CFLAGS) $(EXTRA_WARNINGS) -Wall -Wextra -I../../include
+
+$(OUTPUT)gfp-decode: gfp-decode.c
+ $(QUIET_CC)$(CC) -o $@ $(ALL_CFLAGS) $(LDFLAGS) $<
+clean:
+ $(RM) $(OUTPUT)gfp-decode
diff --git a/tools/gfp-decode/gfp-decode.c b/tools/gfp-decode/gfp-decode.c
new file mode 100644
index 0000000..4997f22
--- /dev/null
+++ b/tools/gfp-decode/gfp-decode.c
@@ -0,0 +1,89 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../../include/trace/events/gfpflags.h"
+
+typedef unsigned gfp_t; /* from linux/types.h */
+#define __force
+#include "../../include/linux/gfp-flags.h"
+
+/* taken from linux/ftrace_event.h */
+struct trace_print_flags {
+ unsigned long mask;
+ const char *name;
+};
+
+/*
+ * taken from include/trace/ftrace.h
+ * modified to not pass 'p' to ftrace_print_flags_seq().
+ */
+#define __print_flags(flag, delim, flag_array...) \
+ ({ \
+ static const struct trace_print_flags __flags[] = \
+ { flag_array, { -1, NULL } }; \
+ ftrace_print_flags_seq(delim, flag, __flags); \
+ })
+
+/*
+ * taken from kernel/trace/trace_output.c
+ * modified to use standard puts,putc, and printf and remove use of the buffer.
+ */
+static void
+ftrace_print_flags_seq(const char *delim,
+ unsigned long flags,
+ const struct trace_print_flags *flag_array)
+{
+ unsigned long mask;
+ const char *str;
+ int i, first = 1;
+
+ for (i = 0; flag_array[i].name && flags; i++) {
+
+ mask = flag_array[i].mask;
+ if ((flags & mask) != mask)
+ continue;
+
+ str = flag_array[i].name;
+ flags &= ~mask;
+ if (!first && delim)
+ fputs(delim, stdout);
+ else
+ first = 0;
+ fputs(str, stdout);
+ }
+
+ /* check for left over flags */
+ if (flags) {
+ if (!first && delim)
+ fputs(delim, stdout);
+ printf("0x%lx", flags);
+ }
+ putchar('\n');
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ if (argc < 2) {
+ printf("usage: %s <gfp hex mask>..\n", argv[0]);
+ return 1;
+ }
+
+ for (i = 1; i < argc; i++) {
+ char *cur = argv[i];
+ char *r;
+ unsigned long flags;
+ if (cur[0] == '0' && cur[1] == 'x')
+ cur = &cur[2];
+ flags = strtoul(cur, &r, 16);
+ if (*r != '\0') {
+ fprintf(stderr, "skipping arg %d\n", i-1);
+ continue;
+ }
+
+ show_gfp_flags(flags);
+ }
+
+ return 0;
+}
--
1.8.0.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/