mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
Merge branch 'akpm' (patches from Andrew)
Merge more updates from Andrew Morton: "55 patches. Subsystems affected by this patch series: percpu, procfs, sysctl, misc, core-kernel, get_maintainer, lib, checkpatch, binfmt, nilfs2, hfs, fat, adfs, panic, delayacct, kconfig, kcov, and ubsan" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (55 commits) lib: remove redundant assignment to variable ret ubsan: remove CONFIG_UBSAN_OBJECT_SIZE kcov: fix generic Kconfig dependencies if ARCH_WANTS_NO_INSTR lib/Kconfig.debug: make TEST_KMOD depend on PAGE_SIZE_LESS_THAN_256KB btrfs: use generic Kconfig option for 256kB page size limit arch/Kconfig: split PAGE_SIZE_LESS_THAN_256KB from PAGE_SIZE_LESS_THAN_64KB configs: introduce debug.config for CI-like setup delayacct: track delays from memory compact Documentation/accounting/delay-accounting.rst: add thrashing page cache and direct compact delayacct: cleanup flags in struct task_delay_info and functions use it delayacct: fix incomplete disable operation when switch enable to disable delayacct: support swapin delay accounting for swapping without blkio panic: remove oops_id panic: use error_report_end tracepoint on warnings fs/adfs: remove unneeded variable make code cleaner FAT: use io_schedule_timeout() instead of congestion_wait() hfsplus: use struct_group_attr() for memcpy() region nilfs2: remove redundant pointer sbufs fs/binfmt_elf: use PT_LOAD p_align values for static PIE const_structs.checkpatch: add frequently used ops structs ...
This commit is contained in:
commit
f4484d138b
@ -13,6 +13,8 @@ a) waiting for a CPU (while being runnable)
|
||||
b) completion of synchronous block I/O initiated by the task
|
||||
c) swapping in pages
|
||||
d) memory reclaim
|
||||
e) thrashing page cache
|
||||
f) direct compact
|
||||
|
||||
and makes these statistics available to userspace through
|
||||
the taskstats interface.
|
||||
@ -41,11 +43,12 @@ generic data structure to userspace corresponding to per-pid and per-tgid
|
||||
statistics. The delay accounting functionality populates specific fields of
|
||||
this structure. See
|
||||
|
||||
include/linux/taskstats.h
|
||||
include/uapi/linux/taskstats.h
|
||||
|
||||
for a description of the fields pertaining to delay accounting.
|
||||
It will generally be in the form of counters returning the cumulative
|
||||
delay seen for cpu, sync block I/O, swapin, memory reclaim etc.
|
||||
delay seen for cpu, sync block I/O, swapin, memory reclaim, thrash page
|
||||
cache, direct compact etc.
|
||||
|
||||
Taking the difference of two successive readings of a given
|
||||
counter (say cpu_delay_total) for a task will give the delay
|
||||
@ -88,41 +91,37 @@ seen.
|
||||
|
||||
General format of the getdelays command::
|
||||
|
||||
getdelays [-t tgid] [-p pid] [-c cmd...]
|
||||
|
||||
getdelays [-dilv] [-t tgid] [-p pid]
|
||||
|
||||
Get delays, since system boot, for pid 10::
|
||||
|
||||
# ./getdelays -p 10
|
||||
# ./getdelays -d -p 10
|
||||
(output similar to next case)
|
||||
|
||||
Get sum of delays, since system boot, for all pids with tgid 5::
|
||||
|
||||
# ./getdelays -t 5
|
||||
# ./getdelays -d -t 5
|
||||
print delayacct stats ON
|
||||
TGID 5
|
||||
|
||||
|
||||
CPU count real total virtual total delay total
|
||||
7876 92005750 100000000 24001500
|
||||
IO count delay total
|
||||
0 0
|
||||
SWAP count delay total
|
||||
0 0
|
||||
RECLAIM count delay total
|
||||
0 0
|
||||
CPU count real total virtual total delay total delay average
|
||||
8 7000000 6872122 3382277 0.423ms
|
||||
IO count delay total delay average
|
||||
0 0 0ms
|
||||
SWAP count delay total delay average
|
||||
0 0 0ms
|
||||
RECLAIM count delay total delay average
|
||||
0 0 0ms
|
||||
THRASHING count delay total delay average
|
||||
0 0 0ms
|
||||
COMPACT count delay total delay average
|
||||
0 0 0ms
|
||||
|
||||
Get delays seen in executing a given simple command::
|
||||
Get IO accounting for pid 1, it works only with -p::
|
||||
|
||||
# ./getdelays -c ls /
|
||||
# ./getdelays -i -p 1
|
||||
printing IO accounting
|
||||
linuxrc: read=65536, write=0, cancelled_write=0
|
||||
|
||||
bin data1 data3 data5 dev home media opt root srv sys usr
|
||||
boot data2 data4 data6 etc lib mnt proc sbin subdomain tmp var
|
||||
|
||||
|
||||
CPU count real total virtual total delay total
|
||||
6 4000250 4000000 0
|
||||
IO count delay total
|
||||
0 0
|
||||
SWAP count delay total
|
||||
0 0
|
||||
RECLAIM count delay total
|
||||
0 0
|
||||
The above command can be used with -v to get more debug information.
|
||||
|
@ -997,6 +997,10 @@ config PAGE_SIZE_LESS_THAN_64KB
|
||||
depends on !PAGE_SIZE_64KB
|
||||
depends on !PARISC_PAGE_SIZE_64KB
|
||||
depends on !PPC_64K_PAGES
|
||||
depends on PAGE_SIZE_LESS_THAN_256KB
|
||||
|
||||
config PAGE_SIZE_LESS_THAN_256KB
|
||||
def_bool y
|
||||
depends on !PPC_256K_PAGES
|
||||
depends on !PAGE_SIZE_256KB
|
||||
|
||||
|
@ -1136,6 +1136,10 @@ config NUMA
|
||||
select GENERIC_ARCH_NUMA
|
||||
select ACPI_NUMA if ACPI
|
||||
select OF_NUMA
|
||||
select HAVE_SETUP_PER_CPU_AREA
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
select NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
help
|
||||
Enable NUMA (Non-Uniform Memory Access) support.
|
||||
|
||||
@ -1152,22 +1156,6 @@ config NODES_SHIFT
|
||||
Specify the maximum number of NUMA Nodes available on the target
|
||||
system. Increases memory reserved to accommodate various tables.
|
||||
|
||||
config USE_PERCPU_NUMA_NODE_ID
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
source "kernel/Kconfig.hz"
|
||||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
|
@ -32,6 +32,7 @@ config IA64
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_DYNAMIC_FTRACE if (!ITANIUM)
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_SETUP_PER_CPU_AREA
|
||||
select TTY
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_VIRT_CPU_ACCOUNTING
|
||||
@ -88,9 +89,6 @@ config GENERIC_CALIBRATE_DELAY
|
||||
bool
|
||||
default y
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool y
|
||||
|
||||
config DMI
|
||||
bool
|
||||
default y
|
||||
@ -292,6 +290,7 @@ config NUMA
|
||||
bool "NUMA support"
|
||||
depends on !FLATMEM
|
||||
select SMP
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
help
|
||||
Say Y to compile the kernel to support NUMA (Non-Uniform Memory
|
||||
Access). This option is for configuring high-end multiprocessor
|
||||
@ -311,10 +310,6 @@ config HAVE_ARCH_NODEDATA_EXTENSION
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config USE_PERCPU_NUMA_NODE_ID
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config HAVE_MEMORYLESS_NODES
|
||||
def_bool NUMA
|
||||
|
||||
|
@ -2674,6 +2674,8 @@ config NUMA
|
||||
bool "NUMA Support"
|
||||
depends on SYS_SUPPORTS_NUMA
|
||||
select SMP
|
||||
select HAVE_SETUP_PER_CPU_AREA
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
help
|
||||
Say Y to compile the kernel to support NUMA (Non-Uniform Memory
|
||||
Access). This option improves performance on systems with more
|
||||
@ -2684,14 +2686,6 @@ config NUMA
|
||||
config SYS_SUPPORTS_NUMA
|
||||
bool
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config RELOCATABLE
|
||||
bool "Relocatable kernel"
|
||||
depends on SYS_SUPPORTS_RELOCATABLE
|
||||
|
@ -519,17 +519,9 @@ static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
return node_distance(cpu_to_node(from), cpu_to_node(to));
|
||||
}
|
||||
|
||||
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size,
|
||||
size_t align)
|
||||
static int __init pcpu_cpu_to_node(int cpu)
|
||||
{
|
||||
return memblock_alloc_try_nid(size, align, __pa(MAX_DMA_ADDRESS),
|
||||
MEMBLOCK_ALLOC_ACCESSIBLE,
|
||||
cpu_to_node(cpu));
|
||||
}
|
||||
|
||||
static void __init pcpu_fc_free(void *ptr, size_t size)
|
||||
{
|
||||
memblock_free(ptr, size);
|
||||
return cpu_to_node(cpu);
|
||||
}
|
||||
|
||||
void __init setup_per_cpu_areas(void)
|
||||
@ -545,7 +537,7 @@ void __init setup_per_cpu_areas(void)
|
||||
rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
|
||||
PERCPU_DYNAMIC_RESERVE, PAGE_SIZE,
|
||||
pcpu_cpu_distance,
|
||||
pcpu_fc_alloc, pcpu_fc_free);
|
||||
pcpu_cpu_to_node);
|
||||
if (rc < 0)
|
||||
panic("Failed to initialize percpu areas.");
|
||||
|
||||
|
@ -55,15 +55,6 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
|
||||
default 9 if PPC_16K_PAGES # 9 = 23 (8MB) - 14 (16K)
|
||||
default 11 # 11 = 23 (8MB) - 12 (4K)
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool PPC64
|
||||
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
def_bool y if PPC64
|
||||
|
||||
config NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
def_bool y if PPC64
|
||||
|
||||
config NR_IRQS
|
||||
int "Number of virtual interrupt numbers"
|
||||
range 32 1048576
|
||||
@ -241,6 +232,7 @@ config PPC
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RELIABLE_STACKTRACE
|
||||
select HAVE_RSEQ
|
||||
select HAVE_SETUP_PER_CPU_AREA if PPC64
|
||||
select HAVE_SOFTIRQ_ON_OWN_STACK
|
||||
select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2)
|
||||
select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13)
|
||||
@ -255,6 +247,8 @@ config PPC
|
||||
select MMU_GATHER_RCU_TABLE_FREE
|
||||
select MODULES_USE_ELF_RELA
|
||||
select NEED_DMA_MAP_STATE if PPC64 || NOT_COHERENT_CACHE
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK if PPC64
|
||||
select NEED_PER_CPU_PAGE_FIRST_CHUNK if PPC64
|
||||
select NEED_SG_DMA_LENGTH
|
||||
select OF
|
||||
select OF_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE
|
||||
@ -660,6 +654,7 @@ config NUMA
|
||||
bool "NUMA Memory Allocation and Scheduler Support"
|
||||
depends on PPC64 && SMP
|
||||
default y if PPC_PSERIES || PPC_POWERNV
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
help
|
||||
Enable NUMA (Non-Uniform Memory Access) support.
|
||||
|
||||
@ -673,10 +668,6 @@ config NODES_SHIFT
|
||||
default "4"
|
||||
depends on NUMA
|
||||
|
||||
config USE_PERCPU_NUMA_NODE_ID
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config HAVE_MEMORYLESS_NODES
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
@ -771,50 +771,6 @@ void __init emergency_stack_init(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/**
|
||||
* pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
|
||||
* @cpu: cpu to allocate for
|
||||
* @size: size allocation in bytes
|
||||
* @align: alignment
|
||||
*
|
||||
* Allocate @size bytes aligned at @align for cpu @cpu. This wrapper
|
||||
* does the right thing for NUMA regardless of the current
|
||||
* configuration.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the allocated area on success, NULL on failure.
|
||||
*/
|
||||
static void * __init pcpu_alloc_bootmem(unsigned int cpu, size_t size,
|
||||
size_t align)
|
||||
{
|
||||
const unsigned long goal = __pa(MAX_DMA_ADDRESS);
|
||||
#ifdef CONFIG_NUMA
|
||||
int node = early_cpu_to_node(cpu);
|
||||
void *ptr;
|
||||
|
||||
if (!node_online(node) || !NODE_DATA(node)) {
|
||||
ptr = memblock_alloc_from(size, align, goal);
|
||||
pr_info("cpu %d has no node %d or node-local memory\n",
|
||||
cpu, node);
|
||||
pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
|
||||
cpu, size, __pa(ptr));
|
||||
} else {
|
||||
ptr = memblock_alloc_try_nid(size, align, goal,
|
||||
MEMBLOCK_ALLOC_ACCESSIBLE, node);
|
||||
pr_debug("per cpu data for cpu%d %lu bytes on node%d at "
|
||||
"%016lx\n", cpu, size, node, __pa(ptr));
|
||||
}
|
||||
return ptr;
|
||||
#else
|
||||
return memblock_alloc_from(size, align, goal);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init pcpu_free_bootmem(void *ptr, size_t size)
|
||||
{
|
||||
memblock_free(ptr, size);
|
||||
}
|
||||
|
||||
static int pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
{
|
||||
if (early_cpu_to_node(from) == early_cpu_to_node(to))
|
||||
@ -823,53 +779,13 @@ static int pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
return REMOTE_DISTANCE;
|
||||
}
|
||||
|
||||
unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
|
||||
EXPORT_SYMBOL(__per_cpu_offset);
|
||||
|
||||
static void __init pcpu_populate_pte(unsigned long addr)
|
||||
static __init int pcpu_cpu_to_node(int cpu)
|
||||
{
|
||||
pgd_t *pgd = pgd_offset_k(addr);
|
||||
p4d_t *p4d;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
|
||||
p4d = p4d_offset(pgd, addr);
|
||||
if (p4d_none(*p4d)) {
|
||||
pud_t *new;
|
||||
|
||||
new = memblock_alloc(PUD_TABLE_SIZE, PUD_TABLE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
p4d_populate(&init_mm, p4d, new);
|
||||
}
|
||||
|
||||
pud = pud_offset(p4d, addr);
|
||||
if (pud_none(*pud)) {
|
||||
pmd_t *new;
|
||||
|
||||
new = memblock_alloc(PMD_TABLE_SIZE, PMD_TABLE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pud_populate(&init_mm, pud, new);
|
||||
}
|
||||
|
||||
pmd = pmd_offset(pud, addr);
|
||||
if (!pmd_present(*pmd)) {
|
||||
pte_t *new;
|
||||
|
||||
new = memblock_alloc(PTE_TABLE_SIZE, PTE_TABLE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pmd_populate_kernel(&init_mm, pmd, new);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_alloc:
|
||||
panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n",
|
||||
__func__, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
||||
return early_cpu_to_node(cpu);
|
||||
}
|
||||
|
||||
unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
|
||||
EXPORT_SYMBOL(__per_cpu_offset);
|
||||
|
||||
void __init setup_per_cpu_areas(void)
|
||||
{
|
||||
@ -900,7 +816,7 @@ void __init setup_per_cpu_areas(void)
|
||||
|
||||
if (pcpu_chosen_fc != PCPU_FC_PAGE) {
|
||||
rc = pcpu_embed_first_chunk(0, dyn_size, atom_size, pcpu_cpu_distance,
|
||||
pcpu_alloc_bootmem, pcpu_free_bootmem);
|
||||
pcpu_cpu_to_node);
|
||||
if (rc)
|
||||
pr_warn("PERCPU: %s allocator failed (%d), "
|
||||
"falling back to page size\n",
|
||||
@ -908,8 +824,7 @@ void __init setup_per_cpu_areas(void)
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
rc = pcpu_page_first_chunk(0, pcpu_alloc_bootmem, pcpu_free_bootmem,
|
||||
pcpu_populate_pte);
|
||||
rc = pcpu_page_first_chunk(0, pcpu_cpu_to_node);
|
||||
if (rc < 0)
|
||||
panic("cannot initialize percpu area (err=%d)", rc);
|
||||
|
||||
|
@ -335,6 +335,8 @@ config NUMA
|
||||
select GENERIC_ARCH_NUMA
|
||||
select OF_NUMA
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
help
|
||||
Enable NUMA (Non-Uniform Memory Access) support.
|
||||
|
||||
@ -350,14 +352,6 @@ config NODES_SHIFT
|
||||
Specify the maximum number of NUMA Nodes available on the target
|
||||
system. Increases memory reserved to accommodate various tables.
|
||||
|
||||
config USE_PERCPU_NUMA_NODE_ID
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
config RISCV_ISA_C
|
||||
bool "Emit compressed instructions when building Linux"
|
||||
default y
|
||||
|
@ -97,6 +97,9 @@ config SPARC64
|
||||
select PCI_DOMAINS if PCI
|
||||
select ARCH_HAS_GIGANTIC_PAGE
|
||||
select HAVE_SOFTIRQ_ON_OWN_STACK
|
||||
select HAVE_SETUP_PER_CPU_AREA
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
select NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
|
||||
config ARCH_PROC_KCORE_TEXT
|
||||
def_bool y
|
||||
@ -123,15 +126,6 @@ config AUDIT_ARCH
|
||||
bool
|
||||
default y
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool y if SPARC64
|
||||
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
def_bool y if SPARC64
|
||||
|
||||
config NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
def_bool y if SPARC64
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
|
@ -114,18 +114,16 @@ static const struct proc_ops led_proc_ops = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct proc_dir_entry *led;
|
||||
|
||||
#define LED_VERSION "0.1"
|
||||
|
||||
static int __init led_init(void)
|
||||
{
|
||||
timer_setup(&led_blink_timer, led_blink, 0);
|
||||
|
||||
led = proc_create("led", 0, NULL, &led_proc_ops);
|
||||
if (!led)
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("led", 0, NULL, &led_proc_ops))
|
||||
return -ENOMEM;
|
||||
|
||||
#endif
|
||||
printk(KERN_INFO
|
||||
"led: version %s, Lars Kotthoff <metalhead@metalhead.ws>\n",
|
||||
LED_VERSION);
|
||||
|
@ -1526,50 +1526,6 @@ void smp_send_stop(void)
|
||||
smp_call_function(stop_this_cpu, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
|
||||
* @cpu: cpu to allocate for
|
||||
* @size: size allocation in bytes
|
||||
* @align: alignment
|
||||
*
|
||||
* Allocate @size bytes aligned at @align for cpu @cpu. This wrapper
|
||||
* does the right thing for NUMA regardless of the current
|
||||
* configuration.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the allocated area on success, NULL on failure.
|
||||
*/
|
||||
static void * __init pcpu_alloc_bootmem(unsigned int cpu, size_t size,
|
||||
size_t align)
|
||||
{
|
||||
const unsigned long goal = __pa(MAX_DMA_ADDRESS);
|
||||
#ifdef CONFIG_NUMA
|
||||
int node = cpu_to_node(cpu);
|
||||
void *ptr;
|
||||
|
||||
if (!node_online(node) || !NODE_DATA(node)) {
|
||||
ptr = memblock_alloc_from(size, align, goal);
|
||||
pr_info("cpu %d has no node %d or node-local memory\n",
|
||||
cpu, node);
|
||||
pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
|
||||
cpu, size, __pa(ptr));
|
||||
} else {
|
||||
ptr = memblock_alloc_try_nid(size, align, goal,
|
||||
MEMBLOCK_ALLOC_ACCESSIBLE, node);
|
||||
pr_debug("per cpu data for cpu%d %lu bytes on node%d at "
|
||||
"%016lx\n", cpu, size, node, __pa(ptr));
|
||||
}
|
||||
return ptr;
|
||||
#else
|
||||
return memblock_alloc_from(size, align, goal);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init pcpu_free_bootmem(void *ptr, size_t size)
|
||||
{
|
||||
memblock_free(ptr, size);
|
||||
}
|
||||
|
||||
static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
{
|
||||
if (cpu_to_node(from) == cpu_to_node(to))
|
||||
@ -1578,57 +1534,9 @@ static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
return REMOTE_DISTANCE;
|
||||
}
|
||||
|
||||
static void __init pcpu_populate_pte(unsigned long addr)
|
||||
static int __init pcpu_cpu_to_node(int cpu)
|
||||
{
|
||||
pgd_t *pgd = pgd_offset_k(addr);
|
||||
p4d_t *p4d;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
|
||||
if (pgd_none(*pgd)) {
|
||||
pud_t *new;
|
||||
|
||||
new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pgd_populate(&init_mm, pgd, new);
|
||||
}
|
||||
|
||||
p4d = p4d_offset(pgd, addr);
|
||||
if (p4d_none(*p4d)) {
|
||||
pud_t *new;
|
||||
|
||||
new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
p4d_populate(&init_mm, p4d, new);
|
||||
}
|
||||
|
||||
pud = pud_offset(p4d, addr);
|
||||
if (pud_none(*pud)) {
|
||||
pmd_t *new;
|
||||
|
||||
new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pud_populate(&init_mm, pud, new);
|
||||
}
|
||||
|
||||
pmd = pmd_offset(pud, addr);
|
||||
if (!pmd_present(*pmd)) {
|
||||
pte_t *new;
|
||||
|
||||
new = memblock_alloc_from(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pmd_populate_kernel(&init_mm, pmd, new);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_alloc:
|
||||
panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n",
|
||||
__func__, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
||||
return cpu_to_node(cpu);
|
||||
}
|
||||
|
||||
void __init setup_per_cpu_areas(void)
|
||||
@ -1641,8 +1549,7 @@ void __init setup_per_cpu_areas(void)
|
||||
rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
|
||||
PERCPU_DYNAMIC_RESERVE, 4 << 20,
|
||||
pcpu_cpu_distance,
|
||||
pcpu_alloc_bootmem,
|
||||
pcpu_free_bootmem);
|
||||
pcpu_cpu_to_node);
|
||||
if (rc)
|
||||
pr_warn("PERCPU: %s allocator failed (%d), "
|
||||
"falling back to page size\n",
|
||||
@ -1650,9 +1557,7 @@ void __init setup_per_cpu_areas(void)
|
||||
}
|
||||
if (rc < 0)
|
||||
rc = pcpu_page_first_chunk(PERCPU_MODULE_RESERVE,
|
||||
pcpu_alloc_bootmem,
|
||||
pcpu_free_bootmem,
|
||||
pcpu_populate_pte);
|
||||
pcpu_cpu_to_node);
|
||||
if (rc < 0)
|
||||
panic("cannot initialize percpu area (err=%d)", rc);
|
||||
|
||||
|
@ -78,7 +78,7 @@ config X86
|
||||
select ARCH_HAS_FILTER_PGPROT
|
||||
select ARCH_HAS_FORTIFY_SOURCE
|
||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||
select ARCH_HAS_KCOV if X86_64 && STACK_VALIDATION
|
||||
select ARCH_HAS_KCOV if X86_64
|
||||
select ARCH_HAS_MEM_ENCRYPT
|
||||
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
||||
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
|
||||
@ -240,6 +240,7 @@ config X86
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RELIABLE_STACKTRACE if X86_64 && (UNWINDER_FRAME_POINTER || UNWINDER_ORC) && STACK_VALIDATION
|
||||
select HAVE_FUNCTION_ARG_ACCESS_API
|
||||
select HAVE_SETUP_PER_CPU_AREA
|
||||
select HAVE_SOFTIRQ_ON_OWN_STACK
|
||||
select HAVE_STACKPROTECTOR if CC_HAS_SANE_STACKPROTECTOR
|
||||
select HAVE_STACK_VALIDATION if X86_64
|
||||
@ -253,6 +254,8 @@ config X86
|
||||
select HAVE_GENERIC_VDSO
|
||||
select HOTPLUG_SMT if SMP
|
||||
select IRQ_FORCED_THREADING
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
select NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
select NEED_SG_DMA_LENGTH
|
||||
select PCI_DOMAINS if PCI
|
||||
select PCI_LOCKLESS_CONFIG if PCI
|
||||
@ -333,15 +336,6 @@ config ARCH_HAS_CPU_RELAX
|
||||
config ARCH_HAS_FILTER_PGPROT
|
||||
def_bool y
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
def_bool y
|
||||
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
def_bool y
|
||||
|
||||
config NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
def_bool y
|
||||
|
||||
config ARCH_HIBERNATION_POSSIBLE
|
||||
def_bool y
|
||||
|
||||
@ -1575,6 +1569,7 @@ config NUMA
|
||||
depends on SMP
|
||||
depends on X86_64 || (X86_32 && HIGHMEM64G && X86_BIGSMP)
|
||||
default y if X86_BIGSMP
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
help
|
||||
Enable NUMA (Non-Uniform Memory Access) support.
|
||||
|
||||
@ -2450,10 +2445,6 @@ config ARCH_HAS_ADD_PAGES
|
||||
config ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
|
||||
def_bool y
|
||||
|
||||
config USE_PERCPU_NUMA_NODE_ID
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
||||
menu "Power management and ACPI options"
|
||||
|
||||
config ARCH_HIBERNATION_HEADER
|
||||
|
@ -84,60 +84,6 @@ static bool __init pcpu_need_numa(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
|
||||
* @cpu: cpu to allocate for
|
||||
* @size: size allocation in bytes
|
||||
* @align: alignment
|
||||
*
|
||||
* Allocate @size bytes aligned at @align for cpu @cpu. This wrapper
|
||||
* does the right thing for NUMA regardless of the current
|
||||
* configuration.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the allocated area on success, NULL on failure.
|
||||
*/
|
||||
static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
|
||||
unsigned long align)
|
||||
{
|
||||
const unsigned long goal = __pa(MAX_DMA_ADDRESS);
|
||||
#ifdef CONFIG_NUMA
|
||||
int node = early_cpu_to_node(cpu);
|
||||
void *ptr;
|
||||
|
||||
if (!node_online(node) || !NODE_DATA(node)) {
|
||||
ptr = memblock_alloc_from(size, align, goal);
|
||||
pr_info("cpu %d has no node %d or node-local memory\n",
|
||||
cpu, node);
|
||||
pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
|
||||
cpu, size, __pa(ptr));
|
||||
} else {
|
||||
ptr = memblock_alloc_try_nid(size, align, goal,
|
||||
MEMBLOCK_ALLOC_ACCESSIBLE,
|
||||
node);
|
||||
|
||||
pr_debug("per cpu data for cpu%d %lu bytes on node%d at %016lx\n",
|
||||
cpu, size, node, __pa(ptr));
|
||||
}
|
||||
return ptr;
|
||||
#else
|
||||
return memblock_alloc_from(size, align, goal);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers for first chunk memory allocation
|
||||
*/
|
||||
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
|
||||
{
|
||||
return pcpu_alloc_bootmem(cpu, size, align);
|
||||
}
|
||||
|
||||
static void __init pcpu_fc_free(void *ptr, size_t size)
|
||||
{
|
||||
memblock_free(ptr, size);
|
||||
}
|
||||
|
||||
static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
{
|
||||
#ifdef CONFIG_NUMA
|
||||
@ -150,7 +96,12 @@ static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init pcpup_populate_pte(unsigned long addr)
|
||||
static int __init pcpu_cpu_to_node(int cpu)
|
||||
{
|
||||
return early_cpu_to_node(cpu);
|
||||
}
|
||||
|
||||
void __init pcpu_populate_pte(unsigned long addr)
|
||||
{
|
||||
populate_extra_pte(addr);
|
||||
}
|
||||
@ -205,15 +156,14 @@ void __init setup_per_cpu_areas(void)
|
||||
rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
|
||||
dyn_size, atom_size,
|
||||
pcpu_cpu_distance,
|
||||
pcpu_fc_alloc, pcpu_fc_free);
|
||||
pcpu_cpu_to_node);
|
||||
if (rc < 0)
|
||||
pr_warn("%s allocator failed (%d), falling back to page size\n",
|
||||
pcpu_fc_names[pcpu_chosen_fc], rc);
|
||||
}
|
||||
if (rc < 0)
|
||||
rc = pcpu_page_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
|
||||
pcpu_fc_alloc, pcpu_fc_free,
|
||||
pcpup_populate_pte);
|
||||
pcpu_cpu_to_node);
|
||||
if (rc < 0)
|
||||
panic("cannot initialize percpu area (err=%d)", rc);
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/sections.h>
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
|
||||
EXPORT_SYMBOL(node_data);
|
||||
@ -155,66 +154,6 @@ static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
return node_distance(early_cpu_to_node(from), early_cpu_to_node(to));
|
||||
}
|
||||
|
||||
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size,
|
||||
size_t align)
|
||||
{
|
||||
int nid = early_cpu_to_node(cpu);
|
||||
|
||||
return memblock_alloc_try_nid(size, align,
|
||||
__pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid);
|
||||
}
|
||||
|
||||
static void __init pcpu_fc_free(void *ptr, size_t size)
|
||||
{
|
||||
memblock_free(ptr, size);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
static void __init pcpu_populate_pte(unsigned long addr)
|
||||
{
|
||||
pgd_t *pgd = pgd_offset_k(addr);
|
||||
p4d_t *p4d;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
|
||||
p4d = p4d_offset(pgd, addr);
|
||||
if (p4d_none(*p4d)) {
|
||||
pud_t *new;
|
||||
|
||||
new = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
p4d_populate(&init_mm, p4d, new);
|
||||
}
|
||||
|
||||
pud = pud_offset(p4d, addr);
|
||||
if (pud_none(*pud)) {
|
||||
pmd_t *new;
|
||||
|
||||
new = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pud_populate(&init_mm, pud, new);
|
||||
}
|
||||
|
||||
pmd = pmd_offset(pud, addr);
|
||||
if (!pmd_present(*pmd)) {
|
||||
pte_t *new;
|
||||
|
||||
new = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pmd_populate_kernel(&init_mm, pmd, new);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_alloc:
|
||||
panic("%s: Failed to allocate %lu bytes align=%lx from=%lx\n",
|
||||
__func__, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init setup_per_cpu_areas(void)
|
||||
{
|
||||
unsigned long delta;
|
||||
@ -229,7 +168,7 @@ void __init setup_per_cpu_areas(void)
|
||||
rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
|
||||
PERCPU_DYNAMIC_RESERVE, PAGE_SIZE,
|
||||
pcpu_cpu_distance,
|
||||
pcpu_fc_alloc, pcpu_fc_free);
|
||||
early_cpu_to_node);
|
||||
#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
if (rc < 0)
|
||||
pr_warn("PERCPU: %s allocator failed (%d), falling back to page size\n",
|
||||
@ -239,10 +178,7 @@ void __init setup_per_cpu_areas(void)
|
||||
|
||||
#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
if (rc < 0)
|
||||
rc = pcpu_page_first_chunk(PERCPU_MODULE_RESERVE,
|
||||
pcpu_fc_alloc,
|
||||
pcpu_fc_free,
|
||||
pcpu_populate_pte);
|
||||
rc = pcpu_page_first_chunk(PERCPU_MODULE_RESERVE, early_cpu_to_node);
|
||||
#endif
|
||||
if (rc < 0)
|
||||
panic("Failed to initialize percpu areas (err=%d).", rc);
|
||||
|
@ -196,7 +196,7 @@ struct qib_ctxtdata {
|
||||
pid_t pid;
|
||||
pid_t subpid[QLOGIC_IB_MAX_SUBCTXT];
|
||||
/* same size as task_struct .comm[], command that opened context */
|
||||
char comm[16];
|
||||
char comm[TASK_COMM_LEN];
|
||||
/* pkeys set by this use of this ctxt */
|
||||
u16 pkeys[4];
|
||||
/* so file ops can get at unit */
|
||||
|
@ -1321,7 +1321,7 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt,
|
||||
rcd->tid_pg_list = ptmp;
|
||||
rcd->pid = current->pid;
|
||||
init_waitqueue_head(&dd->rcd[ctxt]->wait);
|
||||
strlcpy(rcd->comm, current->comm, sizeof(rcd->comm));
|
||||
get_task_comm(rcd->comm, current);
|
||||
ctxt_fp(fp) = rcd;
|
||||
qib_stats.sps_ctxts++;
|
||||
dd->freectxts--;
|
||||
|
@ -217,8 +217,7 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp,
|
||||
* the port number must be in the Dynamic Ports range
|
||||
* (0xc000 - 0xffff).
|
||||
*/
|
||||
qp->src_port = RXE_ROCE_V2_SPORT +
|
||||
(hash_32_generic(qp_num(qp), 14) & 0x3fff);
|
||||
qp->src_port = RXE_ROCE_V2_SPORT + (hash_32(qp_num(qp), 14) & 0x3fff);
|
||||
qp->sq.max_wr = init->cap.max_send_wr;
|
||||
|
||||
/* These caps are limited by rxe_qp_chk_cap() done by the caller */
|
||||
|
@ -4,6 +4,8 @@
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <linux/math.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
|
@ -355,7 +355,6 @@ int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct object_info obj;
|
||||
int ret;
|
||||
|
||||
obj.indaddr = ADFS_I(inode)->indaddr;
|
||||
obj.name_len = 0;
|
||||
@ -365,6 +364,5 @@ int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||
obj.attr = ADFS_I(inode)->attr;
|
||||
obj.size = inode->i_size;
|
||||
|
||||
ret = adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
|
||||
return ret;
|
||||
return adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
|
||||
}
|
||||
|
@ -1116,11 +1116,11 @@ out_free_interp:
|
||||
* independently randomized mmap region (0 load_bias
|
||||
* without MAP_FIXED nor MAP_FIXED_NOREPLACE).
|
||||
*/
|
||||
if (interpreter) {
|
||||
alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum);
|
||||
if (alignment > ELF_MIN_ALIGN) {
|
||||
load_bias = ELF_ET_DYN_BASE;
|
||||
if (current->flags & PF_RANDOMIZE)
|
||||
load_bias += arch_mmap_rnd();
|
||||
alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum);
|
||||
if (alignment)
|
||||
load_bias &= ~(alignment - 1);
|
||||
elf_flags |= MAP_FIXED_NOREPLACE;
|
||||
@ -1585,7 +1585,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
|
||||
SET_UID(psinfo->pr_uid, from_kuid_munged(cred->user_ns, cred->uid));
|
||||
SET_GID(psinfo->pr_gid, from_kgid_munged(cred->user_ns, cred->gid));
|
||||
rcu_read_unlock();
|
||||
strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
|
||||
get_task_comm(psinfo->pr_fname, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,8 +18,7 @@ config BTRFS_FS
|
||||
select RAID6_PQ
|
||||
select XOR_BLOCKS
|
||||
select SRCU
|
||||
depends on !PPC_256K_PAGES # powerpc
|
||||
depends on !PAGE_SIZE_256KB # hexagon
|
||||
depends on PAGE_SIZE_LESS_THAN_256KB
|
||||
|
||||
help
|
||||
Btrfs is a general purpose copy-on-write filesystem with extents,
|
||||
|
@ -1207,7 +1207,8 @@ static int unshare_sighand(struct task_struct *me)
|
||||
char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
|
||||
{
|
||||
task_lock(tsk);
|
||||
strncpy(buf, tsk->comm, buf_size);
|
||||
/* Always NUL terminated and zero-padded */
|
||||
strscpy_pad(buf, tsk->comm, buf_size);
|
||||
task_unlock(tsk);
|
||||
return buf;
|
||||
}
|
||||
@ -1222,7 +1223,7 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
|
||||
{
|
||||
task_lock(tsk);
|
||||
trace_task_rename(tsk, buf);
|
||||
strlcpy(tsk->comm, buf, sizeof(tsk->comm));
|
||||
strscpy_pad(tsk->comm, buf, sizeof(tsk->comm));
|
||||
task_unlock(tsk);
|
||||
perf_event_comm(tsk, exec);
|
||||
}
|
||||
|
@ -175,9 +175,10 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
static int fat_file_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if ((filp->f_mode & FMODE_WRITE) &&
|
||||
MSDOS_SB(inode->i_sb)->options.flush) {
|
||||
MSDOS_SB(inode->i_sb)->options.flush) {
|
||||
fat_flush_inodes(inode->i_sb, inode, NULL);
|
||||
congestion_wait(BLK_RW_ASYNC, HZ/10);
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
io_schedule_timeout(HZ/10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -260,8 +260,10 @@ struct hfsplus_cat_folder {
|
||||
__be32 access_date;
|
||||
__be32 backup_date;
|
||||
struct hfsplus_perm permissions;
|
||||
struct DInfo user_info;
|
||||
struct DXInfo finder_info;
|
||||
struct_group_attr(info, __packed,
|
||||
struct DInfo user_info;
|
||||
struct DXInfo finder_info;
|
||||
);
|
||||
__be32 text_encoding;
|
||||
__be32 subfolders; /* Subfolder count in HFSX. Reserved in HFS+. */
|
||||
} __packed;
|
||||
@ -294,8 +296,10 @@ struct hfsplus_cat_file {
|
||||
__be32 access_date;
|
||||
__be32 backup_date;
|
||||
struct hfsplus_perm permissions;
|
||||
struct FInfo user_info;
|
||||
struct FXInfo finder_info;
|
||||
struct_group_attr(info, __packed,
|
||||
struct FInfo user_info;
|
||||
struct FXInfo finder_info;
|
||||
);
|
||||
__be32 text_encoding;
|
||||
u32 reserved2;
|
||||
|
||||
|
@ -296,7 +296,7 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
|
||||
sizeof(hfsplus_cat_entry));
|
||||
if (be16_to_cpu(entry.type) == HFSPLUS_FOLDER) {
|
||||
if (size == folder_finderinfo_len) {
|
||||
memcpy(&entry.folder.user_info, value,
|
||||
memcpy(&entry.folder.info, value,
|
||||
folder_finderinfo_len);
|
||||
hfs_bnode_write(cat_fd.bnode, &entry,
|
||||
cat_fd.entryoffset,
|
||||
@ -309,7 +309,7 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
|
||||
}
|
||||
} else if (be16_to_cpu(entry.type) == HFSPLUS_FILE) {
|
||||
if (size == file_finderinfo_len) {
|
||||
memcpy(&entry.file.user_info, value,
|
||||
memcpy(&entry.file.info, value,
|
||||
file_finderinfo_len);
|
||||
hfs_bnode_write(cat_fd.bnode, &entry,
|
||||
cat_fd.entryoffset,
|
||||
|
@ -195,12 +195,12 @@ void nilfs_page_bug(struct page *page)
|
||||
*/
|
||||
static void nilfs_copy_page(struct page *dst, struct page *src, int copy_dirty)
|
||||
{
|
||||
struct buffer_head *dbh, *dbufs, *sbh, *sbufs;
|
||||
struct buffer_head *dbh, *dbufs, *sbh;
|
||||
unsigned long mask = NILFS_BUFFER_INHERENT_BITS;
|
||||
|
||||
BUG_ON(PageWriteback(dst));
|
||||
|
||||
sbh = sbufs = page_buffers(src);
|
||||
sbh = page_buffers(src);
|
||||
if (!page_has_buffers(dst))
|
||||
create_empty_buffers(dst, sbh->b_size, 0);
|
||||
|
||||
|
@ -92,6 +92,7 @@
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <linux/fs_struct.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include "internal.h"
|
||||
@ -102,6 +103,8 @@ void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape)
|
||||
|
||||
if (p->flags & PF_WQ_WORKER)
|
||||
wq_worker_comm(tcomm, sizeof(tcomm), p);
|
||||
else if (p->flags & PF_KTHREAD)
|
||||
get_kthread_comm(tcomm, sizeof(tcomm), p);
|
||||
else
|
||||
__get_task_comm(tcomm, sizeof(tcomm), p);
|
||||
|
||||
|
@ -670,10 +670,10 @@ static int proc_pid_syscall(struct seq_file *m, struct pid_namespace *ns,
|
||||
/************************************************************************/
|
||||
|
||||
/* permission checks */
|
||||
static int proc_fd_access_allowed(struct inode *inode)
|
||||
static bool proc_fd_access_allowed(struct inode *inode)
|
||||
{
|
||||
struct task_struct *task;
|
||||
int allowed = 0;
|
||||
bool allowed = false;
|
||||
/* Allow access to a task's file descriptors if it is us or we
|
||||
* may use ptrace attach to the process and find out that
|
||||
* information.
|
||||
|
@ -163,7 +163,7 @@ static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
|
||||
else {
|
||||
pr_err("sysctl duplicate entry: ");
|
||||
sysctl_print_dir(head->parent);
|
||||
pr_cont("/%s\n", entry->procname);
|
||||
pr_cont("%s\n", entry->procname);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
@ -1020,8 +1020,8 @@ failed:
|
||||
if (IS_ERR(subdir)) {
|
||||
pr_err("sysctl could not get directory: ");
|
||||
sysctl_print_dir(dir);
|
||||
pr_cont("/%*.*s %ld\n",
|
||||
namelen, namelen, name, PTR_ERR(subdir));
|
||||
pr_cont("%*.*s %ld\n", namelen, namelen, name,
|
||||
PTR_ERR(subdir));
|
||||
}
|
||||
drop_sysctl_table(&dir->header);
|
||||
if (new)
|
||||
@ -1053,7 +1053,6 @@ static int sysctl_follow_link(struct ctl_table_header **phead,
|
||||
struct ctl_dir *dir;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
spin_lock(&sysctl_lock);
|
||||
root = (*pentry)->data;
|
||||
set = lookup_header_set(root);
|
||||
@ -1626,7 +1625,7 @@ static void put_links(struct ctl_table_header *header)
|
||||
else {
|
||||
pr_err("sysctl link missing during unregister: ");
|
||||
sysctl_print_dir(parent);
|
||||
pr_cont("/%s\n", name);
|
||||
pr_cont("%s\n", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +65,6 @@ static size_t vmcoredd_orig_sz;
|
||||
static DECLARE_RWSEM(vmcore_cb_rwsem);
|
||||
/* List of registered vmcore callbacks. */
|
||||
static LIST_HEAD(vmcore_cb_list);
|
||||
/* Whether we had a surprise unregistration of a callback. */
|
||||
static bool vmcore_cb_unstable;
|
||||
/* Whether the vmcore has been opened once. */
|
||||
static bool vmcore_opened;
|
||||
|
||||
@ -94,10 +92,8 @@ void unregister_vmcore_cb(struct vmcore_cb *cb)
|
||||
* very unusual (e.g., forced driver removal), but we cannot stop
|
||||
* unregistering.
|
||||
*/
|
||||
if (vmcore_opened) {
|
||||
if (vmcore_opened)
|
||||
pr_warn_once("Unexpected vmcore callback unregistration\n");
|
||||
vmcore_cb_unstable = true;
|
||||
}
|
||||
up_write(&vmcore_cb_rwsem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_vmcore_cb);
|
||||
@ -108,8 +104,6 @@ static bool pfn_is_ram(unsigned long pfn)
|
||||
bool ret = true;
|
||||
|
||||
lockdep_assert_held_read(&vmcore_cb_rwsem);
|
||||
if (unlikely(vmcore_cb_unstable))
|
||||
return false;
|
||||
|
||||
list_for_each_entry(cb, &vmcore_cb_list, next) {
|
||||
if (unlikely(!cb->pfn_is_ram))
|
||||
@ -581,7 +575,7 @@ static int vmcore_remap_oldmem_pfn(struct vm_area_struct *vma,
|
||||
* looping over all pages without a reason.
|
||||
*/
|
||||
down_read(&vmcore_cb_rwsem);
|
||||
if (!list_empty(&vmcore_cb_list) || vmcore_cb_unstable)
|
||||
if (!list_empty(&vmcore_cb_list))
|
||||
ret = remap_oldmem_pfn_checked(vma, from, pfn, size, prot);
|
||||
else
|
||||
ret = remap_oldmem_pfn_range(vma, from, pfn, size, prot);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#define _KUNIT_ASSERT_H
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
struct kunit;
|
||||
struct string_stream;
|
||||
|
@ -9,18 +9,9 @@
|
||||
|
||||
#include <uapi/linux/taskstats.h>
|
||||
|
||||
/*
|
||||
* Per-task flags relevant to delay accounting
|
||||
* maintained privately to avoid exhausting similar flags in sched.h:PF_*
|
||||
* Used to set current->delays->flags
|
||||
*/
|
||||
#define DELAYACCT_PF_SWAPIN 0x00000001 /* I am doing a swapin */
|
||||
#define DELAYACCT_PF_BLKIO 0x00000002 /* I am waiting on IO */
|
||||
|
||||
#ifdef CONFIG_TASK_DELAY_ACCT
|
||||
struct task_delay_info {
|
||||
raw_spinlock_t lock;
|
||||
unsigned int flags; /* Private per-task flags */
|
||||
|
||||
/* For each stat XXX, add following, aligned appropriately
|
||||
*
|
||||
@ -37,13 +28,13 @@ struct task_delay_info {
|
||||
* associated with the operation is added to XXX_delay.
|
||||
* XXX_delay contains the accumulated delay time in nanoseconds.
|
||||
*/
|
||||
u64 blkio_start; /* Shared by blkio, swapin */
|
||||
u64 blkio_start;
|
||||
u64 blkio_delay; /* wait for sync block io completion */
|
||||
u64 swapin_delay; /* wait for swapin block io completion */
|
||||
u64 swapin_start;
|
||||
u64 swapin_delay; /* wait for swapin */
|
||||
u32 blkio_count; /* total count of the number of sync block */
|
||||
/* io operations performed */
|
||||
u32 swapin_count; /* total count of the number of swapin block */
|
||||
/* io operations performed */
|
||||
u32 swapin_count; /* total count of swapin */
|
||||
|
||||
u64 freepages_start;
|
||||
u64 freepages_delay; /* wait for memory reclaim */
|
||||
@ -51,8 +42,12 @@ struct task_delay_info {
|
||||
u64 thrashing_start;
|
||||
u64 thrashing_delay; /* wait for thrashing page */
|
||||
|
||||
u64 compact_start;
|
||||
u64 compact_delay; /* wait for memory compact */
|
||||
|
||||
u32 freepages_count; /* total count of memory reclaim */
|
||||
u32 thrashing_count; /* total count of thrash waits */
|
||||
u32 compact_count; /* total count of memory compact */
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -79,26 +74,10 @@ extern void __delayacct_freepages_start(void);
|
||||
extern void __delayacct_freepages_end(void);
|
||||
extern void __delayacct_thrashing_start(void);
|
||||
extern void __delayacct_thrashing_end(void);
|
||||
|
||||
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
|
||||
{
|
||||
if (p->delays)
|
||||
return (p->delays->flags & DELAYACCT_PF_BLKIO);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void delayacct_set_flag(struct task_struct *p, int flag)
|
||||
{
|
||||
if (p->delays)
|
||||
p->delays->flags |= flag;
|
||||
}
|
||||
|
||||
static inline void delayacct_clear_flag(struct task_struct *p, int flag)
|
||||
{
|
||||
if (p->delays)
|
||||
p->delays->flags &= ~flag;
|
||||
}
|
||||
extern void __delayacct_swapin_start(void);
|
||||
extern void __delayacct_swapin_end(void);
|
||||
extern void __delayacct_compact_start(void);
|
||||
extern void __delayacct_compact_end(void);
|
||||
|
||||
static inline void delayacct_tsk_init(struct task_struct *tsk)
|
||||
{
|
||||
@ -123,7 +102,6 @@ static inline void delayacct_blkio_start(void)
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
delayacct_set_flag(current, DELAYACCT_PF_BLKIO);
|
||||
if (current->delays)
|
||||
__delayacct_blkio_start();
|
||||
}
|
||||
@ -135,7 +113,6 @@ static inline void delayacct_blkio_end(struct task_struct *p)
|
||||
|
||||
if (p->delays)
|
||||
__delayacct_blkio_end(p);
|
||||
delayacct_clear_flag(p, DELAYACCT_PF_BLKIO);
|
||||
}
|
||||
|
||||
static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
|
||||
@ -147,33 +124,77 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
|
||||
|
||||
static inline void delayacct_freepages_start(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_freepages_start();
|
||||
}
|
||||
|
||||
static inline void delayacct_freepages_end(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_freepages_end();
|
||||
}
|
||||
|
||||
static inline void delayacct_thrashing_start(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_thrashing_start();
|
||||
}
|
||||
|
||||
static inline void delayacct_thrashing_end(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_thrashing_end();
|
||||
}
|
||||
|
||||
static inline void delayacct_swapin_start(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_swapin_start();
|
||||
}
|
||||
|
||||
static inline void delayacct_swapin_end(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_swapin_end();
|
||||
}
|
||||
|
||||
static inline void delayacct_compact_start(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_compact_start();
|
||||
}
|
||||
|
||||
static inline void delayacct_compact_end(void)
|
||||
{
|
||||
if (!static_branch_unlikely(&delayacct_key))
|
||||
return;
|
||||
|
||||
if (current->delays)
|
||||
__delayacct_compact_end();
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void delayacct_set_flag(struct task_struct *p, int flag)
|
||||
{}
|
||||
static inline void delayacct_clear_flag(struct task_struct *p, int flag)
|
||||
{}
|
||||
static inline void delayacct_init(void)
|
||||
{}
|
||||
static inline void delayacct_tsk_init(struct task_struct *tsk)
|
||||
@ -199,6 +220,14 @@ static inline void delayacct_thrashing_start(void)
|
||||
{}
|
||||
static inline void delayacct_thrashing_end(void)
|
||||
{}
|
||||
static inline void delayacct_swapin_start(void)
|
||||
{}
|
||||
static inline void delayacct_swapin_end(void)
|
||||
{}
|
||||
static inline void delayacct_compact_start(void)
|
||||
{}
|
||||
static inline void delayacct_compact_end(void)
|
||||
{}
|
||||
|
||||
#endif /* CONFIG_TASK_DELAY_ACCT */
|
||||
|
||||
|
@ -43,6 +43,11 @@ struct compat_elf_prpsinfo
|
||||
__compat_uid_t pr_uid;
|
||||
__compat_gid_t pr_gid;
|
||||
compat_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
|
||||
/*
|
||||
* The hard-coded 16 is derived from TASK_COMM_LEN, but it can't be
|
||||
* changed as it is exposed to userspace. We'd better make it hard-coded
|
||||
* here.
|
||||
*/
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
};
|
||||
|
@ -65,6 +65,11 @@ struct elf_prpsinfo
|
||||
__kernel_gid_t pr_gid;
|
||||
pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
|
||||
/* Lots missing */
|
||||
/*
|
||||
* The hard-coded 16 is derived from TASK_COMM_LEN, but it can't be
|
||||
* changed as it is exposed to userspace. We'd better make it hard-coded
|
||||
* here.
|
||||
*/
|
||||
char pr_fname[16]; /* filename of executable */
|
||||
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
|
||||
};
|
||||
|
@ -62,10 +62,7 @@ static inline u32 __hash_32_generic(u32 val)
|
||||
return val * GOLDEN_RATIO_32;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ARCH_HASH_32
|
||||
#define hash_32 hash_32_generic
|
||||
#endif
|
||||
static inline u32 hash_32_generic(u32 val, unsigned int bits)
|
||||
static inline u32 hash_32(u32 val, unsigned int bits)
|
||||
{
|
||||
/* High bits are more random, so use them. */
|
||||
return __hash_32(val) >> (32 - bits);
|
||||
|
@ -1,4 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* NOTE:
|
||||
*
|
||||
* This header has combined a lot of unrelated to each other stuff.
|
||||
* The process of splitting its content is in progress while keeping
|
||||
* backward compatibility. That's why it's highly recommended NOT to
|
||||
* include this header inside another header file, especially under
|
||||
* generic or architectural include/ directory.
|
||||
*/
|
||||
#ifndef _LINUX_KERNEL_H
|
||||
#define _LINUX_KERNEL_H
|
||||
|
||||
|
@ -33,6 +33,7 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
|
||||
unsigned int cpu,
|
||||
const char *namefmt);
|
||||
|
||||
void get_kthread_comm(char *buf, size_t buf_size, struct task_struct *tsk);
|
||||
bool set_kthread_struct(struct task_struct *p);
|
||||
|
||||
void kthread_set_per_cpu(struct task_struct *k, int cpu);
|
||||
|
@ -258,8 +258,7 @@ static inline void list_bulk_move_tail(struct list_head *head,
|
||||
* @list: the entry to test
|
||||
* @head: the head of the list
|
||||
*/
|
||||
static inline int list_is_first(const struct list_head *list,
|
||||
const struct list_head *head)
|
||||
static inline int list_is_first(const struct list_head *list, const struct list_head *head)
|
||||
{
|
||||
return list->prev == head;
|
||||
}
|
||||
@ -269,12 +268,21 @@ static inline int list_is_first(const struct list_head *list,
|
||||
* @list: the entry to test
|
||||
* @head: the head of the list
|
||||
*/
|
||||
static inline int list_is_last(const struct list_head *list,
|
||||
const struct list_head *head)
|
||||
static inline int list_is_last(const struct list_head *list, const struct list_head *head)
|
||||
{
|
||||
return list->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_is_head - tests whether @list is the list @head
|
||||
* @list: the entry to test
|
||||
* @head: the head of the list
|
||||
*/
|
||||
static inline int list_is_head(const struct list_head *list, const struct list_head *head)
|
||||
{
|
||||
return list == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
@ -318,7 +326,7 @@ static inline void list_del_init_careful(struct list_head *entry)
|
||||
static inline int list_empty_careful(const struct list_head *head)
|
||||
{
|
||||
struct list_head *next = smp_load_acquire(&head->next);
|
||||
return (next == head) && (next == head->prev);
|
||||
return list_is_head(next, head) && (next == head->prev);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -393,10 +401,9 @@ static inline void list_cut_position(struct list_head *list,
|
||||
{
|
||||
if (list_empty(head))
|
||||
return;
|
||||
if (list_is_singular(head) &&
|
||||
(head->next != entry && head != entry))
|
||||
if (list_is_singular(head) && !list_is_head(entry, head) && (entry != head->next))
|
||||
return;
|
||||
if (entry == head)
|
||||
if (list_is_head(entry, head))
|
||||
INIT_LIST_HEAD(list);
|
||||
else
|
||||
__list_cut_position(list, head, entry);
|
||||
@ -570,7 +577,7 @@ static inline void list_splice_tail_init(struct list_head *list,
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_continue - continue iteration over a list
|
||||
@ -580,7 +587,7 @@ static inline void list_splice_tail_init(struct list_head *list,
|
||||
* Continue to iterate over a list, continuing after the current position.
|
||||
*/
|
||||
#define list_for_each_continue(pos, head) \
|
||||
for (pos = pos->next; pos != (head); pos = pos->next)
|
||||
for (pos = pos->next; !list_is_head(pos, (head)); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
@ -588,7 +595,7 @@ static inline void list_splice_tail_init(struct list_head *list,
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
for (pos = (head)->prev; !list_is_head(pos, (head)); pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
@ -597,8 +604,9 @@ static inline void list_splice_tail_init(struct list_head *list,
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
for (pos = (head)->next, n = pos->next; \
|
||||
!list_is_head(pos, (head)); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
|
||||
@ -608,7 +616,7 @@ static inline void list_splice_tail_init(struct list_head *list,
|
||||
*/
|
||||
#define list_for_each_prev_safe(pos, n, head) \
|
||||
for (pos = (head)->prev, n = pos->prev; \
|
||||
pos != (head); \
|
||||
!list_is_head(pos, (head)); \
|
||||
pos = n, n = pos->prev)
|
||||
|
||||
/**
|
||||
|
@ -94,10 +94,7 @@ extern const char * const pcpu_fc_names[PCPU_FC_NR];
|
||||
|
||||
extern enum pcpu_fc pcpu_chosen_fc;
|
||||
|
||||
typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size,
|
||||
size_t align);
|
||||
typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size);
|
||||
typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr);
|
||||
typedef int (pcpu_fc_cpu_to_node_fn_t)(int cpu);
|
||||
typedef int (pcpu_fc_cpu_distance_fn_t)(unsigned int from, unsigned int to);
|
||||
|
||||
extern struct pcpu_alloc_info * __init pcpu_alloc_alloc_info(int nr_groups,
|
||||
@ -111,15 +108,13 @@ extern void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
|
||||
extern int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
|
||||
size_t atom_size,
|
||||
pcpu_fc_cpu_distance_fn_t cpu_distance_fn,
|
||||
pcpu_fc_alloc_fn_t alloc_fn,
|
||||
pcpu_fc_free_fn_t free_fn);
|
||||
pcpu_fc_cpu_to_node_fn_t cpu_to_nd_fn);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
void __init pcpu_populate_pte(unsigned long addr);
|
||||
extern int __init pcpu_page_first_chunk(size_t reserved_size,
|
||||
pcpu_fc_alloc_fn_t alloc_fn,
|
||||
pcpu_fc_free_fn_t free_fn,
|
||||
pcpu_fc_populate_pte_fn_t populate_pte_fn);
|
||||
pcpu_fc_cpu_to_node_fn_t cpu_to_nd_fn);
|
||||
#endif
|
||||
|
||||
extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align) __alloc_size(1);
|
||||
|
@ -178,8 +178,16 @@ static inline struct proc_dir_entry *proc_mkdir_mode(const char *name,
|
||||
#define proc_create_seq(name, mode, parent, ops) ({NULL;})
|
||||
#define proc_create_single(name, mode, parent, show) ({NULL;})
|
||||
#define proc_create_single_data(name, mode, parent, show, data) ({NULL;})
|
||||
#define proc_create(name, mode, parent, proc_ops) ({NULL;})
|
||||
#define proc_create_data(name, mode, parent, proc_ops, data) ({NULL;})
|
||||
|
||||
static inline struct proc_dir_entry *
|
||||
proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent,
|
||||
const struct proc_ops *proc_ops)
|
||||
{ return NULL; }
|
||||
|
||||
static inline struct proc_dir_entry *
|
||||
proc_create_data(const char *name, umode_t mode, struct proc_dir_entry *parent,
|
||||
const struct proc_ops *proc_ops, void *data)
|
||||
{ return NULL; }
|
||||
|
||||
static inline void proc_set_size(struct proc_dir_entry *de, loff_t size) {}
|
||||
static inline void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid) {}
|
||||
|
@ -274,8 +274,13 @@ struct task_group;
|
||||
|
||||
#define get_current_state() READ_ONCE(current->__state)
|
||||
|
||||
/* Task command name length: */
|
||||
#define TASK_COMM_LEN 16
|
||||
/*
|
||||
* Define the task command name length as enum, then it can be visible to
|
||||
* BPF programs.
|
||||
*/
|
||||
enum {
|
||||
TASK_COMM_LEN = 16,
|
||||
};
|
||||
|
||||
extern void scheduler_tick(void);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H
|
||||
#define _LINUX_UNALIGNED_PACKED_STRUCT_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct __una_u16 { u16 x; } __packed;
|
||||
struct __una_u32 { u32 x; } __packed;
|
||||
|
@ -17,14 +17,16 @@
|
||||
|
||||
enum error_detector {
|
||||
ERROR_DETECTOR_KFENCE,
|
||||
ERROR_DETECTOR_KASAN
|
||||
ERROR_DETECTOR_KASAN,
|
||||
ERROR_DETECTOR_WARN,
|
||||
};
|
||||
|
||||
#endif /* __ERROR_REPORT_DECLARE_TRACE_ENUMS_ONCE_ONLY */
|
||||
|
||||
#define error_detector_list \
|
||||
#define error_detector_list \
|
||||
EM(ERROR_DETECTOR_KFENCE, "kfence") \
|
||||
EMe(ERROR_DETECTOR_KASAN, "kasan")
|
||||
EM(ERROR_DETECTOR_KASAN, "kasan") \
|
||||
EMe(ERROR_DETECTOR_WARN, "warning")
|
||||
/* Always end the list with an EMe. */
|
||||
|
||||
#undef EM
|
||||
|
@ -34,7 +34,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#define TASKSTATS_VERSION 10
|
||||
#define TASKSTATS_VERSION 11
|
||||
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
|
||||
* in linux/sched.h */
|
||||
|
||||
@ -172,6 +172,10 @@ struct taskstats {
|
||||
|
||||
/* v10: 64-bit btime to avoid overflow */
|
||||
__u64 ac_btime64; /* 64-bit begin time */
|
||||
|
||||
/* Delay waiting for memory compact */
|
||||
__u64 compact_count;
|
||||
__u64 compact_delay_total;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,18 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* DO NOT USE in new code! This is solely for MEI due to legacy reasons */
|
||||
/*
|
||||
* UUID/GUID definition
|
||||
*
|
||||
* Copyright (C) 2010, Intel Corp.
|
||||
* Huang Ying <ying.huang@intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_LINUX_UUID_H_
|
||||
|
105
kernel/configs/debug.config
Normal file
105
kernel/configs/debug.config
Normal file
@ -0,0 +1,105 @@
|
||||
# The config is based on running daily CI for enterprise Linux distros to
|
||||
# seek regressions on linux-next builds on different bare-metal and virtual
|
||||
# platforms. It can be used for example,
|
||||
#
|
||||
# $ make ARCH=arm64 defconfig debug.config
|
||||
#
|
||||
# Keep alphabetically sorted inside each section.
|
||||
#
|
||||
# printk and dmesg options
|
||||
#
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
CONFIG_DYNAMIC_DEBUG=y
|
||||
CONFIG_PRINTK_CALLER=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_SYMBOLIC_ERRNAME=y
|
||||
#
|
||||
# Compile-time checks and compiler options
|
||||
#
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_SECTION_MISMATCH=y
|
||||
CONFIG_FRAME_WARN=2048
|
||||
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
|
||||
#
|
||||
# Generic Kernel Debugging Instruments
|
||||
#
|
||||
# CONFIG_UBSAN_ALIGNMENT is not set
|
||||
# CONFIG_UBSAN_DIV_ZERO is not set
|
||||
# CONFIG_UBSAN_TRAP is not set
|
||||
# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_FS_ALLOW_ALL=y
|
||||
CONFIG_DEBUG_IRQFLAGS=y
|
||||
CONFIG_UBSAN=y
|
||||
CONFIG_UBSAN_BOOL=y
|
||||
CONFIG_UBSAN_BOUNDS=y
|
||||
CONFIG_UBSAN_ENUM=y
|
||||
CONFIG_UBSAN_SHIFT=y
|
||||
CONFIG_UBSAN_UNREACHABLE=y
|
||||
#
|
||||
# Memory Debugging
|
||||
#
|
||||
# CONFIG_DEBUG_PAGEALLOC is not set
|
||||
# CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF is not set
|
||||
# CONFIG_DEBUG_RODATA_TEST is not set
|
||||
# CONFIG_DEBUG_WX is not set
|
||||
# CONFIG_KFENCE is not set
|
||||
# CONFIG_PAGE_POISONING is not set
|
||||
# CONFIG_SLUB_STATS is not set
|
||||
CONFIG_PAGE_EXTENSION=y
|
||||
CONFIG_PAGE_OWNER=y
|
||||
CONFIG_DEBUG_KMEMLEAK=y
|
||||
CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y
|
||||
CONFIG_DEBUG_OBJECTS=y
|
||||
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
|
||||
CONFIG_DEBUG_OBJECTS_FREE=y
|
||||
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
|
||||
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
|
||||
CONFIG_DEBUG_OBJECTS_TIMERS=y
|
||||
CONFIG_DEBUG_OBJECTS_WORK=y
|
||||
CONFIG_DEBUG_PER_CPU_MAPS=y
|
||||
CONFIG_DEBUG_STACK_USAGE=y
|
||||
CONFIG_DEBUG_VIRTUAL=y
|
||||
CONFIG_DEBUG_VM=y
|
||||
CONFIG_DEBUG_VM_PGFLAGS=y
|
||||
CONFIG_DEBUG_VM_RB=y
|
||||
CONFIG_DEBUG_VM_VMACACHE=y
|
||||
CONFIG_GENERIC_PTDUMP=y
|
||||
CONFIG_KASAN=y
|
||||
CONFIG_KASAN_GENERIC=y
|
||||
CONFIG_KASAN_INLINE=y
|
||||
CONFIG_KASAN_VMALLOC=y
|
||||
CONFIG_PTDUMP_DEBUGFS=y
|
||||
CONFIG_SCHED_STACK_END_CHECK=y
|
||||
CONFIG_SLUB_DEBUG_ON=y
|
||||
#
|
||||
# Debug Oops, Lockups and Hangs
|
||||
#
|
||||
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
|
||||
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
|
||||
CONFIG_DEBUG_ATOMIC_SLEEP=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_PANIC_ON_OOPS=y
|
||||
CONFIG_PANIC_TIMEOUT=0
|
||||
CONFIG_SOFTLOCKUP_DETECTOR=y
|
||||
#
|
||||
# Lock Debugging (spinlocks, mutexes, etc...)
|
||||
#
|
||||
# CONFIG_PROVE_RAW_LOCK_NESTING is not set
|
||||
CONFIG_PROVE_LOCKING=y
|
||||
#
|
||||
# Debug kernel data structures
|
||||
#
|
||||
CONFIG_BUG_ON_DATA_CORRUPTION=y
|
||||
#
|
||||
# RCU Debugging
|
||||
#
|
||||
CONFIG_PROVE_RCU=y
|
||||
CONFIG_PROVE_RCU_LIST=y
|
||||
#
|
||||
# Tracers
|
||||
#
|
||||
CONFIG_BRANCH_PROFILE_NONE=y
|
||||
CONFIG_DYNAMIC_FTRACE=y
|
||||
CONFIG_FTRACE=y
|
||||
CONFIG_FUNCTION_TRACER=y
|
@ -100,19 +100,10 @@ void __delayacct_blkio_start(void)
|
||||
*/
|
||||
void __delayacct_blkio_end(struct task_struct *p)
|
||||
{
|
||||
struct task_delay_info *delays = p->delays;
|
||||
u64 *total;
|
||||
u32 *count;
|
||||
|
||||
if (p->delays->flags & DELAYACCT_PF_SWAPIN) {
|
||||
total = &delays->swapin_delay;
|
||||
count = &delays->swapin_count;
|
||||
} else {
|
||||
total = &delays->blkio_delay;
|
||||
count = &delays->blkio_count;
|
||||
}
|
||||
|
||||
delayacct_end(&delays->lock, &delays->blkio_start, total, count);
|
||||
delayacct_end(&p->delays->lock,
|
||||
&p->delays->blkio_start,
|
||||
&p->delays->blkio_delay,
|
||||
&p->delays->blkio_count);
|
||||
}
|
||||
|
||||
int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
|
||||
@ -164,10 +155,13 @@ int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
|
||||
d->freepages_delay_total = (tmp < d->freepages_delay_total) ? 0 : tmp;
|
||||
tmp = d->thrashing_delay_total + tsk->delays->thrashing_delay;
|
||||
d->thrashing_delay_total = (tmp < d->thrashing_delay_total) ? 0 : tmp;
|
||||
tmp = d->compact_delay_total + tsk->delays->compact_delay;
|
||||
d->compact_delay_total = (tmp < d->compact_delay_total) ? 0 : tmp;
|
||||
d->blkio_count += tsk->delays->blkio_count;
|
||||
d->swapin_count += tsk->delays->swapin_count;
|
||||
d->freepages_count += tsk->delays->freepages_count;
|
||||
d->thrashing_count += tsk->delays->thrashing_count;
|
||||
d->compact_count += tsk->delays->compact_count;
|
||||
raw_spin_unlock_irqrestore(&tsk->delays->lock, flags);
|
||||
|
||||
return 0;
|
||||
@ -179,8 +173,7 @@ __u64 __delayacct_blkio_ticks(struct task_struct *tsk)
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&tsk->delays->lock, flags);
|
||||
ret = nsec_to_clock_t(tsk->delays->blkio_delay +
|
||||
tsk->delays->swapin_delay);
|
||||
ret = nsec_to_clock_t(tsk->delays->blkio_delay);
|
||||
raw_spin_unlock_irqrestore(&tsk->delays->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
@ -210,3 +203,29 @@ void __delayacct_thrashing_end(void)
|
||||
¤t->delays->thrashing_delay,
|
||||
¤t->delays->thrashing_count);
|
||||
}
|
||||
|
||||
void __delayacct_swapin_start(void)
|
||||
{
|
||||
current->delays->swapin_start = local_clock();
|
||||
}
|
||||
|
||||
void __delayacct_swapin_end(void)
|
||||
{
|
||||
delayacct_end(¤t->delays->lock,
|
||||
¤t->delays->swapin_start,
|
||||
¤t->delays->swapin_delay,
|
||||
¤t->delays->swapin_count);
|
||||
}
|
||||
|
||||
void __delayacct_compact_start(void)
|
||||
{
|
||||
current->delays->compact_start = local_clock();
|
||||
}
|
||||
|
||||
void __delayacct_compact_end(void)
|
||||
{
|
||||
delayacct_end(¤t->delays->lock,
|
||||
¤t->delays->compact_start,
|
||||
¤t->delays->compact_delay,
|
||||
¤t->delays->compact_count);
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ struct kthread {
|
||||
#ifdef CONFIG_BLK_CGROUP
|
||||
struct cgroup_subsys_state *blkcg_css;
|
||||
#endif
|
||||
/* To store the full name if task comm is truncated. */
|
||||
char *full_name;
|
||||
};
|
||||
|
||||
enum KTHREAD_BITS {
|
||||
@ -94,6 +96,18 @@ static inline struct kthread *__to_kthread(struct task_struct *p)
|
||||
return kthread;
|
||||
}
|
||||
|
||||
void get_kthread_comm(char *buf, size_t buf_size, struct task_struct *tsk)
|
||||
{
|
||||
struct kthread *kthread = to_kthread(tsk);
|
||||
|
||||
if (!kthread || !kthread->full_name) {
|
||||
__get_task_comm(buf, buf_size, tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
strscpy_pad(buf, kthread->full_name, buf_size);
|
||||
}
|
||||
|
||||
bool set_kthread_struct(struct task_struct *p)
|
||||
{
|
||||
struct kthread *kthread;
|
||||
@ -121,10 +135,14 @@ void free_kthread_struct(struct task_struct *k)
|
||||
* Can be NULL if kmalloc() in set_kthread_struct() failed.
|
||||
*/
|
||||
kthread = to_kthread(k);
|
||||
if (!kthread)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_BLK_CGROUP
|
||||
WARN_ON_ONCE(kthread && kthread->blkcg_css);
|
||||
WARN_ON_ONCE(kthread->blkcg_css);
|
||||
#endif
|
||||
k->worker_private = NULL;
|
||||
kfree(kthread->full_name);
|
||||
kfree(kthread);
|
||||
}
|
||||
|
||||
@ -438,12 +456,22 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
|
||||
task = create->result;
|
||||
if (!IS_ERR(task)) {
|
||||
char name[TASK_COMM_LEN];
|
||||
va_list aq;
|
||||
int len;
|
||||
|
||||
/*
|
||||
* task is already visible to other tasks, so updating
|
||||
* COMM must be protected.
|
||||
*/
|
||||
vsnprintf(name, sizeof(name), namefmt, args);
|
||||
va_copy(aq, args);
|
||||
len = vsnprintf(name, sizeof(name), namefmt, aq);
|
||||
va_end(aq);
|
||||
if (len >= TASK_COMM_LEN) {
|
||||
struct kthread *kthread = to_kthread(task);
|
||||
|
||||
/* leave it truncated when out of memory. */
|
||||
kthread->full_name = kvasprintf(GFP_KERNEL, namefmt, args);
|
||||
}
|
||||
set_task_comm(task, name);
|
||||
}
|
||||
kfree(create);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/bug.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <trace/events/error_report.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
#define PANIC_TIMER_STEP 100
|
||||
@ -533,26 +534,9 @@ void oops_enter(void)
|
||||
trigger_all_cpu_backtrace();
|
||||
}
|
||||
|
||||
/*
|
||||
* 64-bit random ID for oopses:
|
||||
*/
|
||||
static u64 oops_id;
|
||||
|
||||
static int init_oops_id(void)
|
||||
{
|
||||
if (!oops_id)
|
||||
get_random_bytes(&oops_id, sizeof(oops_id));
|
||||
else
|
||||
oops_id++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(init_oops_id);
|
||||
|
||||
static void print_oops_end_marker(void)
|
||||
{
|
||||
init_oops_id();
|
||||
pr_warn("---[ end trace %016llx ]---\n", (unsigned long long)oops_id);
|
||||
pr_warn("---[ end trace %016llx ]---\n", 0ULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -609,6 +593,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
|
||||
print_irqtrace_events(current);
|
||||
|
||||
print_oops_end_marker();
|
||||
trace_error_report_end(ERROR_DETECTOR_WARN, (unsigned long)caller);
|
||||
|
||||
/* Just a warning, don't kill lockdep. */
|
||||
add_taint(taint, LOCKDEP_STILL_OK);
|
||||
|
16
kernel/sys.c
16
kernel/sys.c
@ -220,7 +220,6 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
|
||||
niceval = MAX_NICE;
|
||||
|
||||
rcu_read_lock();
|
||||
read_lock(&tasklist_lock);
|
||||
switch (which) {
|
||||
case PRIO_PROCESS:
|
||||
if (who)
|
||||
@ -235,9 +234,11 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
|
||||
pgrp = find_vpid(who);
|
||||
else
|
||||
pgrp = task_pgrp(current);
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
|
||||
error = set_one_prio(p, niceval, error);
|
||||
} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
|
||||
read_unlock(&tasklist_lock);
|
||||
break;
|
||||
case PRIO_USER:
|
||||
uid = make_kuid(cred->user_ns, who);
|
||||
@ -249,16 +250,15 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
|
||||
if (!user)
|
||||
goto out_unlock; /* No processes for this user */
|
||||
}
|
||||
do_each_thread(g, p) {
|
||||
for_each_process_thread(g, p) {
|
||||
if (uid_eq(task_uid(p), uid) && task_pid_vnr(p))
|
||||
error = set_one_prio(p, niceval, error);
|
||||
} while_each_thread(g, p);
|
||||
}
|
||||
if (!uid_eq(uid, cred->uid))
|
||||
free_uid(user); /* For find_user() */
|
||||
break;
|
||||
}
|
||||
out_unlock:
|
||||
read_unlock(&tasklist_lock);
|
||||
rcu_read_unlock();
|
||||
out:
|
||||
return error;
|
||||
@ -283,7 +283,6 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
|
||||
return -EINVAL;
|
||||
|
||||
rcu_read_lock();
|
||||
read_lock(&tasklist_lock);
|
||||
switch (which) {
|
||||
case PRIO_PROCESS:
|
||||
if (who)
|
||||
@ -301,11 +300,13 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
|
||||
pgrp = find_vpid(who);
|
||||
else
|
||||
pgrp = task_pgrp(current);
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
|
||||
niceval = nice_to_rlimit(task_nice(p));
|
||||
if (niceval > retval)
|
||||
retval = niceval;
|
||||
} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
|
||||
read_unlock(&tasklist_lock);
|
||||
break;
|
||||
case PRIO_USER:
|
||||
uid = make_kuid(cred->user_ns, who);
|
||||
@ -317,19 +318,18 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
|
||||
if (!user)
|
||||
goto out_unlock; /* No processes for this user */
|
||||
}
|
||||
do_each_thread(g, p) {
|
||||
for_each_process_thread(g, p) {
|
||||
if (uid_eq(task_uid(p), uid) && task_pid_vnr(p)) {
|
||||
niceval = nice_to_rlimit(task_nice(p));
|
||||
if (niceval > retval)
|
||||
retval = niceval;
|
||||
}
|
||||
} while_each_thread(g, p);
|
||||
}
|
||||
if (!uid_eq(uid, cred->uid))
|
||||
free_uid(user); /* for find_user() */
|
||||
break;
|
||||
}
|
||||
out_unlock:
|
||||
read_unlock(&tasklist_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
return retval;
|
||||
|
@ -1984,6 +1984,8 @@ config KCOV
|
||||
bool "Code coverage for fuzzing"
|
||||
depends on ARCH_HAS_KCOV
|
||||
depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS
|
||||
depends on !ARCH_WANTS_NO_INSTR || STACK_VALIDATION || \
|
||||
GCC_VERSION >= 120000 || CLANG_VERSION >= 130000
|
||||
select DEBUG_FS
|
||||
select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC
|
||||
help
|
||||
@ -2222,12 +2224,11 @@ config TEST_RHASHTABLE
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TEST_HASH
|
||||
tristate "Perform selftest on hash functions"
|
||||
config TEST_SIPHASH
|
||||
tristate "Perform selftest on siphash functions"
|
||||
help
|
||||
Enable this option to test the kernel's integer (<linux/hash.h>),
|
||||
string (<linux/stringhash.h>), and siphash (<linux/siphash.h>)
|
||||
hash functions on boot (or module load).
|
||||
Enable this option to test the kernel's siphash (<linux/siphash.h>) hash
|
||||
functions on boot (or module load).
|
||||
|
||||
This is intended to help people writing architecture-specific
|
||||
optimized versions. If unsure, say N.
|
||||
@ -2371,6 +2372,25 @@ config BITFIELD_KUNIT
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config HASH_KUNIT_TEST
|
||||
tristate "KUnit Test for integer hash functions" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable this option to test the kernel's string (<linux/stringhash.h>), and
|
||||
integer (<linux/hash.h>) hash functions on boot.
|
||||
|
||||
KUnit tests run during boot and output the results to the debug log
|
||||
in TAP format (https://testanything.org/). Only useful for kernel devs
|
||||
running the KUnit test harness, and not intended for inclusion into a
|
||||
production build.
|
||||
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
This is intended to help people writing architecture-specific
|
||||
optimized versions. If unsure, say N.
|
||||
|
||||
config RESOURCE_KUNIT_TEST
|
||||
tristate "KUnit test for resource API"
|
||||
depends on KUNIT
|
||||
@ -2502,6 +2522,7 @@ config TEST_KMOD
|
||||
depends on m
|
||||
depends on NETDEVICES && NET_CORE && INET # for TUN
|
||||
depends on BLOCK
|
||||
depends on PAGE_SIZE_LESS_THAN_256KB # for BTRFS
|
||||
select TEST_LKM
|
||||
select XFS_FS
|
||||
select TUN
|
||||
|
@ -112,19 +112,6 @@ config UBSAN_UNREACHABLE
|
||||
This option enables -fsanitize=unreachable which checks for control
|
||||
flow reaching an expected-to-be-unreachable position.
|
||||
|
||||
config UBSAN_OBJECT_SIZE
|
||||
bool "Perform checking for accesses beyond the end of objects"
|
||||
default UBSAN
|
||||
# gcc hugely expands stack usage with -fsanitize=object-size
|
||||
# https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/
|
||||
depends on !CC_IS_GCC
|
||||
depends on $(cc-option,-fsanitize=object-size)
|
||||
help
|
||||
This option enables -fsanitize=object-size which checks for accesses
|
||||
beyond the end of objects where the optimizer can determine both the
|
||||
object being operated on and its size, usually seen with bad downcasts,
|
||||
or access to struct members from NULL pointers.
|
||||
|
||||
config UBSAN_BOOL
|
||||
bool "Perform checking for non-boolean values used as boolean"
|
||||
default UBSAN
|
||||
|
@ -61,7 +61,8 @@ obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
|
||||
obj-$(CONFIG_TEST_BITOPS) += test_bitops.o
|
||||
CFLAGS_test_bitops.o += -Werror
|
||||
obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
|
||||
obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
|
||||
obj-$(CONFIG_TEST_SIPHASH) += test_siphash.o
|
||||
obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o
|
||||
obj-$(CONFIG_TEST_IDA) += test_ida.o
|
||||
obj-$(CONFIG_KASAN_KUNIT_TEST) += test_kasan.o
|
||||
CFLAGS_test_kasan.o += -fno-builtin
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "kstrtox.h"
|
||||
|
||||
noinline
|
||||
const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
|
||||
{
|
||||
if (*base == 0) {
|
||||
@ -47,6 +48,7 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
|
||||
*
|
||||
* Don't you dare use this function.
|
||||
*/
|
||||
noinline
|
||||
unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
|
||||
size_t max_chars)
|
||||
{
|
||||
@ -85,6 +87,7 @@ unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned lon
|
||||
return rv;
|
||||
}
|
||||
|
||||
noinline
|
||||
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
|
||||
{
|
||||
return _parse_integer_limit(s, base, p, INT_MAX);
|
||||
@ -125,6 +128,7 @@ static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
|
||||
* Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
|
||||
* Preferred over simple_strtoull(). Return code must be checked.
|
||||
*/
|
||||
noinline
|
||||
int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
|
||||
{
|
||||
if (s[0] == '+')
|
||||
@ -148,6 +152,7 @@ EXPORT_SYMBOL(kstrtoull);
|
||||
* Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
|
||||
* Preferred over simple_strtoll(). Return code must be checked.
|
||||
*/
|
||||
noinline
|
||||
int kstrtoll(const char *s, unsigned int base, long long *res)
|
||||
{
|
||||
unsigned long long tmp;
|
||||
@ -219,6 +224,7 @@ EXPORT_SYMBOL(_kstrtol);
|
||||
* Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
|
||||
* Preferred over simple_strtoul(). Return code must be checked.
|
||||
*/
|
||||
noinline
|
||||
int kstrtouint(const char *s, unsigned int base, unsigned int *res)
|
||||
{
|
||||
unsigned long long tmp;
|
||||
@ -249,6 +255,7 @@ EXPORT_SYMBOL(kstrtouint);
|
||||
* Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
|
||||
* Preferred over simple_strtol(). Return code must be checked.
|
||||
*/
|
||||
noinline
|
||||
int kstrtoint(const char *s, unsigned int base, int *res)
|
||||
{
|
||||
long long tmp;
|
||||
@ -264,6 +271,7 @@ int kstrtoint(const char *s, unsigned int base, int *res)
|
||||
}
|
||||
EXPORT_SYMBOL(kstrtoint);
|
||||
|
||||
noinline
|
||||
int kstrtou16(const char *s, unsigned int base, u16 *res)
|
||||
{
|
||||
unsigned long long tmp;
|
||||
@ -279,6 +287,7 @@ int kstrtou16(const char *s, unsigned int base, u16 *res)
|
||||
}
|
||||
EXPORT_SYMBOL(kstrtou16);
|
||||
|
||||
noinline
|
||||
int kstrtos16(const char *s, unsigned int base, s16 *res)
|
||||
{
|
||||
long long tmp;
|
||||
@ -294,6 +303,7 @@ int kstrtos16(const char *s, unsigned int base, s16 *res)
|
||||
}
|
||||
EXPORT_SYMBOL(kstrtos16);
|
||||
|
||||
noinline
|
||||
int kstrtou8(const char *s, unsigned int base, u8 *res)
|
||||
{
|
||||
unsigned long long tmp;
|
||||
@ -309,6 +319,7 @@ int kstrtou8(const char *s, unsigned int base, u8 *res)
|
||||
}
|
||||
EXPORT_SYMBOL(kstrtou8);
|
||||
|
||||
noinline
|
||||
int kstrtos8(const char *s, unsigned int base, s8 *res)
|
||||
{
|
||||
long long tmp;
|
||||
@ -333,6 +344,7 @@ EXPORT_SYMBOL(kstrtos8);
|
||||
* [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
|
||||
* pointed to by res is updated upon finding a match.
|
||||
*/
|
||||
noinline
|
||||
int kstrtobool(const char *s, bool *res)
|
||||
{
|
||||
if (!s)
|
||||
|
@ -49,11 +49,11 @@ bool __list_del_entry_valid(struct list_head *entry)
|
||||
"list_del corruption, %px->prev is LIST_POISON2 (%px)\n",
|
||||
entry, LIST_POISON2) ||
|
||||
CHECK_DATA_CORRUPTION(prev->next != entry,
|
||||
"list_del corruption. prev->next should be %px, but was %px\n",
|
||||
entry, prev->next) ||
|
||||
"list_del corruption. prev->next should be %px, but was %px. (prev=%px)\n",
|
||||
entry, prev->next, prev) ||
|
||||
CHECK_DATA_CORRUPTION(next->prev != entry,
|
||||
"list_del corruption. next->prev should be %px, but was %px\n",
|
||||
entry, next->prev))
|
||||
"list_del corruption. next->prev should be %px, but was %px. (next=%px)\n",
|
||||
entry, next->prev, next))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -36,6 +36,8 @@
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/string.h> /* memset, memcpy */
|
||||
|
||||
#define FORCE_INLINE __always_inline
|
||||
|
261
lib/test_hash.c
261
lib/test_hash.c
@ -14,17 +14,15 @@
|
||||
* and hash_64().
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt "\n"
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/stringhash.h>
|
||||
#include <linux/printk.h>
|
||||
#include <kunit/test.h>
|
||||
|
||||
/* 32-bit XORSHIFT generator. Seed must not be zero. */
|
||||
static u32 __init __attribute_const__
|
||||
static u32 __attribute_const__
|
||||
xorshift(u32 seed)
|
||||
{
|
||||
seed ^= seed << 13;
|
||||
@ -34,7 +32,7 @@ xorshift(u32 seed)
|
||||
}
|
||||
|
||||
/* Given a non-zero x, returns a non-zero byte. */
|
||||
static u8 __init __attribute_const__
|
||||
static u8 __attribute_const__
|
||||
mod255(u32 x)
|
||||
{
|
||||
x = (x & 0xffff) + (x >> 16); /* 1 <= x <= 0x1fffe */
|
||||
@ -45,8 +43,7 @@ mod255(u32 x)
|
||||
}
|
||||
|
||||
/* Fill the buffer with non-zero bytes. */
|
||||
static void __init
|
||||
fill_buf(char *buf, size_t len, u32 seed)
|
||||
static void fill_buf(char *buf, size_t len, u32 seed)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -56,6 +53,50 @@ fill_buf(char *buf, size_t len, u32 seed)
|
||||
}
|
||||
}
|
||||
|
||||
/* Holds most testing variables for the int test. */
|
||||
struct test_hash_params {
|
||||
/* Pointer to integer to be hashed. */
|
||||
unsigned long long *h64;
|
||||
/* Low 32-bits of integer to be hashed. */
|
||||
u32 h0;
|
||||
/* Arch-specific hash result. */
|
||||
u32 h1;
|
||||
/* Generic hash result. */
|
||||
u32 h2;
|
||||
/* ORed hashes of given size (in bits). */
|
||||
u32 (*hash_or)[33];
|
||||
};
|
||||
|
||||
#ifdef HAVE_ARCH__HASH_32
|
||||
static void
|
||||
test_int__hash_32(struct kunit *test, struct test_hash_params *params)
|
||||
{
|
||||
params->hash_or[1][0] |= params->h2 = __hash_32_generic(params->h0);
|
||||
#if HAVE_ARCH__HASH_32 == 1
|
||||
KUNIT_EXPECT_EQ_MSG(test, params->h1, params->h2,
|
||||
"__hash_32(%#x) = %#x != __hash_32_generic() = %#x",
|
||||
params->h0, params->h1, params->h2);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARCH_HASH_64
|
||||
static void
|
||||
test_int_hash_64(struct kunit *test, struct test_hash_params *params, u32 const *m, int *k)
|
||||
{
|
||||
params->h2 = hash_64_generic(*params->h64, *k);
|
||||
#if HAVE_ARCH_HASH_64 == 1
|
||||
KUNIT_EXPECT_EQ_MSG(test, params->h1, params->h2,
|
||||
"hash_64(%#llx, %d) = %#x != hash_64_generic() = %#x",
|
||||
*params->h64, *k, params->h1, params->h2);
|
||||
#else
|
||||
KUNIT_EXPECT_LE_MSG(test, params->h1, params->h2,
|
||||
"hash_64_generic(%#llx, %d) = %#x > %#x",
|
||||
*params->h64, *k, params->h1, *m);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Test the various integer hash functions. h64 (or its low-order bits)
|
||||
* is the integer to hash. hash_or accumulates the OR of the hash values,
|
||||
@ -65,23 +106,16 @@ fill_buf(char *buf, size_t len, u32 seed)
|
||||
* inline, the code being tested is actually in the module, and you can
|
||||
* recompile and re-test the module without rebooting.
|
||||
*/
|
||||
static bool __init
|
||||
test_int_hash(unsigned long long h64, u32 hash_or[2][33])
|
||||
static void
|
||||
test_int_hash(struct kunit *test, unsigned long long h64, u32 hash_or[2][33])
|
||||
{
|
||||
int k;
|
||||
u32 h0 = (u32)h64, h1, h2;
|
||||
struct test_hash_params params = { &h64, (u32)h64, 0, 0, hash_or };
|
||||
|
||||
/* Test __hash32 */
|
||||
hash_or[0][0] |= h1 = __hash_32(h0);
|
||||
hash_or[0][0] |= params.h1 = __hash_32(params.h0);
|
||||
#ifdef HAVE_ARCH__HASH_32
|
||||
hash_or[1][0] |= h2 = __hash_32_generic(h0);
|
||||
#if HAVE_ARCH__HASH_32 == 1
|
||||
if (h1 != h2) {
|
||||
pr_err("__hash_32(%#x) = %#x != __hash_32_generic() = %#x",
|
||||
h0, h1, h2);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
test_int__hash_32(test, ¶ms);
|
||||
#endif
|
||||
|
||||
/* Test k = 1..32 bits */
|
||||
@ -89,63 +123,53 @@ test_int_hash(unsigned long long h64, u32 hash_or[2][33])
|
||||
u32 const m = ((u32)2 << (k-1)) - 1; /* Low k bits set */
|
||||
|
||||
/* Test hash_32 */
|
||||
hash_or[0][k] |= h1 = hash_32(h0, k);
|
||||
if (h1 > m) {
|
||||
pr_err("hash_32(%#x, %d) = %#x > %#x", h0, k, h1, m);
|
||||
return false;
|
||||
}
|
||||
#ifdef HAVE_ARCH_HASH_32
|
||||
h2 = hash_32_generic(h0, k);
|
||||
#if HAVE_ARCH_HASH_32 == 1
|
||||
if (h1 != h2) {
|
||||
pr_err("hash_32(%#x, %d) = %#x != hash_32_generic() "
|
||||
" = %#x", h0, k, h1, h2);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (h2 > m) {
|
||||
pr_err("hash_32_generic(%#x, %d) = %#x > %#x",
|
||||
h0, k, h1, m);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
hash_or[0][k] |= params.h1 = hash_32(params.h0, k);
|
||||
KUNIT_EXPECT_LE_MSG(test, params.h1, m,
|
||||
"hash_32(%#x, %d) = %#x > %#x",
|
||||
params.h0, k, params.h1, m);
|
||||
|
||||
/* Test hash_64 */
|
||||
hash_or[1][k] |= h1 = hash_64(h64, k);
|
||||
if (h1 > m) {
|
||||
pr_err("hash_64(%#llx, %d) = %#x > %#x", h64, k, h1, m);
|
||||
return false;
|
||||
}
|
||||
hash_or[1][k] |= params.h1 = hash_64(h64, k);
|
||||
KUNIT_EXPECT_LE_MSG(test, params.h1, m,
|
||||
"hash_64(%#llx, %d) = %#x > %#x",
|
||||
h64, k, params.h1, m);
|
||||
#ifdef HAVE_ARCH_HASH_64
|
||||
h2 = hash_64_generic(h64, k);
|
||||
#if HAVE_ARCH_HASH_64 == 1
|
||||
if (h1 != h2) {
|
||||
pr_err("hash_64(%#llx, %d) = %#x != hash_64_generic() "
|
||||
"= %#x", h64, k, h1, h2);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (h2 > m) {
|
||||
pr_err("hash_64_generic(%#llx, %d) = %#x > %#x",
|
||||
h64, k, h1, m);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
test_int_hash_64(test, ¶ms, &m, &k);
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)h2; /* Suppress unused variable warning */
|
||||
return true;
|
||||
}
|
||||
|
||||
#define SIZE 256 /* Run time is cubic in SIZE */
|
||||
|
||||
static int __init
|
||||
test_hash_init(void)
|
||||
static void test_string_or(struct kunit *test)
|
||||
{
|
||||
char buf[SIZE+1];
|
||||
u32 string_or = 0, hash_or[2][33] = { { 0, } };
|
||||
unsigned tests = 0;
|
||||
u32 string_or = 0;
|
||||
int i, j;
|
||||
|
||||
fill_buf(buf, SIZE, 1);
|
||||
|
||||
/* Test every possible non-empty substring in the buffer. */
|
||||
for (j = SIZE; j > 0; --j) {
|
||||
buf[j] = '\0';
|
||||
|
||||
for (i = 0; i <= j; i++) {
|
||||
u32 h0 = full_name_hash(buf+i, buf+i, j-i);
|
||||
|
||||
string_or |= h0;
|
||||
} /* i */
|
||||
} /* j */
|
||||
|
||||
/* The OR of all the hash values should cover all the bits */
|
||||
KUNIT_EXPECT_EQ_MSG(test, string_or, -1u,
|
||||
"OR of all string hash results = %#x != %#x",
|
||||
string_or, -1u);
|
||||
}
|
||||
|
||||
static void test_hash_or(struct kunit *test)
|
||||
{
|
||||
char buf[SIZE+1];
|
||||
u32 hash_or[2][33] = { { 0, } };
|
||||
unsigned long long h64 = 0;
|
||||
int i, j;
|
||||
|
||||
@ -160,46 +184,27 @@ test_hash_init(void)
|
||||
u32 h0 = full_name_hash(buf+i, buf+i, j-i);
|
||||
|
||||
/* Check that hashlen_string gets the length right */
|
||||
if (hashlen_len(hashlen) != j-i) {
|
||||
pr_err("hashlen_string(%d..%d) returned length"
|
||||
" %u, expected %d",
|
||||
i, j, hashlen_len(hashlen), j-i);
|
||||
return -EINVAL;
|
||||
}
|
||||
KUNIT_EXPECT_EQ_MSG(test, hashlen_len(hashlen), j-i,
|
||||
"hashlen_string(%d..%d) returned length %u, expected %d",
|
||||
i, j, hashlen_len(hashlen), j-i);
|
||||
/* Check that the hashes match */
|
||||
if (hashlen_hash(hashlen) != h0) {
|
||||
pr_err("hashlen_string(%d..%d) = %08x != "
|
||||
"full_name_hash() = %08x",
|
||||
i, j, hashlen_hash(hashlen), h0);
|
||||
return -EINVAL;
|
||||
}
|
||||
KUNIT_EXPECT_EQ_MSG(test, hashlen_hash(hashlen), h0,
|
||||
"hashlen_string(%d..%d) = %08x != full_name_hash() = %08x",
|
||||
i, j, hashlen_hash(hashlen), h0);
|
||||
|
||||
string_or |= h0;
|
||||
h64 = h64 << 32 | h0; /* For use with hash_64 */
|
||||
if (!test_int_hash(h64, hash_or))
|
||||
return -EINVAL;
|
||||
tests++;
|
||||
test_int_hash(test, h64, hash_or);
|
||||
} /* i */
|
||||
} /* j */
|
||||
|
||||
/* The OR of all the hash values should cover all the bits */
|
||||
if (~string_or) {
|
||||
pr_err("OR of all string hash results = %#x != %#x",
|
||||
string_or, -1u);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (~hash_or[0][0]) {
|
||||
pr_err("OR of all __hash_32 results = %#x != %#x",
|
||||
hash_or[0][0], -1u);
|
||||
return -EINVAL;
|
||||
}
|
||||
KUNIT_EXPECT_EQ_MSG(test, hash_or[0][0], -1u,
|
||||
"OR of all __hash_32 results = %#x != %#x",
|
||||
hash_or[0][0], -1u);
|
||||
#ifdef HAVE_ARCH__HASH_32
|
||||
#if HAVE_ARCH__HASH_32 != 1 /* Test is pointless if results match */
|
||||
if (~hash_or[1][0]) {
|
||||
pr_err("OR of all __hash_32_generic results = %#x != %#x",
|
||||
hash_or[1][0], -1u);
|
||||
return -EINVAL;
|
||||
}
|
||||
KUNIT_EXPECT_EQ_MSG(test, hash_or[1][0], -1u,
|
||||
"OR of all __hash_32_generic results = %#x != %#x",
|
||||
hash_or[1][0], -1u);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -207,51 +212,27 @@ test_hash_init(void)
|
||||
for (i = 1; i <= 32; i++) {
|
||||
u32 const m = ((u32)2 << (i-1)) - 1; /* Low i bits set */
|
||||
|
||||
if (hash_or[0][i] != m) {
|
||||
pr_err("OR of all hash_32(%d) results = %#x "
|
||||
"(%#x expected)", i, hash_or[0][i], m);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (hash_or[1][i] != m) {
|
||||
pr_err("OR of all hash_64(%d) results = %#x "
|
||||
"(%#x expected)", i, hash_or[1][i], m);
|
||||
return -EINVAL;
|
||||
}
|
||||
KUNIT_EXPECT_EQ_MSG(test, hash_or[0][i], m,
|
||||
"OR of all hash_32(%d) results = %#x (%#x expected)",
|
||||
i, hash_or[0][i], m);
|
||||
KUNIT_EXPECT_EQ_MSG(test, hash_or[1][i], m,
|
||||
"OR of all hash_64(%d) results = %#x (%#x expected)",
|
||||
i, hash_or[1][i], m);
|
||||
}
|
||||
|
||||
/* Issue notices about skipped tests. */
|
||||
#ifdef HAVE_ARCH__HASH_32
|
||||
#if HAVE_ARCH__HASH_32 != 1
|
||||
pr_info("__hash_32() is arch-specific; not compared to generic.");
|
||||
#endif
|
||||
#else
|
||||
pr_info("__hash_32() has no arch implementation to test.");
|
||||
#endif
|
||||
#ifdef HAVE_ARCH_HASH_32
|
||||
#if HAVE_ARCH_HASH_32 != 1
|
||||
pr_info("hash_32() is arch-specific; not compared to generic.");
|
||||
#endif
|
||||
#else
|
||||
pr_info("hash_32() has no arch implementation to test.");
|
||||
#endif
|
||||
#ifdef HAVE_ARCH_HASH_64
|
||||
#if HAVE_ARCH_HASH_64 != 1
|
||||
pr_info("hash_64() is arch-specific; not compared to generic.");
|
||||
#endif
|
||||
#else
|
||||
pr_info("hash_64() has no arch implementation to test.");
|
||||
#endif
|
||||
|
||||
pr_notice("%u tests passed.", tests);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit test_hash_exit(void)
|
||||
{
|
||||
}
|
||||
static struct kunit_case hash_test_cases[] __refdata = {
|
||||
KUNIT_CASE(test_string_or),
|
||||
KUNIT_CASE(test_hash_or),
|
||||
{}
|
||||
};
|
||||
|
||||
module_init(test_hash_init); /* Does everything */
|
||||
module_exit(test_hash_exit); /* Does nothing */
|
||||
static struct kunit_suite hash_test_suite = {
|
||||
.name = "hash",
|
||||
.test_cases = hash_test_cases,
|
||||
};
|
||||
|
||||
|
||||
kunit_test_suite(hash_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -337,6 +337,7 @@ static int __init do_kmem_cache_size_bulk(int size, int *total_failures)
|
||||
if (num)
|
||||
kmem_cache_free_bulk(c, num, objects);
|
||||
}
|
||||
kmem_cache_destroy(c);
|
||||
*total_failures += fail;
|
||||
return 1;
|
||||
}
|
||||
|
@ -79,15 +79,6 @@ static void test_ubsan_load_invalid_value(void)
|
||||
eval2 = eval;
|
||||
}
|
||||
|
||||
static void test_ubsan_null_ptr_deref(void)
|
||||
{
|
||||
volatile int *ptr = NULL;
|
||||
int val;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE);
|
||||
val = *ptr;
|
||||
}
|
||||
|
||||
static void test_ubsan_misaligned_access(void)
|
||||
{
|
||||
volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5};
|
||||
@ -98,29 +89,16 @@ static void test_ubsan_misaligned_access(void)
|
||||
*ptr = val;
|
||||
}
|
||||
|
||||
static void test_ubsan_object_size_mismatch(void)
|
||||
{
|
||||
/* "((aligned(8)))" helps this not into be misaligned for ptr-access. */
|
||||
volatile int val __aligned(8) = 4;
|
||||
volatile long long *ptr, val2;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE);
|
||||
ptr = (long long *)&val;
|
||||
val2 = *ptr;
|
||||
}
|
||||
|
||||
static const test_ubsan_fp test_ubsan_array[] = {
|
||||
test_ubsan_shift_out_of_bounds,
|
||||
test_ubsan_out_of_bounds,
|
||||
test_ubsan_load_invalid_value,
|
||||
test_ubsan_misaligned_access,
|
||||
test_ubsan_object_size_mismatch,
|
||||
};
|
||||
|
||||
/* Excluded because they Oops the module. */
|
||||
static const test_ubsan_fp skip_ubsan_array[] = {
|
||||
test_ubsan_divrem_overflow,
|
||||
test_ubsan_null_ptr_deref,
|
||||
};
|
||||
|
||||
static int __init test_ubsan_init(void)
|
||||
|
12
mm/Kconfig
12
mm/Kconfig
@ -432,6 +432,18 @@ config NEED_PER_CPU_KM
|
||||
bool
|
||||
default y
|
||||
|
||||
config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
bool
|
||||
|
||||
config NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
bool
|
||||
|
||||
config USE_PERCPU_NUMA_NODE_ID
|
||||
bool
|
||||
|
||||
config HAVE_SETUP_PER_CPU_AREA
|
||||
bool
|
||||
|
||||
config CLEANCACHE
|
||||
bool "Enable cleancache driver to cache clean pages if tmem is present"
|
||||
help
|
||||
|
@ -3529,7 +3529,6 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
||||
if (unlikely(!si))
|
||||
goto out;
|
||||
|
||||
delayacct_set_flag(current, DELAYACCT_PF_SWAPIN);
|
||||
page = lookup_swap_cache(entry, vma, vmf->address);
|
||||
swapcache = page;
|
||||
|
||||
@ -3577,7 +3576,6 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
||||
vmf->address, &vmf->ptl);
|
||||
if (likely(pte_same(*vmf->pte, vmf->orig_pte)))
|
||||
ret = VM_FAULT_OOM;
|
||||
delayacct_clear_flag(current, DELAYACCT_PF_SWAPIN);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@ -3591,13 +3589,11 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
||||
* owner processes (which may be unknown at hwpoison time)
|
||||
*/
|
||||
ret = VM_FAULT_HWPOISON;
|
||||
delayacct_clear_flag(current, DELAYACCT_PF_SWAPIN);
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
locked = lock_page_or_retry(page, vma->vm_mm, vmf->flags);
|
||||
|
||||
delayacct_clear_flag(current, DELAYACCT_PF_SWAPIN);
|
||||
if (!locked) {
|
||||
ret |= VM_FAULT_RETRY;
|
||||
goto out_release;
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include <linux/padata.h>
|
||||
#include <linux/khugepaged.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/delayacct.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/div64.h>
|
||||
@ -4365,6 +4366,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
|
||||
return NULL;
|
||||
|
||||
psi_memstall_enter(&pflags);
|
||||
delayacct_compact_start();
|
||||
noreclaim_flag = memalloc_noreclaim_save();
|
||||
|
||||
*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
|
||||
@ -4372,6 +4374,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
|
||||
|
||||
memalloc_noreclaim_restore(noreclaim_flag);
|
||||
psi_memstall_leave(&pflags);
|
||||
delayacct_compact_end();
|
||||
|
||||
if (*compact_result == COMPACT_SKIPPED)
|
||||
return NULL;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/psi.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <linux/delayacct.h>
|
||||
|
||||
void end_swap_bio_write(struct bio *bio)
|
||||
{
|
||||
@ -370,6 +371,7 @@ int swap_readpage(struct page *page, bool synchronous)
|
||||
* significant part of overall IO time.
|
||||
*/
|
||||
psi_memstall_enter(&pflags);
|
||||
delayacct_swapin_start();
|
||||
|
||||
if (frontswap_load(page) == 0) {
|
||||
SetPageUptodate(page);
|
||||
@ -432,6 +434,7 @@ int swap_readpage(struct page *page, bool synchronous)
|
||||
|
||||
out:
|
||||
psi_memstall_leave(&pflags);
|
||||
delayacct_swapin_end();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
154
mm/percpu.c
154
mm/percpu.c
@ -2992,6 +2992,42 @@ static struct pcpu_alloc_info * __init __flatten pcpu_build_alloc_info(
|
||||
|
||||
return ai;
|
||||
}
|
||||
|
||||
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align,
|
||||
pcpu_fc_cpu_to_node_fn_t cpu_to_nd_fn)
|
||||
{
|
||||
const unsigned long goal = __pa(MAX_DMA_ADDRESS);
|
||||
#ifdef CONFIG_NUMA
|
||||
int node = NUMA_NO_NODE;
|
||||
void *ptr;
|
||||
|
||||
if (cpu_to_nd_fn)
|
||||
node = cpu_to_nd_fn(cpu);
|
||||
|
||||
if (node == NUMA_NO_NODE || !node_online(node) || !NODE_DATA(node)) {
|
||||
ptr = memblock_alloc_from(size, align, goal);
|
||||
pr_info("cpu %d has no node %d or node-local memory\n",
|
||||
cpu, node);
|
||||
pr_debug("per cpu data for cpu%d %zu bytes at 0x%llx\n",
|
||||
cpu, size, (u64)__pa(ptr));
|
||||
} else {
|
||||
ptr = memblock_alloc_try_nid(size, align, goal,
|
||||
MEMBLOCK_ALLOC_ACCESSIBLE,
|
||||
node);
|
||||
|
||||
pr_debug("per cpu data for cpu%d %zu bytes on node%d at 0x%llx\n",
|
||||
cpu, size, node, (u64)__pa(ptr));
|
||||
}
|
||||
return ptr;
|
||||
#else
|
||||
return memblock_alloc_from(size, align, goal);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init pcpu_fc_free(void *ptr, size_t size)
|
||||
{
|
||||
memblock_free(ptr, size);
|
||||
}
|
||||
#endif /* BUILD_EMBED_FIRST_CHUNK || BUILD_PAGE_FIRST_CHUNK */
|
||||
|
||||
#if defined(BUILD_EMBED_FIRST_CHUNK)
|
||||
@ -3001,14 +3037,13 @@ static struct pcpu_alloc_info * __init __flatten pcpu_build_alloc_info(
|
||||
* @dyn_size: minimum free size for dynamic allocation in bytes
|
||||
* @atom_size: allocation atom size
|
||||
* @cpu_distance_fn: callback to determine distance between cpus, optional
|
||||
* @alloc_fn: function to allocate percpu page
|
||||
* @free_fn: function to free percpu page
|
||||
* @cpu_to_nd_fn: callback to convert cpu to it's node, optional
|
||||
*
|
||||
* This is a helper to ease setting up embedded first percpu chunk and
|
||||
* can be called where pcpu_setup_first_chunk() is expected.
|
||||
*
|
||||
* If this function is used to setup the first chunk, it is allocated
|
||||
* by calling @alloc_fn and used as-is without being mapped into
|
||||
* by calling pcpu_fc_alloc and used as-is without being mapped into
|
||||
* vmalloc area. Allocations are always whole multiples of @atom_size
|
||||
* aligned to @atom_size.
|
||||
*
|
||||
@ -3022,7 +3057,7 @@ static struct pcpu_alloc_info * __init __flatten pcpu_build_alloc_info(
|
||||
* @dyn_size specifies the minimum dynamic area size.
|
||||
*
|
||||
* If the needed size is smaller than the minimum or specified unit
|
||||
* size, the leftover is returned using @free_fn.
|
||||
* size, the leftover is returned using pcpu_fc_free.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -errno on failure.
|
||||
@ -3030,8 +3065,7 @@ static struct pcpu_alloc_info * __init __flatten pcpu_build_alloc_info(
|
||||
int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
|
||||
size_t atom_size,
|
||||
pcpu_fc_cpu_distance_fn_t cpu_distance_fn,
|
||||
pcpu_fc_alloc_fn_t alloc_fn,
|
||||
pcpu_fc_free_fn_t free_fn)
|
||||
pcpu_fc_cpu_to_node_fn_t cpu_to_nd_fn)
|
||||
{
|
||||
void *base = (void *)ULONG_MAX;
|
||||
void **areas = NULL;
|
||||
@ -3066,7 +3100,7 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
|
||||
BUG_ON(cpu == NR_CPUS);
|
||||
|
||||
/* allocate space for the whole group */
|
||||
ptr = alloc_fn(cpu, gi->nr_units * ai->unit_size, atom_size);
|
||||
ptr = pcpu_fc_alloc(cpu, gi->nr_units * ai->unit_size, atom_size, cpu_to_nd_fn);
|
||||
if (!ptr) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free_areas;
|
||||
@ -3105,12 +3139,12 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
|
||||
for (i = 0; i < gi->nr_units; i++, ptr += ai->unit_size) {
|
||||
if (gi->cpu_map[i] == NR_CPUS) {
|
||||
/* unused unit, free whole */
|
||||
free_fn(ptr, ai->unit_size);
|
||||
pcpu_fc_free(ptr, ai->unit_size);
|
||||
continue;
|
||||
}
|
||||
/* copy and return the unused part */
|
||||
memcpy(ptr, __per_cpu_load, ai->static_size);
|
||||
free_fn(ptr + size_sum, ai->unit_size - size_sum);
|
||||
pcpu_fc_free(ptr + size_sum, ai->unit_size - size_sum);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3129,7 +3163,7 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
|
||||
out_free_areas:
|
||||
for (group = 0; group < ai->nr_groups; group++)
|
||||
if (areas[group])
|
||||
free_fn(areas[group],
|
||||
pcpu_fc_free(areas[group],
|
||||
ai->groups[group].nr_units * ai->unit_size);
|
||||
out_free:
|
||||
pcpu_free_alloc_info(ai);
|
||||
@ -3140,12 +3174,79 @@ out_free:
|
||||
#endif /* BUILD_EMBED_FIRST_CHUNK */
|
||||
|
||||
#ifdef BUILD_PAGE_FIRST_CHUNK
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
#ifndef P4D_TABLE_SIZE
|
||||
#define P4D_TABLE_SIZE PAGE_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef PUD_TABLE_SIZE
|
||||
#define PUD_TABLE_SIZE PAGE_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef PMD_TABLE_SIZE
|
||||
#define PMD_TABLE_SIZE PAGE_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef PTE_TABLE_SIZE
|
||||
#define PTE_TABLE_SIZE PAGE_SIZE
|
||||
#endif
|
||||
void __init __weak pcpu_populate_pte(unsigned long addr)
|
||||
{
|
||||
pgd_t *pgd = pgd_offset_k(addr);
|
||||
p4d_t *p4d;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
|
||||
if (pgd_none(*pgd)) {
|
||||
p4d_t *new;
|
||||
|
||||
new = memblock_alloc(P4D_TABLE_SIZE, P4D_TABLE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pgd_populate(&init_mm, pgd, new);
|
||||
}
|
||||
|
||||
p4d = p4d_offset(pgd, addr);
|
||||
if (p4d_none(*p4d)) {
|
||||
pud_t *new;
|
||||
|
||||
new = memblock_alloc(PUD_TABLE_SIZE, PUD_TABLE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
p4d_populate(&init_mm, p4d, new);
|
||||
}
|
||||
|
||||
pud = pud_offset(p4d, addr);
|
||||
if (pud_none(*pud)) {
|
||||
pmd_t *new;
|
||||
|
||||
new = memblock_alloc(PMD_TABLE_SIZE, PMD_TABLE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pud_populate(&init_mm, pud, new);
|
||||
}
|
||||
|
||||
pmd = pmd_offset(pud, addr);
|
||||
if (!pmd_present(*pmd)) {
|
||||
pte_t *new;
|
||||
|
||||
new = memblock_alloc(PTE_TABLE_SIZE, PTE_TABLE_SIZE);
|
||||
if (!new)
|
||||
goto err_alloc;
|
||||
pmd_populate_kernel(&init_mm, pmd, new);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_alloc:
|
||||
panic("%s: Failed to allocate memory\n", __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* pcpu_page_first_chunk - map the first chunk using PAGE_SIZE pages
|
||||
* @reserved_size: the size of reserved percpu area in bytes
|
||||
* @alloc_fn: function to allocate percpu page, always called with PAGE_SIZE
|
||||
* @free_fn: function to free percpu page, always called with PAGE_SIZE
|
||||
* @populate_pte_fn: function to populate pte
|
||||
* @cpu_to_nd_fn: callback to convert cpu to it's node, optional
|
||||
*
|
||||
* This is a helper to ease setting up page-remapped first percpu
|
||||
* chunk and can be called where pcpu_setup_first_chunk() is expected.
|
||||
@ -3156,10 +3257,7 @@ out_free:
|
||||
* RETURNS:
|
||||
* 0 on success, -errno on failure.
|
||||
*/
|
||||
int __init pcpu_page_first_chunk(size_t reserved_size,
|
||||
pcpu_fc_alloc_fn_t alloc_fn,
|
||||
pcpu_fc_free_fn_t free_fn,
|
||||
pcpu_fc_populate_pte_fn_t populate_pte_fn)
|
||||
int __init pcpu_page_first_chunk(size_t reserved_size, pcpu_fc_cpu_to_node_fn_t cpu_to_nd_fn)
|
||||
{
|
||||
static struct vm_struct vm;
|
||||
struct pcpu_alloc_info *ai;
|
||||
@ -3201,7 +3299,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
|
||||
for (i = 0; i < unit_pages; i++) {
|
||||
void *ptr;
|
||||
|
||||
ptr = alloc_fn(cpu, PAGE_SIZE, PAGE_SIZE);
|
||||
ptr = pcpu_fc_alloc(cpu, PAGE_SIZE, PAGE_SIZE, cpu_to_nd_fn);
|
||||
if (!ptr) {
|
||||
pr_warn("failed to allocate %s page for cpu%u\n",
|
||||
psize_str, cpu);
|
||||
@ -3223,7 +3321,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
|
||||
(unsigned long)vm.addr + unit * ai->unit_size;
|
||||
|
||||
for (i = 0; i < unit_pages; i++)
|
||||
populate_pte_fn(unit_addr + (i << PAGE_SHIFT));
|
||||
pcpu_populate_pte(unit_addr + (i << PAGE_SHIFT));
|
||||
|
||||
/* pte already populated, the following shouldn't fail */
|
||||
rc = __pcpu_map_pages(unit_addr, &pages[unit * unit_pages],
|
||||
@ -3253,7 +3351,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
|
||||
|
||||
enomem:
|
||||
while (--j >= 0)
|
||||
free_fn(page_address(pages[j]), PAGE_SIZE);
|
||||
pcpu_fc_free(page_address(pages[j]), PAGE_SIZE);
|
||||
rc = -ENOMEM;
|
||||
out_free_ar:
|
||||
memblock_free(pages, pages_size);
|
||||
@ -3278,17 +3376,6 @@ out_free_ar:
|
||||
unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
|
||||
EXPORT_SYMBOL(__per_cpu_offset);
|
||||
|
||||
static void * __init pcpu_dfl_fc_alloc(unsigned int cpu, size_t size,
|
||||
size_t align)
|
||||
{
|
||||
return memblock_alloc_from(size, align, __pa(MAX_DMA_ADDRESS));
|
||||
}
|
||||
|
||||
static void __init pcpu_dfl_fc_free(void *ptr, size_t size)
|
||||
{
|
||||
memblock_free(ptr, size);
|
||||
}
|
||||
|
||||
void __init setup_per_cpu_areas(void)
|
||||
{
|
||||
unsigned long delta;
|
||||
@ -3299,9 +3386,8 @@ void __init setup_per_cpu_areas(void)
|
||||
* Always reserve area for module percpu variables. That's
|
||||
* what the legacy allocator did.
|
||||
*/
|
||||
rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
|
||||
PERCPU_DYNAMIC_RESERVE, PAGE_SIZE, NULL,
|
||||
pcpu_dfl_fc_alloc, pcpu_dfl_fc_free);
|
||||
rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE, PERCPU_DYNAMIC_RESERVE,
|
||||
PAGE_SIZE, NULL, NULL);
|
||||
if (rc < 0)
|
||||
panic("Failed to initialize percpu areas.");
|
||||
|
||||
|
@ -113,11 +113,11 @@ static inline int update_counts(void *ctx, u32 pid, u64 delta)
|
||||
/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */
|
||||
struct sched_switch_args {
|
||||
unsigned long long pad;
|
||||
char prev_comm[16];
|
||||
char prev_comm[TASK_COMM_LEN];
|
||||
int prev_pid;
|
||||
int prev_prio;
|
||||
long long prev_state;
|
||||
char next_comm[16];
|
||||
char next_comm[TASK_COMM_LEN];
|
||||
int next_pid;
|
||||
int next_prio;
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sched.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
@ -22,17 +23,17 @@ int prog(struct pt_regs *ctx)
|
||||
{
|
||||
struct signal_struct *signal;
|
||||
struct task_struct *tsk;
|
||||
char oldcomm[16] = {};
|
||||
char newcomm[16] = {};
|
||||
char oldcomm[TASK_COMM_LEN] = {};
|
||||
char newcomm[TASK_COMM_LEN] = {};
|
||||
u16 oom_score_adj;
|
||||
u32 pid;
|
||||
|
||||
tsk = (void *)PT_REGS_PARM1(ctx);
|
||||
|
||||
pid = _(tsk->pid);
|
||||
bpf_probe_read_kernel(oldcomm, sizeof(oldcomm), &tsk->comm);
|
||||
bpf_probe_read_kernel(newcomm, sizeof(newcomm),
|
||||
(void *)PT_REGS_PARM2(ctx));
|
||||
bpf_probe_read_kernel_str(oldcomm, sizeof(oldcomm), &tsk->comm);
|
||||
bpf_probe_read_kernel_str(newcomm, sizeof(newcomm),
|
||||
(void *)PT_REGS_PARM2(ctx));
|
||||
signal = _(tsk->signal);
|
||||
oom_score_adj = _(signal->oom_score_adj);
|
||||
return 0;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/sched.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
@ -11,8 +12,8 @@
|
||||
struct task_rename {
|
||||
__u64 pad;
|
||||
__u32 pid;
|
||||
char oldcomm[16];
|
||||
char newcomm[16];
|
||||
char oldcomm[TASK_COMM_LEN];
|
||||
char newcomm[TASK_COMM_LEN];
|
||||
__u16 oom_score_adj;
|
||||
};
|
||||
SEC("tracepoint/task/task_rename")
|
||||
|
@ -8,7 +8,6 @@ ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds
|
||||
ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift
|
||||
ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero
|
||||
ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable
|
||||
ubsan-cflags-$(CONFIG_UBSAN_OBJECT_SIZE) += -fsanitize=object-size
|
||||
ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool
|
||||
ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum
|
||||
ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
|
||||
|
@ -3172,7 +3172,7 @@ sub process {
|
||||
length($line) > 75 &&
|
||||
!($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
|
||||
# file delta changes
|
||||
$line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
|
||||
$line =~ /^\s*(?:[\w\.\-\+]*\/)++[\w\.\-\+]+:/ ||
|
||||
# filename then :
|
||||
$line =~ /^\s*(?:Fixes:|Link:|$signature_tags)/i ||
|
||||
# A Fixes: or Link: line or signature tag line
|
||||
@ -3479,47 +3479,47 @@ sub process {
|
||||
# Kconfig supports named choices), so use a word boundary
|
||||
# (\b) rather than a whitespace character (\s)
|
||||
$line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
|
||||
my $length = 0;
|
||||
my $cnt = $realcnt;
|
||||
my $ln = $linenr + 1;
|
||||
my $f;
|
||||
my $is_start = 0;
|
||||
my $is_end = 0;
|
||||
for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
|
||||
$f = $lines[$ln - 1];
|
||||
$cnt-- if ($lines[$ln - 1] !~ /^-/);
|
||||
$is_end = $lines[$ln - 1] =~ /^\+/;
|
||||
my $ln = $linenr;
|
||||
my $needs_help = 0;
|
||||
my $has_help = 0;
|
||||
my $help_length = 0;
|
||||
while (defined $lines[$ln]) {
|
||||
my $f = $lines[$ln++];
|
||||
|
||||
next if ($f =~ /^-/);
|
||||
last if (!$file && $f =~ /^\@\@/);
|
||||
last if ($f !~ /^[\+ ]/); # !patch context
|
||||
|
||||
if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
|
||||
$is_start = 1;
|
||||
} elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
|
||||
$length = -1;
|
||||
if ($f =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
|
||||
$needs_help = 1;
|
||||
next;
|
||||
}
|
||||
if ($f =~ /^\+\s*help\s*$/) {
|
||||
$has_help = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
$f =~ s/^.//;
|
||||
$f =~ s/#.*//;
|
||||
$f =~ s/^\s+//;
|
||||
next if ($f =~ /^$/);
|
||||
$f =~ s/^.//; # strip patch context [+ ]
|
||||
$f =~ s/#.*//; # strip # directives
|
||||
$f =~ s/^\s+//; # strip leading blanks
|
||||
next if ($f =~ /^$/); # skip blank lines
|
||||
|
||||
# At the end of this Kconfig block:
|
||||
# This only checks context lines in the patch
|
||||
# and so hopefully shouldn't trigger false
|
||||
# positives, even though some of these are
|
||||
# common words in help texts
|
||||
if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
|
||||
if|endif|menu|endmenu|source)\b/x) {
|
||||
$is_end = 1;
|
||||
if ($f =~ /^(?:config|menuconfig|choice|endchoice|
|
||||
if|endif|menu|endmenu|source)\b/x) {
|
||||
last;
|
||||
}
|
||||
$length++;
|
||||
$help_length++ if ($has_help);
|
||||
}
|
||||
if ($is_start && $is_end && $length < $min_conf_desc_length) {
|
||||
if ($needs_help &&
|
||||
$help_length < $min_conf_desc_length) {
|
||||
my $stat_real = get_stat_real($linenr, $ln - 1);
|
||||
WARN("CONFIG_DESCRIPTION",
|
||||
"please write a paragraph that describes the config symbol fully\n" . $herecurr);
|
||||
"please write a help paragraph that fully describes the config symbol\n" . "$here\n$stat_real\n");
|
||||
}
|
||||
#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
|
||||
}
|
||||
|
||||
# check MAINTAINERS entries
|
||||
|
@ -12,19 +12,27 @@ driver_info
|
||||
drm_connector_funcs
|
||||
drm_encoder_funcs
|
||||
drm_encoder_helper_funcs
|
||||
dvb_frontend_ops
|
||||
dvb_tuner_ops
|
||||
ethtool_ops
|
||||
extent_io_ops
|
||||
fb_ops
|
||||
file_lock_operations
|
||||
file_operations
|
||||
hv_ops
|
||||
hwmon_ops
|
||||
ib_device_ops
|
||||
ide_dma_ops
|
||||
ide_port_ops
|
||||
ieee80211_ops
|
||||
iio_buffer_setup_ops
|
||||
inode_operations
|
||||
intel_dvo_dev_ops
|
||||
irq_domain_ops
|
||||
item_operations
|
||||
iwl_cfg
|
||||
iwl_ops
|
||||
kernel_param_ops
|
||||
kgdb_arch
|
||||
kgdb_io
|
||||
kset_uevent_ops
|
||||
@ -32,25 +40,33 @@ lock_manager_operations
|
||||
machine_desc
|
||||
microcode_ops
|
||||
mlxsw_reg_info
|
||||
mtd_ooblayout_ops
|
||||
mtrr_ops
|
||||
nand_controller_ops
|
||||
neigh_ops
|
||||
net_device_ops
|
||||
nft_expr_ops
|
||||
nlmsvc_binding
|
||||
nvkm_device_chip
|
||||
of_device_id
|
||||
pci_raw_ops
|
||||
phy_ops
|
||||
pinconf_ops
|
||||
pinctrl_ops
|
||||
pinmux_ops
|
||||
pipe_buf_operations
|
||||
platform_hibernation_ops
|
||||
platform_suspend_ops
|
||||
proc_ops
|
||||
proto_ops
|
||||
pwm_ops
|
||||
regmap_access_table
|
||||
regulator_ops
|
||||
reset_control_ops
|
||||
rpc_pipe_ops
|
||||
rtc_class_ops
|
||||
sd_desc
|
||||
sdhci_ops
|
||||
seq_operations
|
||||
sirfsoc_padmux
|
||||
snd_ac97_build_ops
|
||||
@ -67,6 +83,13 @@ uart_ops
|
||||
usb_mon_operations
|
||||
v4l2_ctrl_ops
|
||||
v4l2_ioctl_ops
|
||||
v4l2_subdev_core_ops
|
||||
v4l2_subdev_internal_ops
|
||||
v4l2_subdev_ops
|
||||
v4l2_subdev_pad_ops
|
||||
v4l2_subdev_video_ops
|
||||
vb2_ops
|
||||
vm_operations_struct
|
||||
wacom_features
|
||||
watchdog_ops
|
||||
wd_ops
|
||||
|
@ -1718,7 +1718,7 @@ sub vcs_exists {
|
||||
%VCS_cmds = %VCS_cmds_hg;
|
||||
return 2 if eval $VCS_cmds{"available"};
|
||||
%VCS_cmds = ();
|
||||
if (!$printed_novcs) {
|
||||
if (!$printed_novcs && $email_git) {
|
||||
warn("$P: No supported VCS found. Add --nogit to options?\n");
|
||||
warn("Using a git repository produces better results.\n");
|
||||
warn("Try Linus Torvalds' latest git repository using:\n");
|
||||
|
@ -205,6 +205,8 @@ static void print_delayacct(struct taskstats *t)
|
||||
"RECLAIM %12s%15s%15s\n"
|
||||
" %15llu%15llu%15llums\n"
|
||||
"THRASHING%12s%15s%15s\n"
|
||||
" %15llu%15llu%15llums\n"
|
||||
"COMPACT %12s%15s%15s\n"
|
||||
" %15llu%15llu%15llums\n",
|
||||
"count", "real total", "virtual total",
|
||||
"delay total", "delay average",
|
||||
@ -228,7 +230,11 @@ static void print_delayacct(struct taskstats *t)
|
||||
"count", "delay total", "delay average",
|
||||
(unsigned long long)t->thrashing_count,
|
||||
(unsigned long long)t->thrashing_delay_total,
|
||||
average_ms(t->thrashing_delay_total, t->thrashing_count));
|
||||
average_ms(t->thrashing_delay_total, t->thrashing_count),
|
||||
"count", "delay total", "delay average",
|
||||
(unsigned long long)t->compact_count,
|
||||
(unsigned long long)t->compact_delay_total,
|
||||
average_ms(t->compact_delay_total, t->compact_count));
|
||||
}
|
||||
|
||||
static void task_context_switch_counts(struct taskstats *t)
|
||||
|
@ -71,8 +71,8 @@ int iter(struct bpf_iter__task_file *ctx)
|
||||
|
||||
e.pid = task->tgid;
|
||||
e.id = get_obj_id(file->private_data, obj_type);
|
||||
bpf_probe_read_kernel(&e.comm, sizeof(e.comm),
|
||||
task->group_leader->comm);
|
||||
bpf_probe_read_kernel_str(&e.comm, sizeof(e.comm),
|
||||
task->group_leader->comm);
|
||||
bpf_seq_write(ctx->meta->seq, &e, sizeof(e));
|
||||
|
||||
return 0;
|
||||
|
@ -62,10 +62,7 @@ static inline u32 __hash_32_generic(u32 val)
|
||||
return val * GOLDEN_RATIO_32;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ARCH_HASH_32
|
||||
#define hash_32 hash_32_generic
|
||||
#endif
|
||||
static inline u32 hash_32_generic(u32 val, unsigned int bits)
|
||||
static inline u32 hash_32(u32 val, unsigned int bits)
|
||||
{
|
||||
/* High bits are more random, so use them. */
|
||||
return __hash_32(val) >> (32 - bits);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2018 Facebook
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <vmlinux.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
#ifndef PERF_MAX_STACK_DEPTH
|
||||
@ -41,11 +41,11 @@ struct {
|
||||
/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */
|
||||
struct sched_switch_args {
|
||||
unsigned long long pad;
|
||||
char prev_comm[16];
|
||||
char prev_comm[TASK_COMM_LEN];
|
||||
int prev_pid;
|
||||
int prev_prio;
|
||||
long long prev_state;
|
||||
char next_comm[16];
|
||||
char next_comm[TASK_COMM_LEN];
|
||||
int next_pid;
|
||||
int next_prio;
|
||||
};
|
||||
|
@ -1,17 +1,17 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2017 Facebook
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <vmlinux.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */
|
||||
struct sched_switch_args {
|
||||
unsigned long long pad;
|
||||
char prev_comm[16];
|
||||
char prev_comm[TASK_COMM_LEN];
|
||||
int prev_pid;
|
||||
int prev_prio;
|
||||
long long prev_state;
|
||||
char next_comm[16];
|
||||
char next_comm[TASK_COMM_LEN];
|
||||
int next_pid;
|
||||
int next_prio;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user