Skip to contentSkip to conversation

2.4 preemption bug in bh_kmap_irq

PATCH In review Joe Korty 4 participants 5 messages Apr 14, 2003 – Jun 19, 2003

lore
Share & tools
lore

Joe Korty

author
#0 lore raw

PATCH 1/1 2.4 preemption bug in bh_kmap_irq

[I submitted this bug to Alan some time ago, he agreed it was
a problem but felt that it should be fixed in the 2.4 preemption patch.]

Hi Robert, Everyone,

The bh_kmap_irq/bh_kunmap_irq functions are broken in 2.4.21-pre5. However no symptoms occur unless the preemption patch is applied.

The bug is that bh_map_irq *conditionally* calls kmap_atomic (which disables preemption as one of its functions), while bh_unmap_irq *unconditionally* calls kunmap_atomic (which enables it). This imbalance results in a occasional off-by-one preempt_count, which in turn causes IDE PIO mode interrupt code (specifically, read_intr) to erronously invoke preempt_schedule while at interrupt level.

The below patch compiles and boots ide=nodma on my preempt 2.4 kernel on the one motherboard that had the problem. Before this patch, the kernel would not even boot for that motherboard. I also applied and test booted a pure 2.4.21-pre5 kernel with this patch.

The patch implements my preference for simplicity, so you may want to take some other approach if maximal performance is what you want.

Joe

linux/highmem.h renamed from linux/highmem.h.orig +3 -15
@@ -33,22 +33,10 @@
 {
 	unsigned long addr;
 
-	__save_flags(*flags);
-
-	/*
-	 * could be low
-	 */
-	if (!PageHighMem(bh->b_page))
-		return bh->b_data;
-
-	/*
-	 * it's a highmem page
-	 */
-	__cli();
+	local_irq_save(*flags);
 	addr = (unsigned long) kmap_atomic(bh->b_page, KM_BH_IRQ);
 
-	if (addr & ~PAGE_MASK)
-		BUG();
+	BUG_ON (addr & ~PAGE_MASK);
 
 	return (char *) addr + bh_offset(bh);
 }
@@ -58,7 +46,7 @@
 	unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
 
 	kunmap_atomic((void *) ptr, KM_BH_IRQ);
-	__restore_flags(*flags);
+	local_irq_restore(*flags);
 }
 
 #else /* CONFIG_HIGHMEM */
Quoted 1 line

From [email protected] Wed Mar 12 22:19:43 2003

Return-Path: <[email protected]>
Received: from exchange.ccur.com by rudolph.ccur.com (8.6.10/CCC-4.1)

	id WAA17543; Wed, 12 Mar 2003 22:19:43 GMT
Received: by exchange.ccur.com with Internet Mail Service (5.5.2653.19)
	id <1J8VJBZT>; Wed, 12 Mar 2003 17:19:43 -0500
Received: from irongate.swansea.linux.org.uk (pc2-cwma1-4-cust86.swan.cable.ntl.com [213.105.254.86]) by exchange.ccur.com with SMTP (Microsoft Exchange Internet Mail Service Version 5.5.2653.13)
	id 1J8VJBZS; Wed, 12 Mar 2003 17:19:38 -0500
Received: from irongate.swansea.linux.org.uk (localhost [127.0.0.1])
	by irongate.swansea.linux.org.uk (8.12.7/8.12.7) with ESMTP id h2CNRVYf024118;
	Wed, 12 Mar 2003 23:27:32 GMT
Received: (from alan@localhost)
	by irongate.swansea.linux.org.uk (8.12.7/8.12.7/Submit) id h2CNRTqm024116;
	Wed, 12 Mar 2003 23:27:29 GMT

X-Authentication-Warning: irongate.swansea.linux.org.uk: alan set sender to [email protected] using -f
Subject: Re: [PATCH] bug in 2.4 bh_kmap_irq() breaks IDE under preempt patch
From: Alan Cox <[email protected]>
To: Joe Korty <[email protected]>
Cc: Linux Kernel Mailing List <[email protected]>
In-Reply-To: <[email protected]>
References: <[email protected]>
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Message-Id: <[email protected]>
Mime-Version: 1.0
X-Mailer: Ximian Evolution 1.2.1 (1.2.1-4)
Date: 12 Mar 2003 23:27:28 +0000
Status: RO
Content-Length: 406
Lines: 9

Quoted 3 lines · Joe Korty

The bug is that bh_map_irq *conditionally* calls kmap_atomic (which disables preemption as one of its functions), while bh_unmap_irq *unconditionally* calls kunmap_atomic (which enables it). This

Thats a pre-empt bug ont a bh_map_irq bug. I'm glad you've found it however. It explains a few things and will be useful for people wanting pre-empt 2.4 .

#1 lore raw

On Monday 14 April 2003 19:27, Joe Korty wrote:

Hi Joe,

Quoted 6 lines

The below patch compiles and boots ide=nodma on my preempt 2.4 kernel on the one motherboard that had the problem. Before this patch, the kernel would not even boot for that motherboard. I also applied and test booted a pure 2.4.21-pre5 kernel with this patch.
The patch implements my preference for simplicity, so you may want to take some other approach if maximal performance is what you want.

yep, and here is the problem ^^^^^^^^. Your patch seems ok but is horribly slow. I've tried it first the day you submitted the patch. It's even alot slower than w/o Preempt or CONFIG_PREEMPT to no.

My Celeron 1,3GHz with 512 MB RAM felt like good old 486SX/25 while doing, for example, a kernel compilation :(

ciao, Marc

author
#2 lore raw
Quoted 10 lines · Marc-Christian Petersen

On Monday 14 April 2003 19:27, Joe Korty wrote:

Hi Joe,

Quoted 6 lines

The below patch compiles and boots ide=nodma on my preempt 2.4 kernel on the one motherboard that had the problem. Before this patch, the kernel would not even boot for that motherboard. I also applied and test booted a pure 2.4.21-pre5 kernel with this patch.
The patch implements my preference for simplicity, so you may want to take some other approach if maximal performance is what you want.

Quoted 8 lines

yep, and here is the problem ^^^^^^^^. Your patch seems ok but is horribly slow. I've tried it first the day you submitted the patch. It's even alot slower than w/o Preempt or CONFIG_PREEMPT to no.

My Celeron 1,3GHz with 512 MB RAM felt like good old 486SX/25 while doing, for example, a kernel compilation :(

ciao, Marc

Hi Marc,
I've been re-reviewing the code and I can't see any problem. There are two cases: kernels compiled with CONFIG_HIGHMEM and those without.

For the CONFIG_HIGHMEM case, the call in bh_kmap_irq to kmap_atomic actually calls a real routine called kmap_atomic. This has a version of the 'if' statement equivalent to the one I removed from bh_kmap_irq, right near the front:

    static inline void *kmap_atomic(...
    {
        ....
        preempt_disable();
        if (page < highmem_start_page)
                return page_address(page);

For the case where CONFIG_HIGHMEM is not set, the bh_kmap_irq call to kmap_atomic is really (through the magic of #defines) a call to page_address, which expands out to a near-NOP:

	#define page_address(page) ((page)->virtual)

So in one case I have the overhead of an extra procedure call/return, in the other the overhead of an extra pointer dereference. Neither of these should be causing the performance impact you are seeing.

There is always the possibility of a case that I missed, but right now I don't see it.

Regards,
Joe

#3 lore raw
In reply to Joe Korty
Quoted 6 lines · Joe Korty

The bug is that bh_map_irq *conditionally* calls kmap_atomic (which disables preemption as one of its functions), while bh_unmap_irq *unconditionally* calls kunmap_atomic (which enables it). This imbalance results in a occasional off-by-one preempt_count, which in turn causes IDE PIO mode interrupt code (specifically, read_intr) to erronously invoke preempt_schedule while at interrupt level.

Thanks for this (and sorry for the very delayed reply).

I am going to put this in the 2.4.21 preempt-kernel patch, because actually someone else here at MontaVista fixed the problem in the same exact way a loooong time ago and it seems to work.

I agree it is suboptimal and I will be happy to take patches from someone else with a better idea. Until then, simplicity rules. Thanks.

Robert Love

#4 lore raw
Quoted 9 lines · Robert Love
Quoted 6 lines · Joe Korty

The bug is that bh_map_irq *conditionally* calls kmap_atomic (which disables preemption as one of its functions), while bh_unmap_irq *unconditionally* calls kunmap_atomic (which enables it). This imbalance results in a occasional off-by-one preempt_count, which in turn causes IDE PIO mode interrupt code (specifically, read_intr) to erronously invoke preempt_schedule while at interrupt level.

Quoted 8 lines

Thanks for this (and sorry for the very delayed reply).

I am going to put this in the 2.4.21 preempt-kernel patch, because actually someone else here at MontaVista fixed the problem in the same exact way a loooong time ago and it seems to work.

I agree it is suboptimal and I will be happy to take patches from someone else with a better idea. Until then, simplicity rules. Thanks.

See 2.5 for the right fix.

Signature · 1 line
Jens Axboe