Skip to content

Commit 927e56d

Browse files
committed
ring-buffer: Add set/clear_current_oom_origin() during allocations
As si_mem_available() can say there is enough memory even though the memory available is not useable by the ring buffer, it is best to not kill innocent applications because the ring buffer is taking up all the memory while it is trying to allocate a great deal of memory. If the allocator is user space (because kernel threads can also increase the size of the kernel ring buffer on boot up), then after si_mem_available() says there is enough memory, set the OOM killer to kill the current task if an OOM triggers during the allocation. Link: http://lkml.kernel.org/r/[email protected] Suggested-by: Michal Hocko <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 2a872fa commit 927e56d

File tree

1 file changed

+38
-10
lines changed

1 file changed

+38
-10
lines changed

kernel/trace/ring_buffer.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/hash.h>
2323
#include <linux/list.h>
2424
#include <linux/cpu.h>
25+
#include <linux/oom.h>
2526

2627
#include <asm/local.h>
2728

@@ -1162,35 +1163,60 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
11621163
static int __rb_allocate_pages(long nr_pages, struct list_head *pages, int cpu)
11631164
{
11641165
struct buffer_page *bpage, *tmp;
1166+
bool user_thread = current->mm != NULL;
1167+
gfp_t mflags;
11651168
long i;
11661169

1167-
/* Check if the available memory is there first */
1170+
/*
1171+
* Check if the available memory is there first.
1172+
* Note, si_mem_available() only gives us a rough estimate of available
1173+
* memory. It may not be accurate. But we don't care, we just want
1174+
* to prevent doing any allocation when it is obvious that it is
1175+
* not going to succeed.
1176+
*/
11681177
i = si_mem_available();
11691178
if (i < nr_pages)
11701179
return -ENOMEM;
11711180

1181+
/*
1182+
* __GFP_RETRY_MAYFAIL flag makes sure that the allocation fails
1183+
* gracefully without invoking oom-killer and the system is not
1184+
* destabilized.
1185+
*/
1186+
mflags = GFP_KERNEL | __GFP_RETRY_MAYFAIL;
1187+
1188+
/*
1189+
* If a user thread allocates too much, and si_mem_available()
1190+
* reports there's enough memory, even though there is not.
1191+
* Make sure the OOM killer kills this thread. This can happen
1192+
* even with RETRY_MAYFAIL because another task may be doing
1193+
* an allocation after this task has taken all memory.
1194+
* This is the task the OOM killer needs to take out during this
1195+
* loop, even if it was triggered by an allocation somewhere else.
1196+
*/
1197+
if (user_thread)
1198+
set_current_oom_origin();
11721199
for (i = 0; i < nr_pages; i++) {
11731200
struct page *page;
1174-
/*
1175-
* __GFP_RETRY_MAYFAIL flag makes sure that the allocation fails
1176-
* gracefully without invoking oom-killer and the system is not
1177-
* destabilized.
1178-
*/
1201+
11791202
bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()),
1180-
GFP_KERNEL | __GFP_RETRY_MAYFAIL,
1181-
cpu_to_node(cpu));
1203+
mflags, cpu_to_node(cpu));
11821204
if (!bpage)
11831205
goto free_pages;
11841206

11851207
list_add(&bpage->list, pages);
11861208

1187-
page = alloc_pages_node(cpu_to_node(cpu),
1188-
GFP_KERNEL | __GFP_RETRY_MAYFAIL, 0);
1209+
page = alloc_pages_node(cpu_to_node(cpu), mflags, 0);
11891210
if (!page)
11901211
goto free_pages;
11911212
bpage->page = page_address(page);
11921213
rb_init_page(bpage->page);
1214+
1215+
if (user_thread && fatal_signal_pending(current))
1216+
goto free_pages;
11931217
}
1218+
if (user_thread)
1219+
clear_current_oom_origin();
11941220

11951221
return 0;
11961222

@@ -1199,6 +1225,8 @@ static int __rb_allocate_pages(long nr_pages, struct list_head *pages, int cpu)
11991225
list_del_init(&bpage->list);
12001226
free_buffer_page(bpage);
12011227
}
1228+
if (user_thread)
1229+
clear_current_oom_origin();
12021230

12031231
return -ENOMEM;
12041232
}

0 commit comments

Comments
 (0)