From: Cody P Schafer <[email protected]>

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 <[email protected]>
---
 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to