From: "Jun'ichi Nomura" <j-nomura@ce.jp.nec.com>

Fix the bug in dm-raid1.c that the region returned by __rh_alloc() may be
freed while it's in use.

__rh_alloc() write-unlocks the hash_lock after inserting the new region. 
Though it read-locks the hash-lock just after that, it's possible that the
region was reclaimed by rh_update_states() as the region was clean at the
time.

   CPU0                                  CPU1
   -----------------------------------------------------------------------
   __rh_alloc()
     write_lock(hash_lock)
     <insert new region to clean list>
     write_unlock(hash_lock)
                                         rh_update_states()
                                           write_lock(hash_lock)
                                           <move clean regions to freeable list>
                                           write_unlock(hash_lock)
                                           <free regions in the freeable list>
     read_lock(hash_lock)
     <return the region>

Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/md/dm-raid1.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletion(-)

diff -puN drivers/md/dm-raid1.c~md-__rh_alloc-rh_update_states-race-in-dm-raid1c drivers/md/dm-raid1.c
--- 25/drivers/md/dm-raid1.c~md-__rh_alloc-rh_update_states-race-in-dm-raid1c	2005-06-16 16:49:41.000000000 -0700
+++ 25-akpm/drivers/md/dm-raid1.c	2005-06-16 16:49:41.000000000 -0700
@@ -269,9 +269,12 @@ static inline struct region *__rh_find(s
 {
 	struct region *reg;
 
+retry:
 	reg = __rh_lookup(rh, region);
-	if (!reg)
+	if (!reg) {
 		reg = __rh_alloc(rh, region);
+		goto retry;
+	}
 
 	return reg;
 }
_