unsigned *map_cmdline_to_pid;
        unsigned cmdline_num;
        int cmdline_idx;
-       char *saved_cmdlines;
+       char saved_cmdlines[];
 };
 static struct saved_cmdlines_buffer *savedcmd;
 
        strncpy(get_saved_cmdlines(idx), cmdline, TASK_COMM_LEN);
 }
 
-static int allocate_cmdlines_buffer(unsigned int val,
-                                   struct saved_cmdlines_buffer *s)
+static void free_saved_cmdlines_buffer(struct saved_cmdlines_buffer *s)
+{
+       int order = get_order(sizeof(*s) + s->cmdline_num * TASK_COMM_LEN);
+
+       kfree(s->map_cmdline_to_pid);
+       free_pages((unsigned long)s, order);
+}
+
+static struct saved_cmdlines_buffer *allocate_cmdlines_buffer(unsigned int val)
 {
+       struct saved_cmdlines_buffer *s;
+       struct page *page;
+       int orig_size, size;
+       int order;
+
+       /* Figure out how much is needed to hold the given number of cmdlines */
+       orig_size = sizeof(*s) + val * TASK_COMM_LEN;
+       order = get_order(orig_size);
+       size = 1 << (order + PAGE_SHIFT);
+       page = alloc_pages(GFP_KERNEL, order);
+       if (!page)
+               return NULL;
+
+       s = page_address(page);
+       memset(s, 0, sizeof(*s));
+
+       /* Round up to actual allocation */
+       val = (size - sizeof(*s)) / TASK_COMM_LEN;
+       s->cmdline_num = val;
+
        s->map_cmdline_to_pid = kmalloc_array(val,
                                              sizeof(*s->map_cmdline_to_pid),
                                              GFP_KERNEL);
-       if (!s->map_cmdline_to_pid)
-               return -ENOMEM;
-
-       s->saved_cmdlines = kmalloc_array(TASK_COMM_LEN, val, GFP_KERNEL);
-       if (!s->saved_cmdlines) {
-               kfree(s->map_cmdline_to_pid);
-               return -ENOMEM;
+       if (!s->map_cmdline_to_pid) {
+               free_saved_cmdlines_buffer(s);
+               return NULL;
        }
 
        s->cmdline_idx = 0;
-       s->cmdline_num = val;
        memset(&s->map_pid_to_cmdline, NO_CMDLINE_MAP,
               sizeof(s->map_pid_to_cmdline));
        memset(s->map_cmdline_to_pid, NO_CMDLINE_MAP,
               val * sizeof(*s->map_cmdline_to_pid));
 
-       return 0;
+       return s;
 }
 
 static int trace_create_savedcmd(void)
 {
-       int ret;
-
-       savedcmd = kmalloc(sizeof(*savedcmd), GFP_KERNEL);
-       if (!savedcmd)
-               return -ENOMEM;
-
-       ret = allocate_cmdlines_buffer(SAVED_CMDLINES_DEFAULT, savedcmd);
-       if (ret < 0) {
-               kfree(savedcmd);
-               savedcmd = NULL;
-               return -ENOMEM;
-       }
+       savedcmd = allocate_cmdlines_buffer(SAVED_CMDLINES_DEFAULT);
 
-       return 0;
+       return savedcmd ? 0 : -ENOMEM;
 }
 
 int is_tracing_stopped(void)
        return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
 }
 
-static void free_saved_cmdlines_buffer(struct saved_cmdlines_buffer *s)
-{
-       kfree(s->saved_cmdlines);
-       kfree(s->map_cmdline_to_pid);
-       kfree(s);
-}
-
 static int tracing_resize_saved_cmdlines(unsigned int val)
 {
        struct saved_cmdlines_buffer *s, *savedcmd_temp;
 
-       s = kmalloc(sizeof(*s), GFP_KERNEL);
+       s = allocate_cmdlines_buffer(val);
        if (!s)
                return -ENOMEM;
 
-       if (allocate_cmdlines_buffer(val, s) < 0) {
-               kfree(s);
-               return -ENOMEM;
-       }
-
        preempt_disable();
        arch_spin_lock(&trace_cmdline_lock);
        savedcmd_temp = savedcmd;