mm/compaction: Disable compact_unevictable_allowed on RT
Subsystems (6)
PATCH 1/1 mm/compaction: Disable compact_unevictable_allowed on RT
Since commit
5bbe3547aa3ba ("mm: allow compaction of unevictable pages")
it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make compact_unevictable_allowed = 0 default and remove it from /proc on RT.
--- kernel/sysctl.c | 3 ++- mm/compaction.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-)
kernel/sysctl.c +2 -1
@@ -1488,6 +1488,7 @@ static struct ctl_table vm_table[] = { .extra1 = &min_extfrag_threshold, .extra2 = &max_extfrag_threshold, }, +#ifndef CONFIG_PREEMPT_RT { .procname = "compact_unevictable_allowed", .data = &sysctl_compact_unevictable_allowed,
@@ -1497,7 +1498,7 @@ static struct ctl_table vm_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, - +#endif #endif /* CONFIG_COMPACTION */ { .procname = "min_free_kbytes",
mm/compaction.c +4 -0
@@ -1590,7 +1590,11 @@ typedef enum {* Allow userspace to control policy on scanning the unevictable LRU for * compactable pages. */ +#ifdef CONFIG_PREEMPT_RT +#define sysctl_compact_unevictable_allowed 0 +#else int sysctl_compact_unevictable_allowed__read_mostly =1 ; +#endif static inline void update_fast_start_pfn (struct compact_control *cc,unsigned long pfn)
Signature · 1 line
2.25.0.rc2
Quoted 6 lines · Sebastian Andrzej Siewior
Since commit
5bbe3547aa3ba("mm: allow compaction of unevictable pages")it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Fine, this makes sense on RT I guess. There might be some trade-off for high-order allocation latencies though. We could perhaps migrate such mlocked pages to pages allocated without __GFP_MOVABLE during the mlock() to at least somewhat prevent them being scattered all over the zones. For MCL_FUTURE, allocate them as unmovable from the beginning. But that can wait until issues are reported.
I assume you have similar solution for NUMA balancing and whatever else can cause minor faults?
Quoted 2 lines
Make
compact_unevictable_allowed= 0 default and remove it from /proc on RT.
Removing it is maybe going too far in terms of RT kernel differences confusing users? Change the default sure, perhaps making it read-only, but removing?
Quoted 1 line
In any case the sysctl Documentation/ should be updated? And perhaps also the mlock manpage as you noted in the older thread above?
Thanks,
Vlastimil
Quoted 44 lines
Signed-off-by Sebastian Andrzej Siewior <[email protected]>--- kernel/sysctl.c | 3 ++- mm/compaction.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-)kernel/sysctl.c +2
-1@@ -1488,6 +1488,7 @@ static struct ctl_table vm_table[] = { .extra1 = &min_extfrag_threshold, .extra2 = &max_extfrag_threshold, }, +#ifndef CONFIG_PREEMPT_RT { .procname = "compact_unevictable_allowed", .data = &sysctl_compact_unevictable_allowed,@@ -1497,7 +1498,7 @@ static struct ctl_table vm_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, - +#endif #endif /* CONFIG_COMPACTION */ { .procname = "min_free_kbytes",mm/compaction.c +4
-0@@ -1590,7 +1590,11 @@ typedef enum {* Allow userspace to control policy on scanning the unevictable LRU for * compactable pages. */ +#ifdef CONFIG_PREEMPT_RT +#define sysctl_compact_unevictable_allowed 0 +#else int sysctl_compact_unevictable_allowed__read_mostly =1 ; +#endif static inline void update_fast_start_pfn (struct compact_control *cc,unsigned long pfn)
Quoted 8 lines · Vlastimil Babka
Quoted 6 lines · Sebastian Andrzej Siewior
Since commit
5bbe3547aa3ba("mm: allow compaction of unevictable pages")it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Quoted 8 lines
Fine, this makes sense on RT I guess. There might be some trade-off for high-order allocation latencies though. We could perhaps migrate such mlocked pages to pages allocated without
__GFP_MOVABLEduring themlock()to at least somewhat prevent them being scattered all over the zones. ForMCL_FUTURE, allocate them as unmovable from the beginning. But that can wait until issues are reported.
I assume you have similar solution for NUMA balancing and whatever else can cause minor faults?
I've found this one while testing. Could you please point to the NUMA balancing that might be an issue?
Quoted 5 lines
Quoted 2 lines
Make
compact_unevictable_allowed= 0 default and remove it from /proc on RT.Removing it is maybe going too far in terms of RT kernel differences confusing users? Change the default sure, perhaps making it read-only, but removing?
Okay. I will make it RO then.
Quoted 4 lines
Quoted 1 line
In any case the sysctl
Documentation/should be updated? And perhaps also the mlock manpage as you noted in the older thread above?
Sure. Let me add the sysctl documentation to this patch and then I will look into the manpage.
Quoted 2 lines
Thanks,
Vlastimil
Sebastian
PATCH v2 1/1 mm/compaction: Disable compact_unevictable_allowed on RT
In reply to Vlastimil BabkaSince commit
5bbe3547aa3ba ("mm: allow compaction of unevictable pages")
it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make compact_unevictable_allowed = 0 default and RO on RT.
---
v1…v2: - Make the proc file RO instead removing it.
- Mention this change in Documentation/…/vm.rst.
Documentation/admin-guide/sysctl/vm.rst | 1 + kernel/sysctl.c | 4 ++++ mm/compaction.c | 4 ++++ 3 files changed, 9 insertions(+)
Documentation/admin-guide/sysctl/vm.rst +1 -0
@@ -128,6 +128,7 @@ allowed to examine the unevictable lru (mlocked pages) for pages to compact. This should be used on systems where stalls for minor page faults are an acceptable trade for large contiguous free memory. Set to 0 to prevent compaction from moving pages that are unevictable. Default value is 1. +On CONFIG_PREEMPT_RT the default value is 0. dirty_background_bytes
kernel/sysctl.c +4 -0
@@ -1483,7 +1483,11 @@ static struct ctl_table vm_table[] = { .procname = "compact_unevictable_allowed", .data = &sysctl_compact_unevictable_allowed, .maxlen =sizeof (int ), +#ifdef CONFIG_PREEMPT_RT + .mode = 0444, +#else .mode = 0644, +#endif .proc_handler = proc_dointvec, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE,
mm/compaction.c +4 -0
@@ -1590,7 +1590,11 @@ typedef enum {* Allow userspace to control policy on scanning the unevictable LRU for * compactable pages. */ +#ifdef CONFIG_PREEMPT_RT +int sysctl_compact_unevictable_allowed__read_mostly =0 ; +#else int sysctl_compact_unevictable_allowed__read_mostly =1 ; +#endif static inline void update_fast_start_pfn (struct compact_control *cc,unsigned long pfn)
Signature · 1 line
2.25.1
Andrew Morton
maintainerQuoted 8 lines · On Mon, 2 Mar 2020 18:35:16 +0100 Sebastian Andrzej Siewior…
Since commit
5bbe3547aa3ba("mm: allow compaction of unevictable pages")it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make
compact_unevictable_allowed= 0 default and RO on RT.
hm, that's a bit sad but I guess it's tolerable.
Documentation/admin-guide/sysctl/vm.rst allowed to examine the unevictable lru (mlocked pages) for pages to compact. · line 131
Quoted 10 lines
...
index
64aeee1009cab..bbfa59d25eec3100644Documentation/admin-guide/sysctl/vm.rst +1
-0@@ -128,6 +128,7 @@ allowed to examine the unevictable lru (mlocked pages) for pages to compact. This should be used on systems where stalls for minor page faults are an acceptable trade for large contiguous free memory. Set to 0 to prevent compaction from moving pages that are unevictable. Default value is 1. +On CONFIG_PREEMPT_RT the default value is 0.
This doesn't mention that the file is unwritable on -rt, and it doesn't explain *why* -rt has different behaviour.
kernel/sysctl.c static struct ctl_table vm_table[] = { · line 1490
Quoted 11 lines
kernel/sysctl.c +4
-0@@ -1483,7 +1483,11 @@ static struct ctl_table vm_table[] = { .procname = "compact_unevictable_allowed", .data = &sysctl_compact_unevictable_allowed, .maxlen = sizeof(int), +#ifdef CONFIG_PREEMPT_RT + .mode = 0444, +#else .mode = 0644, +#endif
This is non-backward-compatible and introduces a possibility that tested-on-non-rt userspace will fail on -rt kernels. It might be better to accept the writes, but to ignore them. Probably with a pr_warn_once() to let people know what we did.
But do we really need to take the option away from -rt users? Perhaps someone wants this feature and can accept the latency hit. How about switching the default and otherwise leaving the kernel behaviour as-is and simply emitting a warning letting -rt users know that they might not want to enable this?
Quoted 11 lines · Andrew Morton
Documentation/admin-guide/sysctl/vm.rst allowed to examine the unevictable lru (mlocked pages) for pages to compact. · line 131
Quoted 8 lines
index
64aeee1009cab..bbfa59d25eec3100644Documentation/admin-guide/sysctl/vm.rst +1
-0@@ -128,6 +128,7 @@ allowed to examine the unevictable lru (mlocked pages) for pages to compact. This should be used on systems where stalls for minor page faults are an acceptable trade for large contiguous free memory. Set to 0 to prevent compaction from moving pages that are unevictable. Default value is 1. +On CONFIG_PREEMPT_RT the default value is 0.This doesn't mention that the file is unwritable on -rt, and it doesn't explain *why* -rt has different behaviour.
I updated this bit.
Quoted 8 lines
Quoted 8 lines
kernel/sysctl.c +2
-0@@ -1483,7 +1483,11 @@ static struct ctl_table vm_table[] = { .procname = "compact_unevictable_allowed", .data = &sysctl_compact_unevictable_allowed, .maxlen =sizeof (int ), +#ifdef CONFIG_PREEMPT_RT + .mode = 0444,
Quoted 8 lines
kernel/sysctl.c static struct ctl_table vm_table[] = { · line 1490
Quoted 3 lines
kernel/sysctl.c +2
-0+#else .mode = 0644, +#endif This is non-backward-compatible and introduces a possibility that tested-on-non-rt userspace will fail on -rt kernels. It might be better to accept the writes, but to ignore them. Probably with a
pr_warn_once()to let people know what we did.
Hmm.
Quoted 5 lines
But do we really need to take the option away from -rt users? Perhaps someone wants this feature and can accept the latency hit. How about switching the default and otherwise leaving the kernel behaviour as-is and simply emitting a warning letting -rt users know that they might not want to enable this?
I don't think that RT people can live with the latency spike. The problem is that it is not deterministic in terms *when* it happens and *how*long* does it need to complete. Also it is not visible so you end up with additional 100us and you have no idea why. compaction is "okay" in the setup / configuration phase when the mlock() pages aren't around / the RT task is disabled. So it does not disturb the RT load.
Allowing the user to change the knob and spitting a warning is probably good. So we have a preferred default and the user is aware if it is changed with or without his knowledge.
Let me send a patch in a bit…
Sebastian
PATCH 1/2 =?UTF-8?q?mm/compaction:=20Really=20limit=20compact?= =?UTF-8?q?=5Funevictable=5Fallowed=20to=200=E2=80=A61?=
The proc file compact_unevictable_allowed' should allow 0 and 1 only, the extra*' attribues have been set properly but without proc_dointvec_minmax() as the `proc_handler' the limit will not be enforced.
Use proc_dointvec_minmax() as the `proc_handler' to enfoce the valid specified range.
--- kernel/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sysctl.c +1 -1
@@ -1484,7 +1484,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_compact_unevictable_allowed, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, },
Signature · 1 line
2.25.1
PATCH v3 2/2 mm/compaction: Disable compact_unevictable_allowed on RT
Since commit
5bbe3547aa3ba ("mm: allow compaction of unevictable pages")
it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make compact_unevictable_allowed = 0 default and issue a warning on RT if it is changed.
---
v2…v3: - Allow to modify the value but issue a warning if it is changed.
v1…v2: - Make the proc file RO instead removing it.
- Mention this change in Documentation/…/vm.rst.
Documentation/admin-guide/sysctl/vm.rst | 3 +++ kernel/sysctl.c | 27 ++++++++++++++++++++++++- mm/compaction.c | 4 ++++ 3 files changed, 33 insertions(+), 1 deletion(-)
Documentation/admin-guide/sysctl/vm.rst +3 -0
@@ -128,6 +128,9 @@ allowed to examine the unevictable lru (mlocked pages) for pages to compact. This should be used on systems where stalls for minor page faults are an acceptable trade for large contiguous free memory. Set to 0 to prevent compaction from moving pages that are unevictable. Default value is 1. +On CONFIG_PREEMPT_RT the default value is 0 in order to avoid a page fault, due +to compaction, which would block the task from becomming active until the fault +is resolved. dirty_background_bytes
kernel/sysctl.c +26 -1
@@ -212,6 +212,11 @@ static int proc_do_cad_pid(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos);static int proc_taint (struct ctl_table *table,int write,void __user *buffer,size_t *lenp,loff_t *ppos); +#ifdef CONFIG_COMPACTION +static int proc_dointvec_warn_RT_change (struct ctl_table *table,int write, +void __user *buffer,size_t *lenp, +loff_t *ppos); +#endif #endif #ifdef CONFIG_PRINTK
@@ -1484,7 +1489,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_compact_unevictable_allowed, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec_warn_RT_change, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, },
@@ -2572,6 +2577,26 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); } +#ifdef CONFIG_COMPACTION +static int proc_dointvec_warn_RT_change (struct ctl_table *table,int write, +void __user *buffer,size_t *lenp, +loff_t *ppos) +{ +int ret, old; + +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec (table, write, buffer, lenp, ppos); + + old = *(int *)table->data; + ret =proc_dointvec (table, write, buffer, lenp, ppos); +if (ret) +return ret; +WARN_ONCE (old != *(int *)table->data,"sysctl attribute %s changed." , + table->procname); +return ret; +} +#endif +/** * proc_douintvec - read a vector of unsigned integers * @table: the sysctl table
mm/compaction.c +4 -0
@@ -1590,7 +1590,11 @@ typedef enum {* Allow userspace to control policy on scanning the unevictable LRU for * compactable pages. */ +#ifdef CONFIG_PREEMPT_RT +int sysctl_compact_unevictable_allowed__read_mostly =0 ; +#else int sysctl_compact_unevictable_allowed__read_mostly =1 ; +#endif static inline void update_fast_start_pfn (struct compact_control *cc,unsigned long pfn)
Signature · 1 line
2.25.1
Andrew Morton
maintainerQuoted 9 lines · On Tue, 3 Mar 2020 21:22:25 +0100 Sebastian Andrzej Siewior…
Since commit
5bbe3547aa3ba("mm: allow compaction of unevictable pages")it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make
compact_unevictable_allowed= 0 default and issue a warning on RT if it is changed.
Fair enough, I guess.
Quoted 10 lines
kernel/sysctl.c +6
-0@@ -2572,6 +2577,26 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); } +#ifdef CONFIG_COMPACTION +static int proc_dointvec_warn_RT_change (struct ctl_table *table,int write, +void __user *buffer,size_t *lenp, +loff_t *ppos) +{ +int ret, old;
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2595
Quoted 10 lines
kernel/sysctl.c +10
-0+ +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec (table, write, buffer, lenp, ppos); + + old = *(int *)table->data; + ret =proc_dointvec (table, write, buffer, lenp, ppos); +if (ret) +return ret; +WARN_ONCE (old != *(int *)table->data,"sysctl attribute %s changed." , + table->procname);
The WARN will include a stack trace which just isn't interesting. A pr_warn() would be better?
Quoted 3 lines
kernel/sysctl.c +3
-0+ return ret; +} +#endif
Quoted 15 lines · Andrew Morton
Quoted 15 lines
kernel/sysctl.c +11
-0@@ -2572,6 +2577,26 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); } +#ifdef CONFIG_COMPACTION +static int proc_dointvec_warn_RT_change (struct ctl_table *table,int write, +void __user *buffer,size_t *lenp, +loff_t *ppos) +{ +int ret, old; + +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec (table, write, buffer, lenp, ppos); + + old = *(int *)table->data;
Quoted 8 lines
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2595
Quoted 5 lines
kernel/sysctl.c +5
-0+ ret =proc_dointvec (table, write, buffer, lenp, ppos); +if (ret) +return ret; +WARN_ONCE (old != *(int *)table->data,"sysctl attribute %s changed." , + table->procname);The WARN will include a stack trace which just isn't interesting. A
pr_warn()would be better?
Yeah, the only interesting part of full WARN would possibly be, which process changed it. That might be useful to print.
Quoted 4 lines
Quoted 3 lines
kernel/sysctl.c +3
-0+ return ret; +} +#endif
Quoted 8 lines · Vlastimil Babka
Quoted 5 lines
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2595
Quoted 2 lines
kernel/sysctl.c +2
-0+WARN_ONCE (old != *(int *)table->data,"sysctl attribute %s changed." , + table->procname);The WARN will include a stack trace which just isn't interesting. A
pr_warn()would be better?Yeah, the only interesting part of full WARN would possibly be, which process changed it. That might be useful to print.
Yes, the stack trace and register dump isn't interesting. But as Vlastimil says, the task and pid are informative. So if that is too much I could extract those two informations and include it in a pr_warn().
Sebastian
PATCH v4 2/2 mm/compaction: Disable compact_unevictable_allowed on RT
In reply to Andrew MortonSince commit
5bbe3547aa3ba ("mm: allow compaction of unevictable pages")
it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make compact_unevictable_allowed = 0 default and issue a warning on RT if it is changed.
---
v3…v4: - Replace WARN_ONCE() with pr_warn_once() and extend the message
by name of the task and its pid.
- Use proc_dointvec_minmax() in the !RT case.
- Added Mel's Ack as per [email protected].
v2…v3: - Allow to modify the value but issue a warning if it is changed.
v1…v2: - Make the proc file RO instead removing it.
- Mention this change in Documentation/…/vm.rst.
Documentation/admin-guide/sysctl/vm.rst | 3 +++ kernel/sysctl.c | 29 ++++++++++++++++++++++++- mm/compaction.c | 4 ++++ 3 files changed, 35 insertions(+), 1 deletion(-)
Documentation/admin-guide/sysctl/vm.rst +3 -0
@@ -128,6 +128,9 @@ allowed to examine the unevictable lru (mlocked pages) for pages to compact. This should be used on systems where stalls for minor page faults are an acceptable trade for large contiguous free memory. Set to 0 to prevent compaction from moving pages that are unevictable. Default value is 1. +On CONFIG_PREEMPT_RT the default value is 0 in order to avoid a page fault, due +to compaction, which would block the task from becomming active until the fault +is resolved. dirty_background_bytes
kernel/sysctl.c +28 -1
@@ -212,6 +212,11 @@ static int proc_do_cad_pid(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos);static int proc_taint (struct ctl_table *table,int write,void __user *buffer,size_t *lenp,loff_t *ppos); +#ifdef CONFIG_COMPACTION +static int proc_dointvec_minmax_warn_RT_change (struct ctl_table *table, +int write,void __user *buffer, +size_t *lenp,loff_t *ppos); +#endif #endif #ifdef CONFIG_PRINTK
@@ -1484,7 +1489,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_compact_unevictable_allowed, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax_warn_RT_change, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, },
@@ -2572,6 +2577,28 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); } +#ifdef CONFIG_COMPACTION +static int proc_dointvec_minmax_warn_RT_change (struct ctl_table *table, +int write,void __user *buffer, +size_t *lenp,loff_t *ppos) +{ +int ret, old; + +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec_minmax (table, write, buffer, lenp, ppos); + + old = *(int *)table->data; + ret =proc_dointvec_minmax (table, write, buffer, lenp, ppos); +if (ret) +return ret; +if (old != *(int *)table->data) +pr_warn_once ("sysctl attribute %s changed changed by %s[%d]\n" , + table->procname, current->comm, +task_pid_nr (current)); +return ret; +} +#endif +/** * proc_douintvec - read a vector of unsigned integers * @table: the sysctl table
mm/compaction.c +4 -0
@@ -1590,7 +1590,11 @@ typedef enum {* Allow userspace to control policy on scanning the unevictable LRU for * compactable pages. */ +#ifdef CONFIG_PREEMPT_RT +int sysctl_compact_unevictable_allowed__read_mostly =0 ; +#else int sysctl_compact_unevictable_allowed__read_mostly =1 ; +#endif static inline void update_fast_start_pfn (struct compact_control *cc,unsigned long pfn)
Signature · 1 line
2.26.0.rc2
Quoted 7 lines · Sebastian Andrzej Siewior
Since commit
5bbe3547aa3ba("mm: allow compaction of unevictable pages")it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Quoted 6 lines
Make
compact_unevictable_allowed= 0 default and issue a warning on RT if it is changed.
Nit below:
Quoted 10 lines
kernel/sysctl.c +6
-0@@ -2572,6 +2577,28 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); } +#ifdef CONFIG_COMPACTION +static int proc_dointvec_minmax_warn_RT_change (struct ctl_table *table, +int write,void __user *buffer, +size_t *lenp,loff_t *ppos) +{ +int ret, old;
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2595
Quoted 10 lines
kernel/sysctl.c +10
-0+ +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec_minmax (table, write, buffer, lenp, ppos); + + old = *(int *)table->data; + ret =proc_dointvec_minmax (table, write, buffer, lenp, ppos); +if (ret) +return ret; +if (old != *(int *)table->data) + pr_warn_once("sysctl attribute %s changed changed by %s[%d]\n",
^ "changed" twice
Quoted 9 lines
kernel/sysctl.c +6
-0+ table->procname, current->comm, + task_pid_nr(current)); + return ret; +} +#endif +/** * proc_douintvec - read a vector of unsigned integers * @table: the sysctl table
PATCH v5 2/2 mm/compaction: Disable compact_unevictable_allowed on RT
Since commit
5bbe3547aa3ba ("mm: allow compaction of unevictable pages")
it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make compact_unevictable_allowed = 0 default and issue a warning on RT if it is changed.
---
v4…v5: - Add Vlastimil's Acked-by
- s/changed changed/changed/
v3…v4: - Replace WARN_ONCE() with pr_warn_once() and extend the message
by name of the task and its pid.
- Use proc_dointvec_minmax() in the !RT case.
- Added Mel's Ack as per [email protected].
v2…v3: - Allow to modify the value but issue a warning if it is changed.
v1…v2: - Make the proc file RO instead removing it.
- Mention this change in Documentation/…/vm.rst.
Documentation/admin-guide/sysctl/vm.rst | 3 +++ kernel/sysctl.c | 29 ++++++++++++++++++++++++- mm/compaction.c | 4 ++++ 3 files changed, 35 insertions(+), 1 deletion(-)
Documentation/admin-guide/sysctl/vm.rst +3 -0
@@ -128,6 +128,9 @@ allowed to examine the unevictable lru (mlocked pages) for pages to compact. This should be used on systems where stalls for minor page faults are an acceptable trade for large contiguous free memory. Set to 0 to prevent compaction from moving pages that are unevictable. Default value is 1. +On CONFIG_PREEMPT_RT the default value is 0 in order to avoid a page fault, due +to compaction, which would block the task from becomming active until the fault +is resolved. dirty_background_bytes
kernel/sysctl.c +28 -1
@@ -212,6 +212,11 @@ static int proc_do_cad_pid(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos);static int proc_taint (struct ctl_table *table,int write,void __user *buffer,size_t *lenp,loff_t *ppos); +#ifdef CONFIG_COMPACTION +static int proc_dointvec_minmax_warn_RT_change (struct ctl_table *table, +int write,void __user *buffer, +size_t *lenp,loff_t *ppos); +#endif #endif #ifdef CONFIG_PRINTK
@@ -1484,7 +1489,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_compact_unevictable_allowed, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax_warn_RT_change, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, },
@@ -2572,6 +2577,28 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); } +#ifdef CONFIG_COMPACTION +static int proc_dointvec_minmax_warn_RT_change (struct ctl_table *table, +int write,void __user *buffer, +size_t *lenp,loff_t *ppos) +{ +int ret, old; + +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec_minmax (table, write, buffer, lenp, ppos); + + old = *(int *)table->data; + ret =proc_dointvec_minmax (table, write, buffer, lenp, ppos); +if (ret) +return ret; +if (old != *(int *)table->data) +pr_warn_once ("sysctl attribute %s changed by %s[%d]\n" , + table->procname, current->comm, +task_pid_nr (current)); +return ret; +} +#endif +/** * proc_douintvec - read a vector of unsigned integers * @table: the sysctl table
mm/compaction.c +4 -0
@@ -1590,7 +1590,11 @@ typedef enum {* Allow userspace to control policy on scanning the unevictable LRU for * compactable pages. */ +#ifdef CONFIG_PREEMPT_RT +int sysctl_compact_unevictable_allowed__read_mostly =0 ; +#else int sysctl_compact_unevictable_allowed__read_mostly =1 ; +#endif static inline void update_fast_start_pfn (struct compact_control *cc,unsigned long pfn)
Signature · 1 line
2.26.0.rc2
Quoted 65 lines · Sebastian Andrzej Siewior
Since commit
5bbe3547aa3ba("mm: allow compaction of unevictable pages")it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Make
compact_unevictable_allowed= 0 default and issue a warning on RT if it is changed.Signed-off-by Sebastian Andrzej Siewior <[email protected]>---
v2…v3: - Allow to modify the value but issue a warning if it is changed.v1…v2: - Make the proc file RO instead removing it.
- Mention this change in Documentation/…/vm.rst.Documentation/admin-guide/sysctl/vm.rst | 3 +++ kernel/sysctl.c | 27 ++++++++++++++++++++++++- mm/compaction.c | 4 ++++ 3 files changed, 33 insertions(+), 1 deletion(-)Documentation/admin-guide/sysctl/vm.rst +3
-0@@ -128,6 +128,9 @@ allowed to examine the unevictable lru (mlocked pages) for pages to compact. This should be used on systems where stalls for minor page faults are an acceptable trade for large contiguous free memory. Set to 0 to prevent compaction from moving pages that are unevictable. Default value is 1. +On CONFIG_PREEMPT_RT the default value is 0 in order to avoid a page fault, due +to compaction, which would block the task from becomming active until the fault +is resolved. dirty_background_byteskernel/sysctl.c +6
-1@@ -212,6 +212,11 @@ static int proc_do_cad_pid(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos);static int proc_taint (struct ctl_table *table,int write,void __user *buffer,size_t *lenp,loff_t *ppos); +#ifdef CONFIG_COMPACTION +static int proc_dointvec_warn_RT_change (struct ctl_table *table,int write, +void __user *buffer,size_t *lenp, +loff_t *ppos); +#endif #endif #ifdef CONFIG_PRINTK @@ -1484,7 +1489,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_compact_unevictable_allowed, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec_warn_RT_change, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, },@@ -2572,6 +2577,26 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); }
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2588
Quoted 10 lines
kernel/sysctl.c +9
-0+#ifdef CONFIG_COMPACTION +static int proc_dointvec_warn_RT_change (struct ctl_table *table,int write, +void __user *buffer,size_t *lenp, +loff_t *ppos) +{ +int ret, old; + +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec (table, write, buffer, lenp, ppos);
Shouldn't you use her proc_dointvec_minmax() per Patch 1/2 ?
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2591
Quoted 3 lines
kernel/sysctl.c +3
-0+ + old = *(int *)table->data; + ret =proc_dointvec (table, write, buffer, lenp, ppos);
And here.
Quoted 28 lines
kernel/sysctl.c +8
-0+if (ret) +return ret; +WARN_ONCE (old != *(int *)table->data,"sysctl attribute %s changed." , + table->procname); + return ret; +} +#endif +/** * proc_douintvec - read a vector of unsigned integers * @table: the sysctl table mm/compaction.c +4
-0@@ -1590,7 +1590,11 @@ typedef enum {* Allow userspace to control policy on scanning the unevictable LRU for * compactable pages. */ +#ifdef CONFIG_PREEMPT_RT +int sysctl_compact_unevictable_allowed__read_mostly =0 ; +#else int sysctl_compact_unevictable_allowed__read_mostly =1 ; +#endif static inline void update_fast_start_pfn (struct compact_control *cc,unsigned long pfn)
Quoted 16 lines · Vlastimil Babka
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2588
Quoted 13 lines
kernel/sysctl.c +9
-0@@ -2572,6 +2577,26 @@ int proc_dointvec(struct ctl_table *table, int write,return do_proc_dointvec (table, write, buffer, lenp, ppos,NULL ,NULL ); } +#ifdef CONFIG_COMPACTION +static int proc_dointvec_warn_RT_change (struct ctl_table *table,int write, +void __user *buffer,size_t *lenp, +loff_t *ppos) +{ +int ret, old; + +if (!IS_ENABLED (CONFIG_PREEMPT_RT ) || !write) +return proc_dointvec (table, write, buffer, lenp, ppos);Shouldn't you use her
proc_dointvec_minmax()per Patch 1/2 ?
Quoted 5 lines
kernel/sysctl.c int proc_dointvec(struct ctl_table *table, int write, · line 2591
Quoted 3 lines
kernel/sysctl.c +3
-0+ + old = *(int *)table->data; + ret =proc_dointvec (table, write, buffer, lenp, ppos);And here.
Yes, thank you for noticing. It didn't make from editor to disk after rebasing…
Sebastian
Quoted 7 lines · Sebastian Andrzej Siewior
Since commit
5bbe3547aa3ba("mm: allow compaction of unevictable pages")it is allowed to examine mlocked pages and compact them by default. On -RT even minor pagefaults are problematic because it may take a few 100us to resolve them and until then the task is blocked.
Quoted 5 lines
Make
compact_unevictable_allowed= 0 default and issue a warning on RT if it is changed.
(caveat: I do not spend very much some on RT-specific topics)
While I ack'd this, an RT application using THP is playing with fire, I know the RT extension for SLE explicitly disables it from being enabled at kernel config time. At minimum the critical regions should be mlocked followed by prctl to disable future THP faults that are non-deterministic, both from an allocation point of view, and a TLB access point of view. It's still reasonable to expect a smaller TLB reach for huge pages than base pages.
It's a similar hazard with NUMA balancing, an RT application should either disable balancing globally or set a memory policy that forces it to be ignored. They should be doing this anyway to avoid non-deterministic memory access costs due to NUMA artifacts but it wouldn't surprise me if some applications got it wrong. In that case, the SLE RT extension disables balancing by default and it probably should warn if it's enabled like this patch does.
It wouldn't surprise me to see patches like this in the future (completely untested, illustrative only).
init/Kconfig +1 -1
@@ -797,7 +797,7 @@ config NUMA_BALANCING config NUMA_BALANCING_DEFAULT_ENABLED bool "Automatically enable NUMA aware memory/task placement" default y - depends on NUMA_BALANCING + depends on NUMA_BALANCING && !PREEMPT_RT help If set, automatic NUMA balancing will be enabled if running on a NUMA machine.
mm/Kconfig +1 -1
@@ -385,7 +385,7 @@ config TRANSPARENT_HUGEPAGE choice prompt "Transparent Hugepage Support sysfs defaults" - depends on TRANSPARENT_HUGEPAGE + depends on TRANSPARENT_HUGEPAGE && !PREEMPT_RT default TRANSPARENT_HUGEPAGE_ALWAYS help Selects the sysfs defaults for Transparent Hugepage Support.
I would hope that a user of an RT kernel with an RT-aware application would be aware of this anyway but ..... uhhhh.
Point for Andrew is that I would not be too surprised if there were more RT-specific checks in the future that sanity checked some configuration options in response to RT-specific bugs that were down to insane configurations (be they kernel configs or sysctls)
Signature · 2 lines
Mel Gorman SUSE Labs
Re: [PATCH 1/2] mm/compaction: Really limit compact_unevictable_allowed to 0…1
In reply to Sebastian Andrzej SiewiorQuoted 9 lines · Sebastian Andrzej Siewior
The proc file
compact_unevictable_allowed' should allow 0 and 1 only, theextra*' attribues have been set properly but withoutproc_dointvec_minmax()as the `proc_handler' the limit will not be enforced.Use
proc_dointvec_minmax()as the `proc_handler' to enfoce the valid specified range.Signed-off-by Sebastian Andrzej Siewior <[email protected]>
Quoted 18 lines
--- kernel/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)kernel/sysctl.c +1
-1@@ -1484,7 +1484,7 @@ static struct ctl_table vm_table[] = { .data = &sysctl_compact_unevictable_allowed, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, },