]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.16.4/ring-buffer-check-if-memory-is-available-before-allocation.patch
drop drm patch
[thirdparty/kernel/stable-queue.git] / releases / 4.16.4 / ring-buffer-check-if-memory-is-available-before-allocation.patch
CommitLineData
f85a50aa
GKH
1From 2a872fa4e9c8adc79c830e4009e1cc0c013a9d8a Mon Sep 17 00:00:00 2001
2From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
3Date: Mon, 2 Apr 2018 10:33:56 -0400
4Subject: ring-buffer: Check if memory is available before allocation
5
6From: Steven Rostedt (VMware) <rostedt@goodmis.org>
7
8commit 2a872fa4e9c8adc79c830e4009e1cc0c013a9d8a upstream.
9
10The ring buffer is made up of a link list of pages. When making the ring
11buffer bigger, it will allocate all the pages it needs before adding to the
12ring buffer, and if it fails, it frees them and returns an error. This makes
13increasing the ring buffer size an all or nothing action. When this was
14first created, the pages were allocated with "NORETRY". This was to not
15cause any Out-Of-Memory (OOM) actions from allocating the ring buffer. But
16NORETRY was too strict, as the ring buffer would fail to expand even when
17there's memory available, but was taken up in the page cache.
18
19Commit 848618857d253 ("tracing/ring_buffer: Try harder to allocate") changed
20the allocating from NORETRY to RETRY_MAYFAIL. The RETRY_MAYFAIL would
21allocate from the page cache, but if there was no memory available, it would
22simple fail the allocation and not trigger an OOM.
23
24This worked fine, but had one problem. As the ring buffer would allocate one
25page at a time, it could take up all memory in the system before it failed
26to allocate and free that memory. If the allocation is happening and the
27ring buffer allocates all memory and then tries to take more than available,
28its allocation will not trigger an OOM, but if there's any allocation that
29happens someplace else, that could trigger an OOM, even though once the ring
30buffer's allocation fails, it would free up all the previous memory it tried
31to allocate, and allow other memory allocations to succeed.
32
33Commit d02bd27bd33dd ("mm/page_alloc.c: calculate 'available' memory in a
34separate function") separated out si_mem_availble() as a separate function
35that could be used to see how much memory is available in the system. Using
36this function to make sure that the ring buffer could be allocated before it
37tries to allocate pages we can avoid allocating all memory in the system and
38making it vulnerable to OOMs if other allocations are taking place.
39
40Link: http://lkml.kernel.org/r/1522320104-6573-1-git-send-email-zhaoyang.huang@spreadtrum.com
41
42CC: stable@vger.kernel.org
43Cc: linux-mm@kvack.org
44Fixes: 848618857d253 ("tracing/ring_buffer: Try harder to allocate")
45Requires: d02bd27bd33dd ("mm/page_alloc.c: calculate 'available' memory in a separate function")
46Reported-by: Zhaoyang Huang <huangzhaoyang@gmail.com>
47Tested-by: Joel Fernandes <joelaf@google.com>
48Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
49Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
50
51---
52 kernel/trace/ring_buffer.c | 5 +++++
53 1 file changed, 5 insertions(+)
54
55--- a/kernel/trace/ring_buffer.c
56+++ b/kernel/trace/ring_buffer.c
57@@ -1136,6 +1136,11 @@ static int __rb_allocate_pages(long nr_p
58 struct buffer_page *bpage, *tmp;
59 long i;
60
61+ /* Check if the available memory is there first */
62+ i = si_mem_available();
63+ if (i < nr_pages)
64+ return -ENOMEM;
65+
66 for (i = 0; i < nr_pages; i++) {
67 struct page *page;
68 /*