提交 009c22bb 编写于 作者: Y Yu Liao 提交者: Yongqiang Liu

mm: clear_freelist_page: Provide timeout mechanism for worker runtime

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I558LD
CVE: NA

--------------------------------

In the case of large memory, the clear freelist will hold zone lock
for a long time. As a result, the process may be blocked unless clear
freelist thread exit, and causing the system to be reset by the watchdog.

Provide a mechanism to stop clear freelist threads when elapsed time
exceeds cfp_timeout, which can be set by module_param().
Signed-off-by: NYu Liao <liaoyu15@huawei.com>
Reviewed-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NYongqiang Liu <liuyongqiang13@huawei.com>
上级 a5aba824
...@@ -13,8 +13,10 @@ ...@@ -13,8 +13,10 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/nmi.h> #include <linux/nmi.h>
#include <linux/sched/clock.h>
#include <linux/module.h> #include <linux/module.h>
#define CFP_DEFAULT_TIMEOUT 2000
#define for_each_populated_zone_pgdat(pgdat, zone) \ #define for_each_populated_zone_pgdat(pgdat, zone) \
for (zone = pgdat->node_zones; \ for (zone = pgdat->node_zones; \
zone; \ zone; \
...@@ -32,6 +34,7 @@ static DECLARE_WAIT_QUEUE_HEAD(clear_freelist_wait); ...@@ -32,6 +34,7 @@ static DECLARE_WAIT_QUEUE_HEAD(clear_freelist_wait);
static DEFINE_MUTEX(clear_freelist_lock); static DEFINE_MUTEX(clear_freelist_lock);
static atomic_t clear_freelist_workers; static atomic_t clear_freelist_workers;
static atomic_t clear_pages_num; static atomic_t clear_pages_num;
static ulong cfp_timeout_ms = CFP_DEFAULT_TIMEOUT;
static int one = 1; static int one = 1;
/* /*
...@@ -51,15 +54,25 @@ static struct zone *next_pgdat_zone(struct zone *zone) ...@@ -51,15 +54,25 @@ static struct zone *next_pgdat_zone(struct zone *zone)
static void clear_pgdat_freelist_pages(struct work_struct *work) static void clear_pgdat_freelist_pages(struct work_struct *work)
{ {
struct pgdat_entry *entry = container_of(work, struct pgdat_entry, work); struct pgdat_entry *entry = container_of(work, struct pgdat_entry, work);
u64 cfp_timeout_ns = cfp_timeout_ms * NSEC_PER_MSEC;
struct pglist_data *pgdat = entry->pgdat; struct pglist_data *pgdat = entry->pgdat;
unsigned long flags, order, t; unsigned long flags, order, t;
struct page *page; struct page *page;
struct zone *zone; struct zone *zone;
u64 start, now;
start = sched_clock();
for_each_populated_zone_pgdat(pgdat, zone) { for_each_populated_zone_pgdat(pgdat, zone) {
spin_lock_irqsave(&zone->lock, flags); spin_lock_irqsave(&zone->lock, flags);
for_each_migratetype_order(order, t) { for_each_migratetype_order(order, t) {
list_for_each_entry(page, &zone->free_area[order].free_list[t], lru) { list_for_each_entry(page, &zone->free_area[order].free_list[t], lru) {
now = sched_clock();
if (unlikely(now - start > cfp_timeout_ns)) {
spin_unlock_irqrestore(&zone->lock, flags);
goto out;
}
#ifdef CONFIG_KMAP_LOCAL #ifdef CONFIG_KMAP_LOCAL
int i; int i;
...@@ -77,6 +90,8 @@ static void clear_pgdat_freelist_pages(struct work_struct *work) ...@@ -77,6 +90,8 @@ static void clear_pgdat_freelist_pages(struct work_struct *work)
cond_resched(); cond_resched();
} }
out:
kfree(entry); kfree(entry);
if (atomic_dec_and_test(&clear_freelist_workers)) if (atomic_dec_and_test(&clear_freelist_workers))
...@@ -170,3 +185,4 @@ static int __init clear_freelist_init(void) ...@@ -170,3 +185,4 @@ static int __init clear_freelist_init(void)
return 0; return 0;
} }
module_init(clear_freelist_init); module_init(clear_freelist_init);
module_param(cfp_timeout_ms, ulong, 0644);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册