diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h index 9d81fc7a94c7c504afb5dbcd55670e4d6ec185ba..164efeb81889daa86f41dc452b90f115ae4b66f7 100644 --- a/include/linux/share_pool.h +++ b/include/linux/share_pool.h @@ -40,6 +40,10 @@ extern int enable_ascend_share_pool; extern int sysctl_share_pool_map_lock_enable; +extern int sysctl_sp_compact_enable; +extern unsigned long sysctl_sp_compact_interval; +extern unsigned long sysctl_sp_compact_interval_max; + #ifdef CONFIG_HAVE_ARCH_HUGE_VMALLOC extern bool vmap_allow_huge; #endif diff --git a/kernel/sysctl.c b/kernel/sysctl.c index cd2d114f3391c123d6d0c4eb5024a44b03cf50cc..c5d4395efd43072087517a33fac0e762bc203b9b 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1789,6 +1789,24 @@ static struct ctl_table vm_table[] = { .extra1 = &zero, .extra2 = &one, }, + { + .procname = "sharepool_compact_enable", + .data = &sysctl_sp_compact_enable, + .maxlen = sizeof(sysctl_sp_compact_enable), + .mode = 0600, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { + .procname = "sharepool_compact_interval", + .data = &sysctl_sp_compact_interval, + .maxlen = sizeof(sysctl_sp_compact_interval), + .mode = 0600, + .proc_handler = proc_doulongvec_minmax, + .extra1 = &zero_ul, + .extra2 = &sysctl_sp_compact_interval_max, + }, #endif { } }; diff --git a/mm/share_pool.c b/mm/share_pool.c index 4c9105722c35e5b399b799d6be6f48a488fdd84a..ad842151f1c710521970abfa02ef850de58e41cd 100644 --- a/mm/share_pool.c +++ b/mm/share_pool.c @@ -1127,26 +1127,44 @@ void sp_area_drop(struct vm_area_struct *vma) spin_unlock(&sp_area_lock); } -static unsigned long last_jiffies; +int sysctl_sp_compact_enable; +unsigned long sysctl_sp_compact_interval = 30UL; +unsigned long sysctl_sp_compact_interval_max = 1000UL; +static unsigned long compact_last_jiffies; +static unsigned long compact_daemon_status; +#define COMPACT_START 1 +#define COMPACT_STOP 0 + static void sp_compact_nodes(struct work_struct *work) { sysctl_compaction_handler(NULL, 1, NULL, NULL, NULL); kfree(work); + + compact_last_jiffies = jiffies; + cmpxchg(&compact_daemon_status, COMPACT_START, COMPACT_STOP); } static void sp_add_work_compact(void) { struct work_struct *compact_work; - if (!time_after(jiffies, last_jiffies + 10 * HZ)) + if (!sysctl_sp_compact_enable) + return; + + /* experimental compaction time: 4GB->1.7s, 8GB->3.4s */ + if (!time_after(jiffies, + compact_last_jiffies + sysctl_sp_compact_interval * HZ)) + return; + + if (cmpxchg(&compact_daemon_status, COMPACT_STOP, COMPACT_START) == + COMPACT_START) return; compact_work = kzalloc(sizeof(*compact_work), GFP_KERNEL); if (!compact_work) return; - last_jiffies = jiffies; INIT_WORK(compact_work, sp_compact_nodes); schedule_work(compact_work); }