xfs: add kmem_alloc_by_vmalloc and kmem_alloc_large_dump_stack sysctl
Upstream: no Add dump stack logic when kmem_alloc failed. kmem_alloc_by_vmalloc: when kmem_alloc size larger than PAGE_SIZE * kmem_alloc_by_vmalloc, use vmalloc instead kmalloc. kmem_alloc_large_dump_stack: dump info and stack when kmem_alloc size larger than PAGE_SIZE*kmem_alloc_by_vmalloc. Signed-off-by: Kaixu Xia <kaixuxia@tencent.com> Signed-off-by: katrinzhou <katrinzhou@tencent.com> Signed-off-by: Kairui Song <kasong@tencent.com>
This commit is contained in:
parent
4330e77496
commit
9ffe8eb4df
|
@ -41,6 +41,7 @@ void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu)
|
|||
nmi_trigger_cpumask_backtrace(mask, exclude_cpu,
|
||||
nmi_raise_cpu_backtrace);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_trigger_cpumask_backtrace);
|
||||
|
||||
static int nmi_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
* All Rights Reserved.
|
||||
*/
|
||||
#include "xfs.h"
|
||||
#include <linux/nmi.h>
|
||||
#include "xfs_message.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_linux.h"
|
||||
|
||||
void *
|
||||
kmem_alloc(size_t size, xfs_km_flags_t flags)
|
||||
|
@ -16,15 +18,33 @@ kmem_alloc(size_t size, xfs_km_flags_t flags)
|
|||
|
||||
trace_kmem_alloc(size, flags, _RET_IP_);
|
||||
|
||||
if (xfs_kmem_alloc_by_vmalloc &&
|
||||
size > (PAGE_SIZE * xfs_kmem_alloc_by_vmalloc) &&
|
||||
xfs_kmem_alloc_large_dump_stack) {
|
||||
xfs_warn(NULL, "%s size: %ld large than %ld\n",
|
||||
__func__, size, PAGE_SIZE * xfs_kmem_alloc_by_vmalloc);
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
do {
|
||||
ptr = kmalloc(size, lflags);
|
||||
if (xfs_kmem_alloc_by_vmalloc && (size > PAGE_SIZE * xfs_kmem_alloc_by_vmalloc))
|
||||
ptr = __vmalloc(size, lflags);
|
||||
else
|
||||
ptr = kmalloc(size, lflags);
|
||||
if (ptr || (flags & KM_MAYFAIL))
|
||||
return ptr;
|
||||
if (!(++retries % 100))
|
||||
if (!(++retries % 100)) {
|
||||
xfs_err(NULL,
|
||||
"%s(%u) possible memory allocation deadlock size %u in %s (mode:0x%x)",
|
||||
"%s(%u) possible memory allocation deadlock size %u in %s (mode:0x%x), flags: 0x%x",
|
||||
current->comm, current->pid,
|
||||
(unsigned int)size, __func__, lflags);
|
||||
(unsigned int)size, __func__, lflags, flags);
|
||||
if (xfs_kmem_fail_dump_stack == 1)
|
||||
dump_stack();
|
||||
else if (xfs_kmem_fail_dump_stack == 2)
|
||||
trigger_all_cpu_backtrace();
|
||||
else if (xfs_kmem_fail_dump_stack == 3)
|
||||
__show_mem(0, NULL, gfp_zone(lflags));
|
||||
}
|
||||
memalloc_retry_wait(lflags);
|
||||
} while (1);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ xfs_param_t xfs_params = {
|
|||
.inherit_nodfrg = { 0, 1, 1 },
|
||||
.fstrm_timer = { 1, 30*100, 3600*100},
|
||||
.blockgc_timer = { 1, 300, 3600*24},
|
||||
.kmem_fail_dump_stack = { 0, 0, 3 },
|
||||
.kmem_alloc_by_vmalloc = { 0, 1, 4 },
|
||||
.kmem_alloc_large_dump_stack = { 0, 0, 1 },
|
||||
};
|
||||
|
||||
struct xfs_globals xfs_globals = {
|
||||
|
|
|
@ -103,6 +103,9 @@ typedef __u32 xfs_nlink_t;
|
|||
#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val
|
||||
#define xfs_fstrm_centisecs xfs_params.fstrm_timer.val
|
||||
#define xfs_blockgc_secs xfs_params.blockgc_timer.val
|
||||
#define xfs_kmem_fail_dump_stack xfs_params.kmem_fail_dump_stack.val
|
||||
#define xfs_kmem_alloc_by_vmalloc xfs_params.kmem_alloc_by_vmalloc.val
|
||||
#define xfs_kmem_alloc_large_dump_stack xfs_params.kmem_alloc_large_dump_stack.val
|
||||
|
||||
#define current_cpu() (raw_smp_processor_id())
|
||||
#define current_set_flags_nested(sp, f) \
|
||||
|
|
|
@ -206,6 +206,33 @@ static struct ctl_table xfs_table[] = {
|
|||
.extra2 = &xfs_params.stats_clear.max
|
||||
},
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
{
|
||||
.procname = "kmem_fail_dump_stack",
|
||||
.data = &xfs_params.kmem_fail_dump_stack.val,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &xfs_params.kmem_fail_dump_stack.min,
|
||||
.extra2 = &xfs_params.kmem_fail_dump_stack.max,
|
||||
},
|
||||
{
|
||||
.procname = "kmem_alloc_by_vmalloc",
|
||||
.data = &xfs_params.kmem_alloc_by_vmalloc.val,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &xfs_params.kmem_alloc_by_vmalloc.min,
|
||||
.extra2 = &xfs_params.kmem_alloc_by_vmalloc.max,
|
||||
},
|
||||
{
|
||||
.procname = "kmem_alloc_large_dump_stack",
|
||||
.data = &xfs_params.kmem_alloc_large_dump_stack.val,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &xfs_params.kmem_alloc_large_dump_stack.min,
|
||||
.extra2 = &xfs_params.kmem_alloc_large_dump_stack.max,
|
||||
},
|
||||
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -36,6 +36,9 @@ typedef struct xfs_param {
|
|||
xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
|
||||
xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */
|
||||
xfs_sysctl_val_t blockgc_timer; /* Interval between blockgc scans */
|
||||
xfs_sysctl_val_t kmem_fail_dump_stack;
|
||||
xfs_sysctl_val_t kmem_alloc_by_vmalloc;
|
||||
xfs_sysctl_val_t kmem_alloc_large_dump_stack;
|
||||
} xfs_param_t;
|
||||
|
||||
/*
|
||||
|
|
|
@ -427,3 +427,4 @@ void __show_mem(unsigned int filter, nodemask_t *nodemask, int max_zone_idx)
|
|||
printk("%lu pages hwpoisoned\n", atomic_long_read(&num_poisoned_pages));
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(__show_mem);
|
||||
|
|
Loading…
Reference in New Issue