Merge branch 'akpm' (patches from Andrew)

Merge misc updates from Andrew Morton:

 - a few misc things

 - ocfs2 updates

 - most of MM

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (159 commits)
  tools/testing/selftests/proc/proc-self-syscall.c: remove duplicate include
  proc: more robust bulk read test
  proc: test /proc/*/maps, smaps, smaps_rollup, statm
  proc: use seq_puts() everywhere
  proc: read kernel cpu stat pointer once
  proc: remove unused argument in proc_pid_lookup()
  fs/proc/thread_self.c: code cleanup for proc_setup_thread_self()
  fs/proc/self.c: code cleanup for proc_setup_self()
  proc: return exit code 4 for skipped tests
  mm,mremap: bail out earlier in mremap_to under map pressure
  mm/sparse: fix a bad comparison
  mm/memory.c: do_fault: avoid usage of stale vm_area_struct
  writeback: fix inode cgroup switching comment
  mm/huge_memory.c: fix "orig_pud" set but not used
  mm/hotplug: fix an imbalance with DEBUG_PAGEALLOC
  mm/memcontrol.c: fix bad line in comment
  mm/cma.c: cma_declare_contiguous: correct err handling
  mm/page_ext.c: fix an imbalance with kmemleak
  mm/compaction: pass pgdat to too_many_isolated() instead of zone
  mm: remove zone_lru_lock() function, access ->lru_lock directly
  ...
Šī revīzija ir iekļauta:
Linus Torvalds
2019-03-06 10:31:36 -08:00
revīzija 8dcd175bc3
213 mainīti faili ar 4924 papildinājumiem un 2321 dzēšanām

Parādīt failu

@@ -222,7 +222,6 @@ config ENABLE_MUST_CHECK
config FRAME_WARN
int "Warn for stack frames larger than (needs gcc 4.4)"
range 0 8192
default 3072 if KASAN_EXTRA
default 2048 if GCC_PLUGIN_LATENT_ENTROPY
default 1280 if (!64BIT && PARISC)
default 1024 if (!64BIT && !PARISC)
@@ -266,23 +265,6 @@ config UNUSED_SYMBOLS
you really need it, and what the merge plan to the mainline kernel for
your module is.
config PAGE_OWNER
bool "Track page owner"
depends on DEBUG_KERNEL && STACKTRACE_SUPPORT
select DEBUG_FS
select STACKTRACE
select STACKDEPOT
select PAGE_EXTENSION
help
This keeps track of what call chain is the owner of a page, may
help to find bare alloc_page(s) leaks. Even if you include this
feature on your build, it is disabled in default. You should pass
"page_owner=on" to boot parameter in order to enable it. Eats
a fair amount of memory if enabled. See tools/vm/page_owner_sort.c
for user-space helper.
If unsure, say N.
config DEBUG_FS
bool "Debug Filesystem"
help
@@ -1876,6 +1858,19 @@ config TEST_LKM
If unsure, say N.
config TEST_VMALLOC
tristate "Test module for stress/performance analysis of vmalloc allocator"
default n
depends on MMU
depends on m
help
This builds the "test_vmalloc" module that should be used for
stress and performance analysis. So, any new change for vmalloc
subsystem can be evaluated from performance and stability point
of view.
If unsure, say N.
config TEST_USER_COPY
tristate "Test user/kernel boundary protections"
depends on m

Parādīt failu

@@ -78,16 +78,6 @@ config KASAN_SW_TAGS
endchoice
config KASAN_EXTRA
bool "KASAN: extra checks"
depends on KASAN_GENERIC && DEBUG_KERNEL && !COMPILE_TEST
help
This enables further checks in generic KASAN, for now it only
includes the address-use-after-scope check that can lead to
excessive kernel stack usage, frame size warnings and longer
compile time.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715
choice
prompt "Instrumentation type"
depends on KASAN

Parādīt failu

@@ -60,6 +60,7 @@ UBSAN_SANITIZE_test_ubsan.o := y
obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
obj-$(CONFIG_TEST_LKM) += test_module.o
obj-$(CONFIG_TEST_VMALLOC) += test_vmalloc.o
obj-$(CONFIG_TEST_OVERFLOW) += test_overflow.o
obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
obj-$(CONFIG_TEST_SORT) += test_sort.o

Parādīt failu

@@ -5,6 +5,7 @@
#include <linux/cpumask.h>
#include <linux/export.h>
#include <linux/memblock.h>
#include <linux/numa.h>
/**
* cpumask_next - get the next cpu in a cpumask
@@ -206,7 +207,7 @@ unsigned int cpumask_local_spread(unsigned int i, int node)
/* Wrap: we always want a cpu. */
i %= num_online_cpus();
if (node == -1) {
if (node == NUMA_NO_NODE) {
for_each_cpu(cpu, cpu_online_mask)
if (i-- == 0)
return cpu;

Parādīt failu

@@ -480,29 +480,6 @@ static noinline void __init copy_user_test(void)
kfree(kmem);
}
static noinline void __init use_after_scope_test(void)
{
volatile char *volatile p;
pr_info("use-after-scope on int\n");
{
int local = 0;
p = (char *)&local;
}
p[0] = 1;
p[3] = 1;
pr_info("use-after-scope on array\n");
{
char local[1024] = {0};
p = local;
}
p[0] = 1;
p[1023] = 1;
}
static noinline void __init kasan_alloca_oob_left(void)
{
volatile int i = 10;
@@ -682,7 +659,6 @@ static int __init kmalloc_tests_init(void)
kasan_alloca_oob_right();
ksize_unpoisons_memory();
copy_user_test();
use_after_scope_test();
kmem_cache_double_free();
kmem_cache_invalid_free();
kasan_memchr();

551
lib/test_vmalloc.c Parasts fails
Parādīt failu

@@ -0,0 +1,551 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Test module for stress and analyze performance of vmalloc allocator.
* (C) 2018 Uladzislau Rezki (Sony) <urezki@gmail.com>
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/random.h>
#include <linux/kthread.h>
#include <linux/moduleparam.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/rwsem.h>
#include <linux/mm.h>
#define __param(type, name, init, msg) \
static type name = init; \
module_param(name, type, 0444); \
MODULE_PARM_DESC(name, msg) \
__param(bool, single_cpu_test, false,
"Use single first online CPU to run tests");
__param(bool, sequential_test_order, false,
"Use sequential stress tests order");
__param(int, test_repeat_count, 1,
"Set test repeat counter");
__param(int, test_loop_count, 1000000,
"Set test loop counter");
__param(int, run_test_mask, INT_MAX,
"Set tests specified in the mask.\n\n"
"\t\tid: 1, name: fix_size_alloc_test\n"
"\t\tid: 2, name: full_fit_alloc_test\n"
"\t\tid: 4, name: long_busy_list_alloc_test\n"
"\t\tid: 8, name: random_size_alloc_test\n"
"\t\tid: 16, name: fix_align_alloc_test\n"
"\t\tid: 32, name: random_size_align_alloc_test\n"
"\t\tid: 64, name: align_shift_alloc_test\n"
"\t\tid: 128, name: pcpu_alloc_test\n"
/* Add a new test case description here. */
);
/*
* Depends on single_cpu_test parameter. If it is true, then
* use first online CPU to trigger a test on, otherwise go with
* all online CPUs.
*/
static cpumask_t cpus_run_test_mask = CPU_MASK_NONE;
/*
* Read write semaphore for synchronization of setup
* phase that is done in main thread and workers.
*/
static DECLARE_RWSEM(prepare_for_test_rwsem);
/*
* Completion tracking for worker threads.
*/
static DECLARE_COMPLETION(test_all_done_comp);
static atomic_t test_n_undone = ATOMIC_INIT(0);
static inline void
test_report_one_done(void)
{
if (atomic_dec_and_test(&test_n_undone))
complete(&test_all_done_comp);
}
static int random_size_align_alloc_test(void)
{
unsigned long size, align, rnd;
void *ptr;
int i;
for (i = 0; i < test_loop_count; i++) {
get_random_bytes(&rnd, sizeof(rnd));
/*
* Maximum 1024 pages, if PAGE_SIZE is 4096.
*/
align = 1 << (rnd % 23);
/*
* Maximum 10 pages.
*/
size = ((rnd % 10) + 1) * PAGE_SIZE;
ptr = __vmalloc_node_range(size, align,
VMALLOC_START, VMALLOC_END,
GFP_KERNEL | __GFP_ZERO,
PAGE_KERNEL,
0, 0, __builtin_return_address(0));
if (!ptr)
return -1;
vfree(ptr);
}
return 0;
}
/*
* This test case is supposed to be failed.
*/
static int align_shift_alloc_test(void)
{
unsigned long align;
void *ptr;
int i;
for (i = 0; i < BITS_PER_LONG; i++) {
align = ((unsigned long) 1) << i;
ptr = __vmalloc_node_range(PAGE_SIZE, align,
VMALLOC_START, VMALLOC_END,
GFP_KERNEL | __GFP_ZERO,
PAGE_KERNEL,
0, 0, __builtin_return_address(0));
if (!ptr)
return -1;
vfree(ptr);
}
return 0;
}
static int fix_align_alloc_test(void)
{
void *ptr;
int i;
for (i = 0; i < test_loop_count; i++) {
ptr = __vmalloc_node_range(5 * PAGE_SIZE,
THREAD_ALIGN << 1,
VMALLOC_START, VMALLOC_END,
GFP_KERNEL | __GFP_ZERO,
PAGE_KERNEL,
0, 0, __builtin_return_address(0));
if (!ptr)
return -1;
vfree(ptr);
}
return 0;
}
static int random_size_alloc_test(void)
{
unsigned int n;
void *p;
int i;
for (i = 0; i < test_loop_count; i++) {
get_random_bytes(&n, sizeof(i));
n = (n % 100) + 1;
p = vmalloc(n * PAGE_SIZE);
if (!p)
return -1;
*((__u8 *)p) = 1;
vfree(p);
}
return 0;
}
static int long_busy_list_alloc_test(void)
{
void *ptr_1, *ptr_2;
void **ptr;
int rv = -1;
int i;
ptr = vmalloc(sizeof(void *) * 15000);
if (!ptr)
return rv;
for (i = 0; i < 15000; i++)
ptr[i] = vmalloc(1 * PAGE_SIZE);
for (i = 0; i < test_loop_count; i++) {
ptr_1 = vmalloc(100 * PAGE_SIZE);
if (!ptr_1)
goto leave;
ptr_2 = vmalloc(1 * PAGE_SIZE);
if (!ptr_2) {
vfree(ptr_1);
goto leave;
}
*((__u8 *)ptr_1) = 0;
*((__u8 *)ptr_2) = 1;
vfree(ptr_1);
vfree(ptr_2);
}
/* Success */
rv = 0;
leave:
for (i = 0; i < 15000; i++)
vfree(ptr[i]);
vfree(ptr);
return rv;
}
static int full_fit_alloc_test(void)
{
void **ptr, **junk_ptr, *tmp;
int junk_length;
int rv = -1;
int i;
junk_length = fls(num_online_cpus());
junk_length *= (32 * 1024 * 1024 / PAGE_SIZE);
ptr = vmalloc(sizeof(void *) * junk_length);
if (!ptr)
return rv;
junk_ptr = vmalloc(sizeof(void *) * junk_length);
if (!junk_ptr) {
vfree(ptr);
return rv;
}
for (i = 0; i < junk_length; i++) {
ptr[i] = vmalloc(1 * PAGE_SIZE);
junk_ptr[i] = vmalloc(1 * PAGE_SIZE);
}
for (i = 0; i < junk_length; i++)
vfree(junk_ptr[i]);
for (i = 0; i < test_loop_count; i++) {
tmp = vmalloc(1 * PAGE_SIZE);
if (!tmp)
goto error;
*((__u8 *)tmp) = 1;
vfree(tmp);
}
/* Success */
rv = 0;
error:
for (i = 0; i < junk_length; i++)
vfree(ptr[i]);
vfree(ptr);
vfree(junk_ptr);
return rv;
}
static int fix_size_alloc_test(void)
{
void *ptr;
int i;
for (i = 0; i < test_loop_count; i++) {
ptr = vmalloc(3 * PAGE_SIZE);
if (!ptr)
return -1;
*((__u8 *)ptr) = 0;
vfree(ptr);
}
return 0;
}
static int
pcpu_alloc_test(void)
{
int rv = 0;
#ifndef CONFIG_NEED_PER_CPU_KM
void __percpu **pcpu;
size_t size, align;
int i;
pcpu = vmalloc(sizeof(void __percpu *) * 35000);
if (!pcpu)
return -1;
for (i = 0; i < 35000; i++) {
unsigned int r;
get_random_bytes(&r, sizeof(i));
size = (r % (PAGE_SIZE / 4)) + 1;
/*
* Maximum PAGE_SIZE
*/
get_random_bytes(&r, sizeof(i));
align = 1 << ((i % 11) + 1);
pcpu[i] = __alloc_percpu(size, align);
if (!pcpu[i])
rv = -1;
}
for (i = 0; i < 35000; i++)
free_percpu(pcpu[i]);
vfree(pcpu);
#endif
return rv;
}
struct test_case_desc {
const char *test_name;
int (*test_func)(void);
};
static struct test_case_desc test_case_array[] = {
{ "fix_size_alloc_test", fix_size_alloc_test },
{ "full_fit_alloc_test", full_fit_alloc_test },
{ "long_busy_list_alloc_test", long_busy_list_alloc_test },
{ "random_size_alloc_test", random_size_alloc_test },
{ "fix_align_alloc_test", fix_align_alloc_test },
{ "random_size_align_alloc_test", random_size_align_alloc_test },
{ "align_shift_alloc_test", align_shift_alloc_test },
{ "pcpu_alloc_test", pcpu_alloc_test },
/* Add a new test case here. */
};
struct test_case_data {
int test_failed;
int test_passed;
u64 time;
};
/* Split it to get rid of: WARNING: line over 80 characters */
static struct test_case_data
per_cpu_test_data[NR_CPUS][ARRAY_SIZE(test_case_array)];
static struct test_driver {
struct task_struct *task;
unsigned long start;
unsigned long stop;
int cpu;
} per_cpu_test_driver[NR_CPUS];
static void shuffle_array(int *arr, int n)
{
unsigned int rnd;
int i, j, x;
for (i = n - 1; i > 0; i--) {
get_random_bytes(&rnd, sizeof(rnd));
/* Cut the range. */
j = rnd % i;
/* Swap indexes. */
x = arr[i];
arr[i] = arr[j];
arr[j] = x;
}
}
static int test_func(void *private)
{
struct test_driver *t = private;
cpumask_t newmask = CPU_MASK_NONE;
int random_array[ARRAY_SIZE(test_case_array)];
int index, i, j, ret;
ktime_t kt;
u64 delta;
cpumask_set_cpu(t->cpu, &newmask);
set_cpus_allowed_ptr(current, &newmask);
for (i = 0; i < ARRAY_SIZE(test_case_array); i++)
random_array[i] = i;
if (!sequential_test_order)
shuffle_array(random_array, ARRAY_SIZE(test_case_array));
/*
* Block until initialization is done.
*/
down_read(&prepare_for_test_rwsem);
t->start = get_cycles();
for (i = 0; i < ARRAY_SIZE(test_case_array); i++) {
index = random_array[i];
/*
* Skip tests if run_test_mask has been specified.
*/
if (!((run_test_mask & (1 << index)) >> index))
continue;
kt = ktime_get();
for (j = 0; j < test_repeat_count; j++) {
ret = test_case_array[index].test_func();
if (!ret)
per_cpu_test_data[t->cpu][index].test_passed++;
else
per_cpu_test_data[t->cpu][index].test_failed++;
}
/*
* Take an average time that test took.
*/
delta = (u64) ktime_us_delta(ktime_get(), kt);
do_div(delta, (u32) test_repeat_count);
per_cpu_test_data[t->cpu][index].time = delta;
}
t->stop = get_cycles();
up_read(&prepare_for_test_rwsem);
test_report_one_done();
/*
* Wait for the kthread_stop() call.
*/
while (!kthread_should_stop())
msleep(10);
return 0;
}
static void
init_test_configurtion(void)
{
/*
* Reset all data of all CPUs.
*/
memset(per_cpu_test_data, 0, sizeof(per_cpu_test_data));
if (single_cpu_test)
cpumask_set_cpu(cpumask_first(cpu_online_mask),
&cpus_run_test_mask);
else
cpumask_and(&cpus_run_test_mask, cpu_online_mask,
cpu_online_mask);
if (test_repeat_count <= 0)
test_repeat_count = 1;
if (test_loop_count <= 0)
test_loop_count = 1;
}
static void do_concurrent_test(void)
{
int cpu, ret;
/*
* Set some basic configurations plus sanity check.
*/
init_test_configurtion();
/*
* Put on hold all workers.
*/
down_write(&prepare_for_test_rwsem);
for_each_cpu(cpu, &cpus_run_test_mask) {
struct test_driver *t = &per_cpu_test_driver[cpu];
t->cpu = cpu;
t->task = kthread_run(test_func, t, "vmalloc_test/%d", cpu);
if (!IS_ERR(t->task))
/* Success. */
atomic_inc(&test_n_undone);
else
pr_err("Failed to start kthread for %d CPU\n", cpu);
}
/*
* Now let the workers do their job.
*/
up_write(&prepare_for_test_rwsem);
/*
* Sleep quiet until all workers are done with 1 second
* interval. Since the test can take a lot of time we
* can run into a stack trace of the hung task. That is
* why we go with completion_timeout and HZ value.
*/
do {
ret = wait_for_completion_timeout(&test_all_done_comp, HZ);
} while (!ret);
for_each_cpu(cpu, &cpus_run_test_mask) {
struct test_driver *t = &per_cpu_test_driver[cpu];
int i;
if (!IS_ERR(t->task))
kthread_stop(t->task);
for (i = 0; i < ARRAY_SIZE(test_case_array); i++) {
if (!((run_test_mask & (1 << i)) >> i))
continue;
pr_info(
"Summary: %s passed: %d failed: %d repeat: %d loops: %d avg: %llu usec\n",
test_case_array[i].test_name,
per_cpu_test_data[cpu][i].test_passed,
per_cpu_test_data[cpu][i].test_failed,
test_repeat_count, test_loop_count,
per_cpu_test_data[cpu][i].time);
}
pr_info("All test took CPU%d=%lu cycles\n",
cpu, t->stop - t->start);
}
}
static int vmalloc_test_init(void)
{
do_concurrent_test();
return -EAGAIN; /* Fail will directly unload the module */
}
static void vmalloc_test_exit(void)
{
}
module_init(vmalloc_test_init)
module_exit(vmalloc_test_exit)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Uladzislau Rezki");
MODULE_DESCRIPTION("vmalloc test module");