3.2-rc1-rt2
Subsystems (7)
Dear RT Folks,
I'm pleased to announce the 3.2-rc1-rt2 release.
Changes vs. 3.2-rc1-rt2:
* Add missing softirq export (John Kacur)
* Fix rcu macro substitution (John Kacur)
* Fix device mapper BUG_ON (Reported by Luis Claudio)
* Fix x86 aesni (crypto) preemption problem (Peter Zijlstra, reported by Carsten Emde)
* Fix UP (tiny) RCU build issues (Reported by Tim Sanders)
3.2-rc1-rt2 is not against 3.2-rc1 - it's against the post rc1 commit 52e4c2a05256cb83cda12f3c2137ab1533344edb.
For non git users conveniance I uploaded a delta patch against 3.2-rc1:
https://tglx.de/~tglx/rt/3.2/base/patch-3.2-rc1-52e4c2a05.patch.gz
to get the base kernel on which the RT patch applies.
The incremental patch against 3.2-rc1-rt1 can be found here:
https://tglx.de/~tglx/rt/3.2/incr/patch-3.2-rc1-52e4c2a05-rt1-rt2.patch.gz
and is also appended below.
The RT patch against 3.2-rc1-52e4c2a05 can be found here:
https://tglx.de/~tglx/rt/3.2/patch-3.2-rc1-52e4c2a05-rt2.patch.gz
The split quilt queue is available at:
https://tglx.de/~tglx/rt/3.2/patches-3.2-rc1-52e4c2a05-rt2.tar.gz
I got several private (sigh) questions about the signature files which can be found beside the release files.
The signature file is a gpg detached signature signed with my signing key against the _uncompressed_ file.
In order to verify the signature, download both the release file and the signature file (which has ".sig" appended to the release file), e.g.:
wget https://tglx.de/~tglx/rt/3.2/incr/patch-3.2-rc1-52e4c2a05-rt1-rt2.patch.gz
wget https://tglx.de/~tglx/rt/3.2/incr/patch-3.2-rc1-52e4c2a05-rt1-rt2.patch.sign
Now decompress the release file:
gunzip patch-3.2-rc1-52e4c2a05-rt1-rt2.patch.gz
Make sure that you have my gpg key in your gpg keyring
gpg --recv-keys 06FF0B14
Now verify against the signature:
gpg --verify patch-3.2-rc1-52e4c2a05-rt1-rt2.patch.sign patch-3.2-rc1-52e4c2a05-rt1-rt2.patch.gz
That should give you something like
gpg: Signature made Tue 15 Nov 2011 12:47:24 AM CET using RSA key ID 0D7498A1
gpg: Good signature from "Thomas Gleixner <[email protected]>"
gpg: aka "Thomas Gleixner <[email protected]>"
gpg: aka "Thomas Gleixner <[email protected]>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
The last two lines are because you do not trust my key when you downloaded it, but that's your decision to make :)
Enjoy,
tglx
---
include/linux/rcutree.h +1 -1
@@ -60,7 +60,7 @@ static inline void exit_rcu(void)#ifndef CONFIG_PREEMPT_RT_FULL extern void synchronize_rcu_bh (void );#else -# define synchronize_rcu_bh () synchronize_rcu() +# define synchronize_rcu_bh synchronize_rcu#endif extern void synchronize_sched_expedited (void );extern void synchronize_rcu_expedited (void );
init/Kconfig +1 -1
@@ -410,7 +410,7 @@ config TINY_RCU config TINY_PREEMPT_RCU bool "Preemptible UP-only small-memory-footprint RCU" - depends on PREEMPT && !SMP && !PREEMPT_RT_FULL + depends on PREEMPT && !SMP help This option selects the RCU implementation that is designed for real-time UP systems. This option greatly reduces the
kernel/softirq.c +1 -0
@@ -447,6 +447,7 @@ int in_serving_softirq(void)preempt_enable ();return res; } +EXPORT_SYMBOL (in_serving_softirq);/* * Called with bh and local interrupts disabled. For full RT cpu must
localversion-rt +1 -1
@@ -1 +1 @@ --rt1 +-rt2
include/linux/sysctl.h +1 -0
@@ -932,6 +932,7 @@ enum#include <linux/list.h> #include <linux/rcupdate.h> #include <linux/wait.h> +#include <linux/atomic.h> /* For the /proc/sys support */ struct ctl_table ;
kernel/rcutiny.c +2 -0
@@ -243,6 +243,7 @@ void call_rcu_sched(struct rcu_head *hea }EXPORT_SYMBOL_GPL (call_rcu_sched); +#ifndef CONFIG_PREEMPT_RT_FULL /* * Post an RCU bottom-half callback to be invoked after any subsequent * quiescent state.
@@ -252,3 +253,4 @@ void call_rcu_bh(struct rcu_head *head, __call_rcu(head, func, &rcu_bh_ctrlblk); }EXPORT_SYMBOL_GPL (call_rcu_bh); +#endif
arch/x86/crypto/aesni-intel_glue.c +13 -11
@@ -289,14 +289,14 @@ static int ecb_encrypt(struct blkcipher_ err =blkcipher_walk_virt (desc, &walk); desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP ; -kernel_fpu_begin ();while ((nbytes = walk.nbytes)) { +kernel_fpu_begin ();aesni_ecb_enc (ctx, walk.dst.virt.addr, walk.src.virt.addr, - nbytes &AES_BLOCK_MASK ); + nbytes &AES_BLOCK_MASK ); +kernel_fpu_end (); nbytes &=AES_BLOCK_SIZE -1 ; err =blkcipher_walk_done (desc, &walk, nbytes); } -kernel_fpu_end ();return err; }
@@ -313,14 +313,14 @@ static int ecb_decrypt(struct blkcipher_ err =blkcipher_walk_virt (desc, &walk); desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP ; -kernel_fpu_begin ();while ((nbytes = walk.nbytes)) { +kernel_fpu_begin ();aesni_ecb_dec (ctx, walk.dst.virt.addr, walk.src.virt.addr, nbytes &AES_BLOCK_MASK ); +kernel_fpu_end (); nbytes &=AES_BLOCK_SIZE -1 ; err =blkcipher_walk_done (desc, &walk, nbytes); } -kernel_fpu_end ();return err; }
@@ -359,14 +359,14 @@ static int cbc_encrypt(struct blkcipher_ err =blkcipher_walk_virt (desc, &walk); desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP ; -kernel_fpu_begin ();while ((nbytes = walk.nbytes)) { +kernel_fpu_begin ();aesni_cbc_enc (ctx, walk.dst.virt.addr, walk.src.virt.addr, nbytes &AES_BLOCK_MASK , walk.iv); +kernel_fpu_end (); nbytes &=AES_BLOCK_SIZE -1 ; err =blkcipher_walk_done (desc, &walk, nbytes); } -kernel_fpu_end ();return err; }
@@ -383,14 +383,14 @@ static int cbc_decrypt(struct blkcipher_ err =blkcipher_walk_virt (desc, &walk); desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP ; -kernel_fpu_begin ();while ((nbytes = walk.nbytes)) { +kernel_fpu_begin ();aesni_cbc_dec (ctx, walk.dst.virt.addr, walk.src.virt.addr, nbytes &AES_BLOCK_MASK , walk.iv); +kernel_fpu_end (); nbytes &=AES_BLOCK_SIZE -1 ; err =blkcipher_walk_done (desc, &walk, nbytes); } -kernel_fpu_end ();return err; }
@@ -445,18 +445,20 @@ static int ctr_crypt(struct blkcipher_de err =blkcipher_walk_virt_block (desc, &walk,AES_BLOCK_SIZE ); desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP ; -kernel_fpu_begin ();while ((nbytes = walk.nbytes) >=AES_BLOCK_SIZE ) { +kernel_fpu_begin ();aesni_ctr_enc (ctx, walk.dst.virt.addr, walk.src.virt.addr, nbytes &AES_BLOCK_MASK , walk.iv); +kernel_fpu_end (); nbytes &=AES_BLOCK_SIZE -1 ; err =blkcipher_walk_done (desc, &walk, nbytes); }if (walk.nbytes) { +kernel_fpu_begin ();ctr_crypt_final (ctx, &walk); +kernel_fpu_end (); err =blkcipher_walk_done (desc, &walk,0 ); } -kernel_fpu_end ();return err; }
drivers/md/dm.c +2 -2
@@ -1648,14 +1648,14 @@ static void dm_request_fn(struct requestif (map_request (ti, clone, md)) goto requeued; -BUG_ON (!irqs_disabled ()); +BUG_ON_NORT (!irqs_disabled ());spin_lock (q->queue_lock); } goto out; requeued: -BUG_ON (!irqs_disabled ()); +BUG_ON_NORT (!irqs_disabled ());spin_lock (q->queue_lock); delay_and_out:
Quoted 8 lines · Thomas Gleixner
Dear RT Folks,
I'm pleased to announce the 3.2-rc1-rt2 release.
Changes vs. 3.2-rc1-rt2:
* Add missing softirq export (John Kacur)
Quoted 8 lines
* Fix rcu macro substitution (John Kacur)
* Fix device mapper
BUG_ON(Reported by Luis Claudio)* Fix x86 aesni (crypto) preemption problem (Peter Zijlstra, reported by Carsten Emde)
* Fix UP (tiny) RCU build issues (Reported by Tim Sanders)
Got below warning:
[ 8.459702] BUG: sleeping function called from invalid context at linux/kernel/rtmutex.c:645
[ 8.459705] in_atomic(): 1, irqs_disabled(): 0, pid: 1, name: swapper/0
[ 8.459707] 1 lock held by swapper/0/1:
[ 8.459708] #0: (&sig->cred_guard_mutex){+.+.+.}, at: [<ffffffff81154c45>] prepare_bprm_creds+0x35/0x80
[ 8.459717] Pid: 1, comm: swapper/0 Not tainted 3.2.0-rc1-rt2-11311-g3c4c0e7-dirty #10
[ 8.459718] Call Trace:
[ 8.459724] [<ffffffff81040c4e>] __might_sleep+0x12e/0x1e0
[ 8.459730] [<ffffffff815f4d74>] rt_spin_lock+0x24/0x60
[ 8.459735] [<ffffffff8114506e>] memcg_check_events+0x11e/0x230
[ 8.459739] [<ffffffff81146c5a>] T.1144+0x8a/0xf0
[ 8.459743] [<ffffffff81146d16>] __mem_cgroup_commit_charge_lrucare+0x56/0x180
[ 8.459747] [<ffffffff810430c9>] ? sub_preempt_count+0xa9/0xe0
[ 8.459751] [<ffffffff81147d08>] mem_cgroup_cache_charge+0xd8/0xe0
[ 8.459756] [<ffffffff81103a49>] add_to_page_cache_locked+0x49/0x100
[ 8.459760] [<ffffffff8110344f>] ? find_get_page+0xdf/0x1a0
[ 8.459764] [<ffffffff81103b22>] add_to_page_cache_lru+0x22/0x50
[ 8.459767] [<ffffffff81103ca5>] do_read_cache_page+0x75/0x1a0
[ 8.459774] [<ffffffff812695f0>] ? nfs_follow_link+0xc0/0xc0
[ 8.459777] [<ffffffff81103e1c>] read_cache_page_async+0x1c/0x20
[ 8.459781] [<ffffffff81103e2e>] read_cache_page+0xe/0x20
[ 8.459785] [<ffffffff81269589>] nfs_follow_link+0x59/0xc0
[ 8.459789] [<ffffffff8115de07>] path_openat+0x2a7/0x470
[ 8.459793] [<ffffffff8115e0e9>] do_filp_open+0x49/0xa0
[ 8.459798] [<ffffffff81155b22>] open_exec+0x32/0xf0
[ 8.459803] [<ffffffff811a3e0b>] load_elf_binary+0x85b/0x1d30
[ 8.459810] [<ffffffff81096d55>] ? __lock_acquire+0x4f5/0xbf0
[ 8.459816] [<ffffffff8100a819>] ? native_sched_clock+0x29/0x80
[ 8.459821] [<ffffffff8108429f>] ? local_clock+0x4f/0x60
[ 8.459824] [<ffffffff815f4658>] ? rt_spin_lock_slowunlock+0x78/0x80
[ 8.459828] [<ffffffff81091a39>] ? trace_hardirqs_off_caller+0x29/0x120
[ 8.459832] [<ffffffff8109119e>] ? put_lock_stats+0xe/0x40
[ 8.459836] [<ffffffff815f4658>] ? rt_spin_lock_slowunlock+0x78/0x80
[ 8.459840] [<ffffffff811a35b0>] ? elf_map+0x1d0/0x1d0
[ 8.459843] [<ffffffff810430c9>] ? sub_preempt_count+0xa9/0xe0
[ 8.459847] [<ffffffff811a35b0>] ? elf_map+0x1d0/0x1d0
[ 8.459850] [<ffffffff81154748>] search_binary_handler+0x1c8/0x4b0
[ 8.459854] [<ffffffff811545d7>] ? search_binary_handler+0x57/0x4b0
[ 8.459858] [<ffffffff81156876>] do_execve_common+0x276/0x330
[ 8.459862] [<ffffffff811569ba>] do_execve+0x3a/0x40
[ 8.459866] [<ffffffff8100bdca>] sys_execve+0x4a/0x80
[ 8.459871] [<ffffffff815f85e8>] kernel_execve+0x68/0xd0
[ 8.459877] [<ffffffff81000333>] ? run_init_process+0x23/0x30
[ 8.459881] [<ffffffff81000398>] init_post+0x58/0xd0
[ 8.459888] [<ffffffff81b5e6bd>] kernel_init+0x156/0x160
[ 8.459892] [<ffffffff815f8574>] kernel_thread_helper+0x4/0x10
[ 8.459896] [<ffffffff810423bc>] ? finish_task_switch+0x8c/0x110
[ 8.459900] [<ffffffff815f5bab>] ? _raw_spin_unlock_irq+0x3b/0x70
[ 8.459903] [<ffffffff815f5f61>] ? retint_restore_args+0xe/0xe
[ 8.459907] [<ffffffff81b5e567>] ? parse_early_options+0x20/0x20
[ 8.459911] [<ffffffff815f8570>] ? gs_change+0xb/0xbThanks,
Yong
Quoted 8 lines · Yong Zhang
Got below warning:
[ 8.459702] BUG: sleeping function called from invalid context at linux/kernel/rtmutex.c:645 [ 8.459705] in_atomic(): 1, irqs_disabled(): 0, pid: 1, name: swapper/0 [ 8.459707] 1 lock held by swapper/0/1: [ 8.459708] #0: (&sig->cred_guard_mutex){+.+.+.}, at: [<ffffffff81154c45>] prepare_bprm_creds+0x35/0x80 [ 8.459717] Pid: 1, comm: swapper/0 Not tainted 3.2.0-rc1-rt2-11311-g3c4c0e7-dirty #10 [ 8.459718] Call Trace:
I'm hitting the same issue. Here's the trace:
[ 0.915638] BUG: sleeping function called from invalid context at /home/luis.henriques/git-trees/linux-2.6/kernel/rtmutex.c:645
[ 0.915641] in_atomic(): 1, irqs_disabled(): 0, pid: 33, name: busybox
[ 0.915642] 1 lock held by busybox/33:
[ 0.915643] #0: (&mm->page_table_lock){+.+...}, at: [<ffffffff81119ec3>] unmap_vmas+0x333/0x6d0
[ 0.915664] Pid: 33, comm: busybox Not tainted 3.2.0-rc1-rt2+ #1
[ 0.915665] Call Trace:
[ 0.915674] [<ffffffff810497ba>] __might_sleep+0x12a/0x1e0
[ 0.915687] [<ffffffff81300f74>] rt_spin_lock+0x24/0x60
[ 0.915692] [<ffffffff8113efcd>] memcg_check_events.clone.33+0x14d/0x250
[ 0.915696] [<ffffffff8113f1bf>] __mem_cgroup_uncharge_common+0xef/0x270
[ 0.915698] [<ffffffff8114311f>] mem_cgroup_uncharge_page+0x2f/0x40
[ 0.915701] [<ffffffff81125410>] page_remove_rmap+0x70/0x90
[ 0.915703] [<ffffffff81119fbf>] unmap_vmas+0x42f/0x6d0
[ 0.915705] [<ffffffff811229d9>] exit_mmap+0xa9/0x120
[ 0.915710] [<ffffffff8104b9e0>] mmput+0x50/0x100
[ 0.915713] [<ffffffff81052c5b>] exit_mm+0x11b/0x140
[ 0.915718] [<ffffffff8109cb6d>] ? acct_collect+0x17d/0x1c0
[ 0.915720] [<ffffffff81053518>] do_exit+0x678/0x930
[ 0.915722] [<ffffffff8130224e>] ? retint_swapgs+0xe/0x13
[ 0.915724] [<ffffffff81053881>] do_group_exit+0x61/0xe0
[ 0.915726] [<ffffffff81053917>] sys_exit_group+0x17/0x20
[ 0.915728] [<ffffffff81302aeb>] system_call_fastpath+0x16/0x1bCheers,
--
Luis Henriques
PATCH 1/1 memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
In reply to Yong ZhangLooking at commit 4799401f [memcg: Fix race condition in memcg_check_events() with this_cpu usage], we just want to disable migration. So use the right API in -rt. This will cure below warning.
BUG: sleeping function called from invalid context at linux/kernel/rtmutex.c:645
in_atomic(): 1, irqs_disabled(): 0, pid: 1, name: swapper/0
1 lock held by swapper/0/1:
#0: (&sig->cred_guard_mutex){+.+.+.}, at: [<ffffffff81154c45>] prepare_bprm_creds+0x35/0x80
Pid: 1, comm: swapper/0 Not tainted 3.2.0-rc1-rt2-11311-g3c4c0e7-dirty #10
Call Trace: [<ffffffff81040c4e>] __might_sleep+0x12e/0x1e0 [<ffffffff815f4d74>] rt_spin_lock+0x24/0x60 [<ffffffff8114506e>] memcg_check_events+0x11e/0x230 [<ffffffff81146c5a>] T.1144+0x8a/0xf0 [<ffffffff81146d16>] __mem_cgroup_commit_charge_lrucare+0x56/0x180 [<ffffffff810430c9>] ? sub_preempt_count+0xa9/0xe0 [<ffffffff81147d08>] mem_cgroup_cache_charge+0xd8/0xe0 [<ffffffff81103a49>] add_to_page_cache_locked+0x49/0x100 [<ffffffff8110344f>] ? find_get_page+0xdf/0x1a0 [<ffffffff81103b22>] add_to_page_cache_lru+0x22/0x50 [<ffffffff81103ca5>] do_read_cache_page+0x75/0x1a0 [<ffffffff812695f0>] ? nfs_follow_link+0xc0/0xc0 [<ffffffff81103e1c>] read_cache_page_async+0x1c/0x20 [<ffffffff81103e2e>] read_cache_page+0xe/0x20 [<ffffffff81269589>] nfs_follow_link+0x59/0xc0 [<ffffffff8115de07>] path_openat+0x2a7/0x470 [<ffffffff8115e0e9>] do_filp_open+0x49/0xa0 [<ffffffff81155b22>] open_exec+0x32/0xf0 [<ffffffff811a3e0b>] load_elf_binary+0x85b/0x1d30 [<ffffffff81096d55>] ? __lock_acquire+0x4f5/0xbf0 [<ffffffff8100a819>] ? native_sched_clock+0x29/0x80 [<ffffffff8108429f>] ? local_clock+0x4f/0x60 [<ffffffff815f4658>] ? rt_spin_lock_slowunlock+0x78/0x80 [<ffffffff81091a39>] ? trace_hardirqs_off_caller+0x29/0x120 [<ffffffff8109119e>] ? put_lock_stats+0xe/0x40 [<ffffffff815f4658>] ? rt_spin_lock_slowunlock+0x78/0x80 [<ffffffff811a35b0>] ? elf_map+0x1d0/0x1d0 [<ffffffff810430c9>] ? sub_preempt_count+0xa9/0xe0 [<ffffffff811a35b0>] ? elf_map+0x1d0/0x1d0 [<ffffffff81154748>] search_binary_handler+0x1c8/0x4b0 [<ffffffff811545d7>] ? search_binary_handler+0x57/0x4b0 [<ffffffff81156876>] do_execve_common+0x276/0x330 [<ffffffff811569ba>] do_execve+0x3a/0x40 [<ffffffff8100bdca>] sys_execve+0x4a/0x80 [<ffffffff815f85e8>] kernel_execve+0x68/0xd0 [<ffffffff81000333>] ? run_init_process+0x23/0x30 [<ffffffff81000398>] init_post+0x58/0xd0 [<ffffffff81b5e6bd>] kernel_init+0x156/0x160 [<ffffffff815f8574>] kernel_thread_helper+0x4/0x10 [<ffffffff810423bc>] ? finish_task_switch+0x8c/0x110 [<ffffffff815f5bab>] ? _raw_spin_unlock_irq+0x3b/0x70 [<ffffffff815f5f61>] ? retint_restore_args+0xe/0xe [<ffffffff81b5e567>] ? parse_early_options+0x20/0x20 [<ffffffff815f8570>] ? gs_change+0xb/0xb
--- mm/memcontrol.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
mm/memcontrol.c +2 -2
@@ -722,7 +722,7 @@ static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target)*/ static void memcg_check_events (struct mem_cgroup *memcg,struct page *page) { -preempt_disable (); +migrate_disable ();/* threshold event is triggered in finer grain than soft limit */ if (unlikely (__memcg_event_check (memcg,MEM_CGROUP_TARGET_THRESH ))) {mem_cgroup_threshold (memcg);
@@ -742,7 +742,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) }#endif } -preempt_enable (); +migrate_enable (); }static struct mem_cgroup *mem_cgroup_from_cont (struct cgroup *cont)
Signature · 1 line
1.7.5.4
Steven Rostedt
reviewerRe: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Quoted 14 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.mm/memcontrol.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)mm/memcontrol.c +0
-0
mm/memcontrol.c static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target) · line 725
Quoted 5 lines
mm/memcontrol.c +1
-1@@ -722,7 +722,7 @@ static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target)*/ static void memcg_check_events (struct mem_cgroup *memcg,struct page *page) { -preempt_disable (); +migrate_disable ();
No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in __memcg_event_check() will be corrupted because nothing is protecting the updates from two tasks going into the same path.
Perhaps a local_lock would work.
-- Steve
Quoted 12 lines
mm/memcontrol.c +1
-1/* threshold event is triggered in finer grain than soft limit */ if (unlikely (__memcg_event_check (memcg,MEM_CGROUP_TARGET_THRESH ))) {mem_cgroup_threshold (memcg);@@ -742,7 +742,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) }#endif } -preempt_enable (); +migrate_enable (); }static struct mem_cgroup *mem_cgroup_from_cont (struct cgroup *cont)
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Quoted 11 lines · Steven Rostedt
Quoted 4 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in
__memcg_event_check()will be corrupted because nothing is protecting the updates from two tasks going into the same path.Perhaps a
local_lockwould work.
Yes, that's the only sensible option for now. Untested patch below.
Thanks,
tglx
-------------->
mm/memcontrol.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
mm/memcontrol.c +10 -6
@@ -49,6 +49,8 @@#include <linux/page_cgroup.h> #include <linux/cpu.h> #include <linux/oom.h> +#include <linux/locallock.h> +#include "internal.h" #include <asm/uaccess.h>
@@ -363,6 +365,8 @@ enum charge_type {#define MEM_CGROUP_RECLAIM_SOFT_BIT 0x2#define MEM_CGROUP_RECLAIM_SOFT (1 << MEM_CGROUP_RECLAIM_SOFT_BIT) +static DEFINE_LOCAL_IRQ_LOCK (stats_lock); +static void mem_cgroup_get (struct mem_cgroup *memcg);static void mem_cgroup_put (struct mem_cgroup *memcg);static struct mem_cgroup *parent_mem_cgroup (struct mem_cgroup *memcg);
@@ -619,7 +623,7 @@ static unsigned long mem_cgroup_read_evestatic void mem_cgroup_charge_statistics (struct mem_cgroup *memcg,bool file,int nr_pages) { -preempt_disable (); +local_lock (stats_lock);if (file) __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_CACHE],
@@ -638,7 +642,7 @@ static void mem_cgroup_charge_statistics__this_cpu_add (memcg->stat->events[MEM_CGROUP_EVENTS_COUNT ], nr_pages); -preempt_enable (); +local_unlock (stats_lock); }unsigned long
@@ -722,7 +726,7 @@ static void __mem_cgroup_target_update(s*/ static void memcg_check_events (struct mem_cgroup *memcg,struct page *page) { -preempt_disable (); +local_lock (stats_lock);/* threshold event is triggered in finer grain than soft limit */ if (unlikely (__memcg_event_check (memcg,MEM_CGROUP_TARGET_THRESH ))) {mem_cgroup_threshold (memcg);
@@ -742,7 +746,7 @@ static void memcg_check_events(struct me }#endif } -preempt_enable (); +local_unlock (stats_lock); }static struct mem_cgroup *mem_cgroup_from_cont (struct cgroup *cont)
@@ -2608,10 +2612,10 @@ static int mem_cgroup_move_account(strucif (PageCgroupFileMapped (pc)) {/* Update mapped_file data for mem_cgroup */ -preempt_disable (); +local_lock (stats_lock);__this_cpu_dec (from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED ]);__this_cpu_inc (to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED ]); -preempt_enable (); +local_unlock (stats_lock); }mem_cgroup_charge_statistics (from,PageCgroupCache (pc), -nr_pages);if (uncharge)
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Quoted 6 lines · Thomas Gleixner
Quoted 5 lines · Steven Rostedt
Quoted 4 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.
Quoted 8 lines
Quoted 6 lines
No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in
__memcg_event_check()will be corrupted because nothing is protecting the updates from two tasks going into the same path.Perhaps a
local_lockwould work.Yes, that's the only sensible option for now. Untested patch below.
I run a quick test and it looks like the problem is gone.
Cheers,
--
Luis Henriques
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Quoted 12 lines · On Wed, 16 Nov 2011 17:18:09 +0000 Luis Henriques <[email protected]> wrote:
Quoted 11 lines · Thomas Gleixner
Quoted 10 lines · Steven Rostedt
Quoted 4 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in
__memcg_event_check()will be corrupted because nothing is protecting the updates from two tasks going into the same path.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Perhaps a
local_lockwould work.Yes, that's the only sensible option for now. Untested patch below.
I run a quick test and it looks like the problem is gone.
Cheers,
Could you CC the final patch to [email protected] ? Does this fix will go thorugh rt tree rather than -mm ?
Thanks,
-Kame
Steven Rostedt
reviewerRe: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Quoted 6 lines · KAMEZAWA Hiroyuki
Quoted 3 lines
I run a quick test and it looks like the problem is gone.
Cheers,
Could you CC the final patch to [email protected] ? Does this fix will go thorugh rt tree rather than -mm ?
This particular fix only goes through the rt tree because it is only a bug when full rt is enabled. When rt is enabled, spin_locks become mutexes, and thus can not be used when preemption is disabled. The rt tree introduced a local_lock() to remove open coded preempt disabling and also to help annotate places that need per cpu protections.
-- Steve
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
In reply to Thomas GleixnerQuoted 6 lines · Thomas Gleixner
Quoted 5 lines · Steven Rostedt
Quoted 4 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.
Quoted 8 lines
Quoted 6 lines
No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in
__memcg_event_check()will be corrupted because nothing is protecting the updates from two tasks going into the same path.Perhaps a
local_lockwould work.Yes, that's the only sensible option for now. Untested patch below.
Works for me.
Thanks,
Yong
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Quoted 12 lines · Yong Zhang
Quoted 11 lines · Thomas Gleixner
Quoted 10 lines · Steven Rostedt
Quoted 4 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in
__memcg_event_check()will be corrupted because nothing is protecting the updates from two tasks going into the same path.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Perhaps a
local_lockwould work.Yes, that's the only sensible option for now. Untested patch below.
Works for me.
Johannes came up with a different solution. Could you please give it a try?
Thanks,
tglx
------------->
Subject: [patch] mm: memcg: shorten preempt-disabled section around event checks
Only the ratelimit checks themselves have to run with preemption disabled, the resulting actions - checking for usage thresholds, updating the soft limit tree - can and should run with preemption enabled.
--- mm/memcontrol.c | 73 ++++++++++++++++++++++++++---------------------------- 1 files changed, 35 insertions(+), 38 deletions(-)
Thomas, HTH and it is probably interesting for upstream as well. Unfortunately, I'm in the middle of moving right now, so this is untested except for compiling.
mm/memcontrol.c +35 -38
@@ -683,37 +683,32 @@ static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,return total; } -static bool __memcg_event_check (struct mem_cgroup *memcg,int target) +static bool mem_cgroup_event_ratelimit (struct mem_cgroup *memcg, +enum mem_cgroup_events_target target) {unsigned long val, next; val =__this_cpu_read (memcg->stat->events[MEM_CGROUP_EVENTS_COUNT ]); next =__this_cpu_read (memcg->stat->targets[target]);/* from time_after() in jiffies.h */ -return ((long )next - (long )val <0 ); -} - -static void __mem_cgroup_target_update (struct mem_cgroup *memcg,int target) -{ -unsigned long val, next; - - val =__this_cpu_read (memcg->stat->events[MEM_CGROUP_EVENTS_COUNT ]); - -switch (target) { -case MEM_CGROUP_TARGET_THRESH : - next = val +THRESHOLDS_EVENTS_TARGET ; -break ; -case MEM_CGROUP_TARGET_SOFTLIMIT : - next = val +SOFTLIMIT_EVENTS_TARGET ; -break ; -case MEM_CGROUP_TARGET_NUMAINFO : - next = val +NUMAINFO_EVENTS_TARGET ; -break ; -default : -return ; +if ((long )next - (long )val <0 ) { +switch (target) { +case MEM_CGROUP_TARGET_THRESH : + next = val +THRESHOLDS_EVENTS_TARGET ; +break ; +case MEM_CGROUP_TARGET_SOFTLIMIT : + next = val +SOFTLIMIT_EVENTS_TARGET ; +break ; +case MEM_CGROUP_TARGET_NUMAINFO : + next = val +NUMAINFO_EVENTS_TARGET ; +break ; +default : +break ; + } +__this_cpu_write (memcg->stat->targets[target], next); +return true; } - -__this_cpu_write (memcg->stat->targets[target], next); +return false; }/*
@@ -724,25 +719,27 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) {preempt_disable ();/* threshold event is triggered in finer grain than soft limit */ -if (unlikely (__memcg_event_check (memcg,MEM_CGROUP_TARGET_THRESH ))) { +if (unlikely (mem_cgroup_event_ratelimit (memcg, +MEM_CGROUP_TARGET_THRESH ))) { +bool do_softlimit, do_numainfo; + + do_softlimit =mem_cgroup_event_ratelimit (memcg, +MEM_CGROUP_TARGET_SOFTLIMIT ); +#if MAX_NUMNODES >1 + do_numainfo =mem_cgroup_event_ratelimit (memcg, +MEM_CGROUP_TARGET_NUMAINFO ); +#endif +preempt_enable (); +mem_cgroup_threshold (memcg); -__mem_cgroup_target_update (memcg,MEM_CGROUP_TARGET_THRESH ); -if (unlikely (__memcg_event_check (memcg, -MEM_CGROUP_TARGET_SOFTLIMIT ))) { +if (unlikely (do_softlimit))mem_cgroup_update_tree (memcg, page); -__mem_cgroup_target_update (memcg, -MEM_CGROUP_TARGET_SOFTLIMIT ); - }#if MAX_NUMNODES >1 -if (unlikely (__memcg_event_check (memcg, -MEM_CGROUP_TARGET_NUMAINFO ))) { +if (unlikely (do_numainfo))atomic_inc (&memcg->numainfo_events); -__mem_cgroup_target_update (memcg, -MEM_CGROUP_TARGET_NUMAINFO ); - }#endif - } -preempt_enable (); + }else +preempt_enable (); }static struct mem_cgroup *mem_cgroup_from_cont (struct cgroup *cont)
Signature · 1 line
1.7.6.4
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Quoted 1 line · Thomas Gleixner
Johannes came up with a different solution. Could you please give it a try?
Again, I've run a quick test and it looks like this solves the issue.
Cheers,
--
Luis Henriques
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
Luis,
Quoted 4 lines · Luis Henriques
Quoted 1 line · Thomas Gleixner
Johannes came up with a different solution. Could you please give it a try?
Again, I've run a quick test and it looks like this solves the issue.
thanks for testing. That solution is way better than the local_lock based one.
Thanks,
tglx
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
In reply to Thomas GleixnerQuoted 14 lines · Thomas Gleixner
Quoted 12 lines · Yong Zhang
Quoted 11 lines · Thomas Gleixner
Quoted 10 lines · Steven Rostedt
Quoted 4 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in
__memcg_event_check()will be corrupted because nothing is protecting the updates from two tasks going into the same path.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Perhaps a
local_lockwould work.Yes, that's the only sensible option for now. Untested patch below.
Works for me.
Johannes came up with a different solution. Could you please give it a try?
Works too :)
Thanks,
Yong
Quoted 133 lines
Thanks,
tglx
------------->
Subject: [patch] mm: memcg: shorten preempt-disabled section around event checksOnly the ratelimit checks themselves have to run with preemption disabled, the resulting actions - checking for usage thresholds, updating the soft limit tree - can and should run with preemption enabled.
Signed-off-by Johannes Weiner <[email protected]>--- mm/memcontrol.c | 73 ++++++++++++++++++++++++++---------------------------- 1 files changed, 35 insertions(+), 38 deletions(-)Thomas, HTH and it is probably interesting for upstream as well. Unfortunately, I'm in the middle of moving right now, so this is untested except for compiling.
mm/memcontrol.c +35
-38@@ -683,37 +683,32 @@ static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,return total; } -static bool __memcg_event_check (struct mem_cgroup *memcg,int target) +static bool mem_cgroup_event_ratelimit (struct mem_cgroup *memcg, +enum mem_cgroup_events_target target) {unsigned long val, next; val =__this_cpu_read (memcg->stat->events[MEM_CGROUP_EVENTS_COUNT ]); next =__this_cpu_read (memcg->stat->targets[target]);/* from time_after() in jiffies.h */ -return ((long )next - (long )val <0 ); -} - -static void __mem_cgroup_target_update (struct mem_cgroup *memcg,int target) -{ -unsigned long val, next; - - val =__this_cpu_read (memcg->stat->events[MEM_CGROUP_EVENTS_COUNT ]); - -switch (target) { -case MEM_CGROUP_TARGET_THRESH : - next = val +THRESHOLDS_EVENTS_TARGET ; -break ; -case MEM_CGROUP_TARGET_SOFTLIMIT : - next = val +SOFTLIMIT_EVENTS_TARGET ; -break ; -case MEM_CGROUP_TARGET_NUMAINFO : - next = val +NUMAINFO_EVENTS_TARGET ; -break ; -default : -return ; +if ((long )next - (long )val <0 ) { +switch (target) { +case MEM_CGROUP_TARGET_THRESH : + next = val +THRESHOLDS_EVENTS_TARGET ; +break ; +case MEM_CGROUP_TARGET_SOFTLIMIT : + next = val +SOFTLIMIT_EVENTS_TARGET ; +break ; +case MEM_CGROUP_TARGET_NUMAINFO : + next = val +NUMAINFO_EVENTS_TARGET ; +break ; +default : +break ; + } +__this_cpu_write (memcg->stat->targets[target], next); +return true; } - -__this_cpu_write (memcg->stat->targets[target], next); +return false; }/* @@ -724,25 +719,27 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) {preempt_disable ();/* threshold event is triggered in finer grain than soft limit */ -if (unlikely (__memcg_event_check (memcg,MEM_CGROUP_TARGET_THRESH ))) { +if (unlikely (mem_cgroup_event_ratelimit (memcg, +MEM_CGROUP_TARGET_THRESH ))) { +bool do_softlimit, do_numainfo; + + do_softlimit =mem_cgroup_event_ratelimit (memcg, +MEM_CGROUP_TARGET_SOFTLIMIT ); +#if MAX_NUMNODES >1 + do_numainfo =mem_cgroup_event_ratelimit (memcg, +MEM_CGROUP_TARGET_NUMAINFO ); +#endif +preempt_enable (); +mem_cgroup_threshold (memcg); -__mem_cgroup_target_update (memcg,MEM_CGROUP_TARGET_THRESH ); -if (unlikely (__memcg_event_check (memcg, -MEM_CGROUP_TARGET_SOFTLIMIT ))) { +if (unlikely (do_softlimit))mem_cgroup_update_tree (memcg, page); -__mem_cgroup_target_update (memcg, -MEM_CGROUP_TARGET_SOFTLIMIT ); - }#if MAX_NUMNODES >1 -if (unlikely (__memcg_event_check (memcg, -MEM_CGROUP_TARGET_NUMAINFO ))) { +if (unlikely (do_numainfo))atomic_inc (&memcg->numainfo_events); -__mem_cgroup_target_update (memcg, -MEM_CGROUP_TARGET_NUMAINFO ); - }#endif - } -preempt_enable (); + }else +preempt_enable (); }static struct mem_cgroup *mem_cgroup_from_cont (struct cgroup *cont)Signature · 7 lines
1.7.6.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Signature · 1 line
Only stand for myself
Re: [PATCH -rt] memcg: use migrate_disable()/migrate_enable( ) in memcg_check_events()
In reply to Steven RostedtQuoted 10 lines · Steven Rostedt
Quoted 9 lines · Yong Zhang
Looking at commit
4799401f[memcg: Fix race condition inmemcg_check_events()withthis_cpuusage], we just want to disable migration. So use the right API in -rt. This will cure below warning.mm/memcontrol.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
Quoted 15 lines
mm/memcontrol.c static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target) · line 725
Quoted 10 lines
mm/memcontrol.c +1
-1@@ -722,7 +722,7 @@ static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target)*/ static void memcg_check_events (struct mem_cgroup *memcg,struct page *page) { -preempt_disable (); +migrate_disable ();No this won't work. Not even for -rt. If we disable migration but not preemption, then two tasks can take this path. And the checks in
__memcg_event_check()will be corrupted because nothing is protecting the updates from two tasks going into the same path.
I assumed that we only care about migration, but obviously I'm wrong.
Quoted 2 lines
Perhaps a
local_lockwould work.
Yeah, will try tglx's patch later.
Thanks,
Yong