aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 82ced406aacf..2824cf48cdca 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -27,6 +27,7 @@
27#include <linux/poll.h> 27#include <linux/poll.h>
28#include <linux/gfp.h> 28#include <linux/gfp.h>
29#include <linux/fs.h> 29#include <linux/fs.h>
30#include <linux/writeback.h>
30 31
31#include <linux/stacktrace.h> 32#include <linux/stacktrace.h>
32 33
@@ -51,6 +52,8 @@ static int trace_free_page(void);
51 52
52static int tracing_disabled = 1; 53static int tracing_disabled = 1;
53 54
55static unsigned long tracing_pages_allocated;
56
54long 57long
55ns2usecs(cycle_t nsec) 58ns2usecs(cycle_t nsec)
56{ 59{
@@ -2591,12 +2594,41 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
2591 } 2594 }
2592 2595
2593 if (val > global_trace.entries) { 2596 if (val > global_trace.entries) {
2597 long pages_requested;
2598 unsigned long freeable_pages;
2599
2600 /* make sure we have enough memory before mapping */
2601 pages_requested =
2602 (val + (ENTRIES_PER_PAGE-1)) / ENTRIES_PER_PAGE;
2603
2604 /* account for each buffer (and max_tr) */
2605 pages_requested *= tracing_nr_buffers * 2;
2606
2607 /* Check for overflow */
2608 if (pages_requested < 0) {
2609 cnt = -ENOMEM;
2610 goto out;
2611 }
2612
2613 freeable_pages = determine_dirtyable_memory();
2614
2615 /* we only allow to request 1/4 of useable memory */
2616 if (pages_requested >
2617 ((freeable_pages + tracing_pages_allocated) / 4)) {
2618 cnt = -ENOMEM;
2619 goto out;
2620 }
2621
2594 while (global_trace.entries < val) { 2622 while (global_trace.entries < val) {
2595 if (trace_alloc_page()) { 2623 if (trace_alloc_page()) {
2596 cnt = -ENOMEM; 2624 cnt = -ENOMEM;
2597 goto out; 2625 goto out;
2598 } 2626 }
2627 /* double check that we don't go over the known pages */
2628 if (tracing_pages_allocated > pages_requested)
2629 break;
2599 } 2630 }
2631
2600 } else { 2632 } else {
2601 /* include the number of entries in val (inc of page entries) */ 2633 /* include the number of entries in val (inc of page entries) */
2602 while (global_trace.entries > val + (ENTRIES_PER_PAGE - 1)) 2634 while (global_trace.entries > val + (ENTRIES_PER_PAGE - 1))
@@ -2776,6 +2808,7 @@ static int trace_alloc_page(void)
2776 struct page *page, *tmp; 2808 struct page *page, *tmp;
2777 LIST_HEAD(pages); 2809 LIST_HEAD(pages);
2778 void *array; 2810 void *array;
2811 unsigned pages_allocated = 0;
2779 int i; 2812 int i;
2780 2813
2781 /* first allocate a page for each CPU */ 2814 /* first allocate a page for each CPU */
@@ -2787,6 +2820,7 @@ static int trace_alloc_page(void)
2787 goto free_pages; 2820 goto free_pages;
2788 } 2821 }
2789 2822
2823 pages_allocated++;
2790 page = virt_to_page(array); 2824 page = virt_to_page(array);
2791 list_add(&page->lru, &pages); 2825 list_add(&page->lru, &pages);
2792 2826
@@ -2798,6 +2832,7 @@ static int trace_alloc_page(void)
2798 "for trace buffer!\n"); 2832 "for trace buffer!\n");
2799 goto free_pages; 2833 goto free_pages;
2800 } 2834 }
2835 pages_allocated++;
2801 page = virt_to_page(array); 2836 page = virt_to_page(array);
2802 list_add(&page->lru, &pages); 2837 list_add(&page->lru, &pages);
2803#endif 2838#endif
@@ -2819,6 +2854,7 @@ static int trace_alloc_page(void)
2819 SetPageLRU(page); 2854 SetPageLRU(page);
2820#endif 2855#endif
2821 } 2856 }
2857 tracing_pages_allocated += pages_allocated;
2822 global_trace.entries += ENTRIES_PER_PAGE; 2858 global_trace.entries += ENTRIES_PER_PAGE;
2823 2859
2824 return 0; 2860 return 0;
@@ -2853,6 +2889,8 @@ static int trace_free_page(void)
2853 page = list_entry(p, struct page, lru); 2889 page = list_entry(p, struct page, lru);
2854 ClearPageLRU(page); 2890 ClearPageLRU(page);
2855 list_del(&page->lru); 2891 list_del(&page->lru);
2892 tracing_pages_allocated--;
2893 tracing_pages_allocated--;
2856 __free_page(page); 2894 __free_page(page);
2857 2895
2858 tracing_reset(data); 2896 tracing_reset(data);