Skip to contentSkip to conversation

mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

PATCH In review Philby John 2 participants 5 messages Jun 14, 2010 – Jun 15, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume, on the NOR flash, the kernel thread ubi_bgt1d calls cfi_amdstd_write_buffers() --> do_write_buffer() --> INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls smp_processor_id() in preemptible code, which you are not supposed to. Fix the problem by disabling preemption.

The kernel error messages seen when trying to create UBI volume is

BUG: using smp_processor_id() in preemptible [00000000] code: ubi_bgt1d/843
caller is __udelay+0x14/0x70
Call Trace:
[<ffffffff8110b0d4>] dump_stack+0x8/0x34
[<ffffffff812ee1ac>] debug_smp_processor_id+0x114/0x130
[<ffffffff812e9274>] __udelay+0x14/0x70
[<ffffffff81337c0c>] cfi_amdstd_write_buffers+0xa9c/0xd70
[<ffffffff8134cab0>] ubi_io_sync_erase+0x248/0x390
[<ffffffff8134d714>] erase_worker+0x6c/0x4f8
[<ffffffff8134e4fc>] do_work+0xac/0x138
[<ffffffff8134e6a0>] ubi_thread+0x118/0x1a8
[<ffffffff8115ebe0>] kthread+0x88/0x90
[<ffffffff81115650>] kernel_thread_helper+0x10/0x18
---
 include/linux/mtd/cfi.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/linux/mtd/cfi.h +2 -0
index 574d9ee..9673213 100644
@@ -495,7 +495,9 @@ static inline void cfi_udelay(int us)
 	if (us >= 1000) {
 		msleep((us+999)/1000);
 	} else {
+		preempt_disable();
 		udelay(us);
+		preempt_enable();
 		cond_resched();
 	}
 }
Signature · 1 line
1.6.3.3.333.g4d53f
#1 lore raw
Quoted 8 lines · Philby John

mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume, on the NOR flash, the kernel thread ubi_bgt1d calls cfi_amdstd_write_buffers() --> do_write_buffer() --> INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls smp_processor_id() in preemptible code, which you are not supposed to. Fix the problem by disabling preemption.

The MTD code just calls udelay().
Are you sure it isn't permitted to call udelay() from preemptible code? I think it is fine.

Perhaps MIPS udelay() should be disabling preemption itself, or (as x86 does) using raw_smp_processor_id() instead? Or perhaps the x86 version is a bug because the current CPU might change during the delay loop?

See git commit 5c1ea08215f1f830dfaf4819a5f22efca41c3832 "x86: enable preemption in delay"

I don't think it makes sense to disable preemption in all udelay() calls in drivers, so my NAK to this MTD patch. To workaround, consider putting the preempt_disable in MIPS udelay(), or using raw_smp_processor_id() in it, after reading the above git commit's message. A proper fix would accept a context switch during the delay and rescale the remaining count, but even on x86 they haven't done that yet :-)

Regards,
-- Jamie

#2 lore raw
Quoted 10 lines · Jamie Lokier
Quoted 8 lines · Philby John

mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume, on the NOR flash, the kernel thread ubi_bgt1d calls cfi_amdstd_write_buffers() --> do_write_buffer() --> INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls smp_processor_id() in preemptible code, which you are not supposed to. Fix the problem by disabling preemption.

Quoted 3 lines

The MTD code just calls udelay().
Are you sure it isn't permitted to call udelay() from preemptible code? I think it is fine.

The mips code uses __udelay() where the macro current_cpu_data returns the actual data structure on a per CPU basis by calling smp_processor_id(). Since I have enabled CONFIG_DEBUG_PREEMPT, this would call debug_smp_processor_id(). This function would check

a)if the thread is preemptiable. If preemption is disabled, normal flow. b)If irqs are disabled, if yes normal flow.
c)if the thread is bound to a single cpu, if yes normal flow d)or if its an early bootup

None of these condition get satisfied and hence the kernel error messages are seen. So I think yes for MIPS, udelay() shouldn't be called in preemptiable code.

Quoted 2 lines

Perhaps MIPS udelay() should be disabling preemption itself,

I will need to investigate this. Will follow up soon.

Quoted 2 lines

or
(as x86 does) using raw_smp_processor_id() instead?

I have enabled CONFIG_DEBUG_PREEMPT so this would call debug_smp_processor_id() instead of raw_smp_processor_id().

Quoted 3 lines

Or perhaps the x86
version is a bug because the current CPU might change during the delay loop?

Yes, isn't this a possibility? In that case shouldn't we be using spin_lock_irqsave() ?

Quoted 6 lines

See git commit 5c1ea08215f1f830dfaf4819a5f22efca41c3832 "x86: enable preemption in delay"

I don't think it makes sense to disable preemption in all udelay() calls in drivers, so my NAK to this MTD patch. To workaround, consider putting the preempt_disable in MIPS udelay(),

This would definitely work.

Quoted 3 lines

or using
raw_smp_processor_id() in it, after reading the above git commit's message.

Will look into this.

Thanks
Philby

#3 lore raw
In reply to Jamie Lokier
Quoted 10 lines · Jamie Lokier
Quoted 8 lines · Philby John

mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume, on the NOR flash, the kernel thread ubi_bgt1d calls cfi_amdstd_write_buffers() --> do_write_buffer() --> INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls smp_processor_id() in preemptible code, which you are not supposed to. Fix the problem by disabling preemption.

Quoted 3 lines

The MTD code just calls udelay().
Are you sure it isn't permitted to call udelay() from preemptible code? I think it is fine.

It isn't really udelay() but smp_processor_id() that you are not to call from a preemptible thread. Now I also see Ed Swierk has done a similar thing https://patchwork.kernel.org/patch/4049/ and he comments "..which calls smp_processor_id(), which is not supposed to be called from a preemptible thread."

So perhaps I can use preempt_disable() around just this call in function __udelay()?

Regards,
Philby

#4 lore raw
In reply to Jamie Lokier

Hello Jamie,

Quoted 10 lines · Jamie Lokier
Quoted 8 lines · Philby John

mtd: Fix bug using smp_processor_id() in preemptible ubi_bgt1d kthread

On a MIPS Cavium Octeon CN5020 when trying to create a UBI volume, on the NOR flash, the kernel thread ubi_bgt1d calls cfi_amdstd_write_buffers() --> do_write_buffer() --> INVALIDATE_CACHE_UDELAY --> __udelay(). Its __udelay() that calls smp_processor_id() in preemptible code, which you are not supposed to. Fix the problem by disabling preemption.

Quoted 6 lines

The MTD code just calls udelay().
Are you sure it isn't permitted to call udelay() from preemptible code? I think it is fine.

Perhaps MIPS udelay() should be disabling preemption itself, or (as x86 does) using raw_smp_processor_id() instead?

Sorry for the noise. I now find that raw_smp_processor_id() has been implemented specific to MIPS in the latest kernel, I was using 2.6.32.

Thanks and regards,
Philby