public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@elte.hu>, Steven Rostedt <rostedt@goodmis.org>,
	akpm@osdl.org, Peter Zijlstra <peterz@infradead.org>,
	Soeren Sandmann Pedersen <sandmann@redhat.com>,
	Pekka Paalanen <pq@iki.fi>, Steven Rostedt <srostedt@redhat.com>
Subject: [PATCH 4/5] ftrace: limit trace entries
Date: Fri, 18 Apr 2008 16:05:42 -0400	[thread overview]
Message-ID: <20080418200850.443055618@goodmis.org> (raw)
In-Reply-To: 20080418200538.788522018@goodmis.org

[-- Attachment #1: ftrace-limit-trace_entries.patch --]
[-- Type: text/plain, Size: 5404 bytes --]

Currently there is no protection from the root user to use up all of
memory for trace buffers. If the root user allocates too many entries,
the OOM killer might start kill off all tasks.

This patch adds an algorith to check the following condition:

 pages_requested > (freeable_memory + current_trace_buffer_pages) / 4

If the above is met then the allocation fails. The above prevents more
than 1/4th of freeable memory from being used by trace buffers.

To determine the freeable_memory, I made determine_dirtyable_memory in
mm/page-writeback.c global.

Special thanks goes to Peter Zijlstra for suggesting the above calculation.

Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
 include/linux/writeback.h |    2 ++
 kernel/trace/trace.c      |   38 ++++++++++++++++++++++++++++++++++++++
 mm/page-writeback.c       |   10 +++++++---
 3 files changed, 47 insertions(+), 3 deletions(-)

Index: linux-sched-devel.git/include/linux/writeback.h
===================================================================
--- linux-sched-devel.git.orig/include/linux/writeback.h	2008-04-18 15:47:21.000000000 -0400
+++ linux-sched-devel.git/include/linux/writeback.h	2008-04-18 15:53:08.000000000 -0400
@@ -105,6 +105,8 @@ extern int vm_highmem_is_dirtyable;
 extern int block_dump;
 extern int laptop_mode;
 
+extern unsigned long determine_dirtyable_memory(void);
+
 extern int dirty_ratio_handler(struct ctl_table *table, int write,
 		struct file *filp, void __user *buffer, size_t *lenp,
 		loff_t *ppos);
Index: linux-sched-devel.git/kernel/trace/trace.c
===================================================================
--- linux-sched-devel.git.orig/kernel/trace/trace.c	2008-04-18 15:50:47.000000000 -0400
+++ linux-sched-devel.git/kernel/trace/trace.c	2008-04-18 15:53:08.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/poll.h>
 #include <linux/gfp.h>
 #include <linux/fs.h>
+#include <linux/writeback.h>
 
 #include <linux/stacktrace.h>
 
@@ -51,6 +52,8 @@ static int trace_free_page(void);
 
 static int tracing_disabled = 1;
 
+static unsigned long tracing_pages_allocated;
+
 long
 ns2usecs(cycle_t nsec)
 {
@@ -2479,12 +2482,41 @@ tracing_entries_write(struct file *filp,
 	}
 
 	if (val > global_trace.entries) {
+		long pages_requested;
+		unsigned long freeable_pages;
+
+		/* make sure we have enough memory before mapping */
+		pages_requested =
+			(val + (ENTRIES_PER_PAGE-1)) / ENTRIES_PER_PAGE;
+
+		/* account for each buffer (and max_tr) */
+		pages_requested *= tracing_nr_buffers * 2;
+
+		/* Check for overflow */
+		if (pages_requested < 0) {
+			cnt = -ENOMEM;
+			goto out;
+		}
+
+		freeable_pages = determine_dirtyable_memory();
+
+		/* we only allow to request 1/4 of useable memory */
+		if (pages_requested >
+		    ((freeable_pages + tracing_pages_allocated) / 4)) {
+			cnt = -ENOMEM;
+			goto out;
+		}
+
 		while (global_trace.entries < val) {
 			if (trace_alloc_page()) {
 				cnt = -ENOMEM;
 				goto out;
 			}
+			/* double check that we don't go over the known pages */
+			if (tracing_pages_allocated > pages_requested)
+				break;
 		}
+
 	} else {
 		/* include the number of entries in val (inc of page entries) */
 		while (global_trace.entries > val + (ENTRIES_PER_PAGE - 1))
@@ -2667,6 +2699,7 @@ static int trace_alloc_page(void)
 	struct page *page, *tmp;
 	LIST_HEAD(pages);
 	void *array;
+	unsigned pages_allocated = 0;
 	int i;
 
 	/* first allocate a page for each CPU */
@@ -2678,6 +2711,7 @@ static int trace_alloc_page(void)
 			goto free_pages;
 		}
 
+		pages_allocated++;
 		page = virt_to_page(array);
 		list_add(&page->lru, &pages);
 
@@ -2689,6 +2723,7 @@ static int trace_alloc_page(void)
 			       "for trace buffer!\n");
 			goto free_pages;
 		}
+		pages_allocated++;
 		page = virt_to_page(array);
 		list_add(&page->lru, &pages);
 #endif
@@ -2710,6 +2745,7 @@ static int trace_alloc_page(void)
 		SetPageLRU(page);
 #endif
 	}
+	tracing_pages_allocated += pages_allocated;
 	global_trace.entries += ENTRIES_PER_PAGE;
 
 	return 0;
@@ -2744,6 +2780,7 @@ static int trace_free_page(void)
 		page = list_entry(p, struct page, lru);
 		ClearPageLRU(page);
 		list_del(&page->lru);
+		tracing_pages_allocated--;
 		__free_page(page);
 
 		tracing_reset(data);
@@ -2761,6 +2798,7 @@ static int trace_free_page(void)
 		page = list_entry(p, struct page, lru);
 		ClearPageLRU(page);
 		list_del(&page->lru);
+		tracing_pages_allocated--;
 		__free_page(page);
 
 		tracing_reset(data);
Index: linux-sched-devel.git/mm/page-writeback.c
===================================================================
--- linux-sched-devel.git.orig/mm/page-writeback.c	2008-04-18 15:47:21.000000000 -0400
+++ linux-sched-devel.git/mm/page-writeback.c	2008-04-18 15:53:08.000000000 -0400
@@ -126,8 +126,6 @@ static void background_writeout(unsigned
 static struct prop_descriptor vm_completions;
 static struct prop_descriptor vm_dirties;
 
-static unsigned long determine_dirtyable_memory(void);
-
 /*
  * couple the period to the dirty_ratio:
  *
@@ -286,7 +284,13 @@ static unsigned long highmem_dirtyable_m
 #endif
 }
 
-static unsigned long determine_dirtyable_memory(void)
+/**
+ * detremine_dirtyable_memory - amount of memory that may be used
+ *
+ * Returns the numebr of pages that can currently be freed and used
+ * by the kernel for direct mappings.
+ */
+unsigned long determine_dirtyable_memory(void)
 {
 	unsigned long x;
 

-- 

  parent reply	other threads:[~2008-04-18 20:10 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-18 20:05 [PATCH 0/5] ftrace update patches Steven Rostedt
2008-04-18 20:05 ` [PATCH 1/5] ftrace: simple clean ups Steven Rostedt
2008-04-18 20:15   ` Andrew Morton
2008-04-19  3:09     ` Steven Rostedt
2008-04-19  3:11     ` [PATCH 1/5 -v2] " Steven Rostedt
2008-04-18 20:05 ` [PATCH 2/5] ftrace: replace simple_strtoul with strict_strtoul Steven Rostedt
2008-04-18 20:05 ` [PATCH 3/5] ftrace: modulize the number of CPU buffers Steven Rostedt
2008-04-18 20:05 ` Steven Rostedt [this message]
2008-04-18 20:19   ` [PATCH 4/5] ftrace: limit trace entries Andrew Morton
2008-04-19  3:12     ` Steven Rostedt
2008-04-19  3:32       ` Andrew Morton
2008-04-19  3:17     ` [PATCH 4/5 -v2] " Steven Rostedt
2008-04-19  6:10     ` [PATCH 4/5] " Ingo Molnar
2008-04-18 20:05 ` [PATCH 5/5] ftrace: comment code Steven Rostedt
2008-04-19  6:11 ` [PATCH 0/5] ftrace update patches Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080418200850.443055618@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    --cc=pq@iki.fi \
    --cc=sandmann@redhat.com \
    --cc=srostedt@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox