[RFC][PATCH 2/2] perf,sparc: Use vmalloc to back the mmap() array

From: Peter Zijlstra
Date: Mon Sep 21 2009 - 10:20:19 EST


Implement vmalloc() backed storage for perf_mmap().

Alternatively we could put this code in kernel/perf_counter_vmalloc.c
and conditionally compile that or something, since there really isn't
anything Sparc specific about it.

Suggested-by: David Miller <davem@xxxxxxxxxxxxx>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
LKML-Reference: <new-submission>
---
arch/sparc/kernel/perf_counter.c | 72 +++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)

Index: linux-2.6/arch/sparc/kernel/perf_counter.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/perf_counter.c
+++ linux-2.6/arch/sparc/kernel/perf_counter.c
@@ -14,6 +14,7 @@

#include <linux/perf_counter.h>
#include <linux/kprobes.h>
+#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/kdebug.h>
#include <linux/mutex.h>
@@ -554,3 +555,74 @@ void __init init_hw_perf_counters(void)

register_die_notifier(&perf_counter_nmi_notifier);
}
+
+struct page *perf_mmap_to_page(void *addr)
+{
+ return vmalloc_to_page(addr);
+}
+
+static void perf_mmap_unmark_page(void *addr)
+{
+ struct page *page = vmalloc_to_page(addr);
+
+ page->mapping = NULL;
+}
+
+static void perf_mmap_data_free_work(struct work_struct *work)
+{
+ struct perf_mmap_data *data;
+ void *base;
+ int i;
+
+ data = container_of(work, struct perf_mmap_data, work);
+
+ base = data->user_page;
+ for (i = 0; i < data->nr_pages + 1; i++)
+ perf_mmap_unmark_page(base + (i * PAGE_SIZE));
+
+ vfree(base);
+}
+
+void perf_mmap_data_free(struct perf_mmap_data *data)
+{
+ schedule_work(&data->work);
+}
+
+struct perf_mmap_data *
+perf_mmap_data_alloc(struct perf_counter *counter, int nr_pages)
+{
+ struct perf_mmap_data *data;
+ unsigned long size;
+ void *all_buf;
+ int i;
+
+ WARN_ON(atomic_read(&counter->mmap_count));
+
+ size = sizeof(struct perf_mmap_data);
+ size += nr_pages * sizeof(void *);
+
+ data = kzalloc(size, GFP_KERNEL);
+ if (!data)
+ goto fail;
+
+ INIT_WORK(&data->work, perf_mmap_data_free_work);
+
+ all_buf = vmalloc_user((nr_pages + 1) * PAGE_SIZE);
+ if (!all_buf)
+ goto fail_all_buf;
+
+ data->user_page = all_buf;
+
+ for (i = 0; i < nr_pages; i++)
+ data->data_pages[i] = all_buf + ((i + 1) * PAGE_SIZE);
+
+ data->nr_pages = nr_pages;
+
+ return data;
+
+fail_all_buf:
+ kfree(data);
+
+fail:
+ return NULL;
+}

--

--
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/