Re: [BUG] nfs client stuck in D state in linux 2.4.17 - 2.4.21-pre5

From: Russell King (rmk@arm.linux.org.uk)
Date: Wed May 21 2003 - 04:29:23 EST


On Mon, May 19, 2003 at 05:20:27PM +0400, Vladimir Serov wrote:
> My current kernel is 2.4.21-pre6 based with patches from 2.4.19-rmk7
> applied (well partially, except ide and pci cause i don't have them,
> board is mostly brutus). I'm using HARD mounted nfs
> volume now !!! The tail of dmesg is following.

Looking back on stuff which happened a long time ago, there's a
possibility that there's an ordering issue with set_current_state.

Please note that this is affects _all_ 2.4 architectures.

I think this was discussed about 6 months ago, so I'm surprised this
hasn't made it into the 2.4.2x kernel (or no one else has seen the
problem.)

Please note that since I don't track 2.4 kernels currently, I've no
idea whether 2.4.21-pre/rc has this fix. (This means if Marcelo
drops or ignores the fix, it won't get re-sent.) Certainly gcc 3
requires this patch. I've not heard of gcc 2.95.x tripping over
this problem though.

The problem area is:

#define __set_task_state(tsk, state_value) \
        do { (tsk)->state = (state_value); } while (0)
#ifdef CONFIG_SMP
#define set_task_state(tsk, state_value) \
        set_mb((tsk)->state, (state_value))
#else
#define set_task_state(tsk, state_value) \
        __set_task_state((tsk), (state_value))
#endif

#define __set_current_state(state_value) \
        do { current->state = (state_value); } while (0)
#ifdef CONFIG_SMP
#define set_current_state(state_value) \
        set_mb(current->state, (state_value))
#else
#define set_current_state(state_value) \
        __set_current_state(state_value)
#endif

As they currently stand, there is no guarantee that the assignment to
"->state" occurs before the condition in wait_event is processed.

The attached patch should fix your problem. It should be applied to
2.4.2x. All architectures which do not provide set_mb() need to be
fixed.

--- ref/include/linux/sched.h Wed Mar 19 15:54:45 2003
+++ linux/include/linux/sched.h Wed May 14 09:45:31 2003
@@ -94,23 +94,13 @@
 
 #define __set_task_state(tsk, state_value) \
         do { (tsk)->state = (state_value); } while (0)
-#ifdef CONFIG_SMP
 #define set_task_state(tsk, state_value) \
         set_mb((tsk)->state, (state_value))
-#else
-#define set_task_state(tsk, state_value) \
- __set_task_state((tsk), (state_value))
-#endif
 
 #define __set_current_state(state_value) \
         do { current->state = (state_value); } while (0)
-#ifdef CONFIG_SMP
 #define set_current_state(state_value) \
         set_mb(current->state, (state_value))
-#else
-#define set_current_state(state_value) \
- __set_current_state(state_value)
-#endif
 
 /*
  * Scheduling policies
--- ref/include/asm-arm/system.h Wed Sep 11 17:30:52 2002
+++ linux/include/asm-arm/system.h Wed May 14 09:46:20 2003
@@ -46,6 +46,8 @@
 #define mb() __asm__ __volatile__ ("" : : : "memory")
 #define rmb() mb()
 #define wmb() mb()
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
 #define prepare_to_switch() do { } while(0)

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri May 23 2003 - 22:00:44 EST