Skip to content

Commit 65d759c

Browse files
Charan Teja Reddytorvalds
authored andcommitted
mm: compaction: support triggering of proactive compaction by user
The proactive compaction[1] gets triggered for every 500msec and run compaction on the node for COMPACTION_HPAGE_ORDER (usually order-9) pages based on the value set to sysctl.compaction_proactiveness. Triggering the compaction for every 500msec in search of COMPACTION_HPAGE_ORDER pages is not needed for all applications, especially on the embedded system usecases which may have few MB's of RAM. Enabling the proactive compaction in its state will endup in running almost always on such systems. Other side, proactive compaction can still be very much useful for getting a set of higher order pages in some controllable manner(controlled by using the sysctl.compaction_proactiveness). So, on systems where enabling the proactive compaction always may proove not required, can trigger the same from user space on write to its sysctl interface. As an example, say app launcher decide to launch the memory heavy application which can be launched fast if it gets more higher order pages thus launcher can prepare the system in advance by triggering the proactive compaction from userspace. This triggering of proactive compaction is done on a write to sysctl.compaction_proactiveness by user. [1]https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=facdaa917c4d5a376d09d25865f5a863f906234a [akpm@linux-foundation.org: tweak vm.rst, per Mike] Link: https://lkml.kernel.org/r/1627653207-12317-1-git-send-email-charante@codeaurora.org Signed-off-by: Charan Teja Reddy <charante@codeaurora.org> Acked-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Rafael Aquini <aquini@redhat.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Luis Chamberlain <mcgrof@kernel.org> Cc: Kees Cook <keescook@chromium.org> Cc: Iurii Zaikin <yzaikin@google.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Mel Gorman <mgorman@techsingularity.net> Cc: Nitin Gupta <nigupta@nvidia.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Khalid Aziz <khalid.aziz@oracle.com> Cc: David Rientjes <rientjes@google.com> Cc: Vinayak Menon <vinmenon@codeaurora.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent e1e92bf commit 65d759c

5 files changed

Lines changed: 42 additions & 4 deletions

File tree

Documentation/admin-guide/sysctl/vm.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ compaction_proactiveness
118118

119119
This tunable takes a value in the range [0, 100] with a default value of
120120
20. This tunable determines how aggressively compaction is done in the
121-
background. Setting it to 0 disables proactive compaction.
121+
background. Write of a non zero value to this tunable will immediately
122+
trigger the proactive compaction. Setting it to 0 disables proactive compaction.
122123

123124
Note that compaction has a non-trivial system-wide impact as pages
124125
belonging to different processes are moved around, which could also lead

include/linux/compaction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ static inline unsigned long compact_gap(unsigned int order)
8484
extern unsigned int sysctl_compaction_proactiveness;
8585
extern int sysctl_compaction_handler(struct ctl_table *table, int write,
8686
void *buffer, size_t *length, loff_t *ppos);
87+
extern int compaction_proactiveness_sysctl_handler(struct ctl_table *table,
88+
int write, void *buffer, size_t *length, loff_t *ppos);
8789
extern int sysctl_extfrag_threshold;
8890
extern int sysctl_compact_unevictable_allowed;
8991

include/linux/mmzone.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ typedef struct pglist_data {
846846
enum zone_type kcompactd_highest_zoneidx;
847847
wait_queue_head_t kcompactd_wait;
848848
struct task_struct *kcompactd;
849+
bool proactive_compact_trigger;
849850
#endif
850851
/*
851852
* This is a per-node reserve of pages that are not available

kernel/sysctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2871,7 +2871,7 @@ static struct ctl_table vm_table[] = {
28712871
.data = &sysctl_compaction_proactiveness,
28722872
.maxlen = sizeof(sysctl_compaction_proactiveness),
28732873
.mode = 0644,
2874-
.proc_handler = proc_dointvec_minmax,
2874+
.proc_handler = compaction_proactiveness_sysctl_handler,
28752875
.extra1 = SYSCTL_ZERO,
28762876
.extra2 = &one_hundred,
28772877
},

mm/compaction.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,6 +2706,30 @@ static void compact_nodes(void)
27062706
*/
27072707
unsigned int __read_mostly sysctl_compaction_proactiveness = 20;
27082708

2709+
int compaction_proactiveness_sysctl_handler(struct ctl_table *table, int write,
2710+
void *buffer, size_t *length, loff_t *ppos)
2711+
{
2712+
int rc, nid;
2713+
2714+
rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
2715+
if (rc)
2716+
return rc;
2717+
2718+
if (write && sysctl_compaction_proactiveness) {
2719+
for_each_online_node(nid) {
2720+
pg_data_t *pgdat = NODE_DATA(nid);
2721+
2722+
if (pgdat->proactive_compact_trigger)
2723+
continue;
2724+
2725+
pgdat->proactive_compact_trigger = true;
2726+
wake_up_interruptible(&pgdat->kcompactd_wait);
2727+
}
2728+
}
2729+
2730+
return 0;
2731+
}
2732+
27092733
/*
27102734
* This is the entry point for compacting all nodes via
27112735
* /proc/sys/vm/compact_memory
@@ -2750,7 +2774,8 @@ void compaction_unregister_node(struct node *node)
27502774

27512775
static inline bool kcompactd_work_requested(pg_data_t *pgdat)
27522776
{
2753-
return pgdat->kcompactd_max_order > 0 || kthread_should_stop();
2777+
return pgdat->kcompactd_max_order > 0 || kthread_should_stop() ||
2778+
pgdat->proactive_compact_trigger;
27542779
}
27552780

27562781
static bool kcompactd_node_suitable(pg_data_t *pgdat)
@@ -2901,9 +2926,16 @@ static int kcompactd(void *p)
29012926
while (!kthread_should_stop()) {
29022927
unsigned long pflags;
29032928

2929+
/*
2930+
* Avoid the unnecessary wakeup for proactive compaction
2931+
* when it is disabled.
2932+
*/
2933+
if (!sysctl_compaction_proactiveness)
2934+
timeout = MAX_SCHEDULE_TIMEOUT;
29042935
trace_mm_compaction_kcompactd_sleep(pgdat->node_id);
29052936
if (wait_event_freezable_timeout(pgdat->kcompactd_wait,
2906-
kcompactd_work_requested(pgdat), timeout)) {
2937+
kcompactd_work_requested(pgdat), timeout) &&
2938+
!pgdat->proactive_compact_trigger) {
29072939

29082940
psi_memstall_enter(&pflags);
29092941
kcompactd_do_work(pgdat);
@@ -2938,6 +2970,8 @@ static int kcompactd(void *p)
29382970
timeout =
29392971
default_timeout << COMPACT_MAX_DEFER_SHIFT;
29402972
}
2973+
if (unlikely(pgdat->proactive_compact_trigger))
2974+
pgdat->proactive_compact_trigger = false;
29412975
}
29422976

29432977
return 0;

0 commit comments

Comments
 (0)