Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1785

kernel-2.6.18-238.el5.src.rpm

From: Takahiro Yasui <tyasui@redhat.com>
Date: Thu, 14 Jan 2010 23:51:44 -0500
Subject: [md] fix kernel panic releasing bio after recovery failed
Message-id: <4B4FAE10.2060000@redhat.com>
Patchwork-id: 22562
O-Subject: [RHEL5.5 PATCH] bz555171: fix kernel panic at releasing bio on
	recovery failed region
Bugzilla: 555171
RH-Acked-by: Mikulas Patocka <mpatocka@redhat.com>
RH-Acked-by: Alasdair G Kergon <agk@redhat.com>

BZ#:
----
  https://bugzilla.redhat.com/show_bug.cgi?id=555171

Description:
-----------
Fix kernel panic when bio on a recovery failed region is released.

When recovery process of a region failed, rh_recovery_end() function
changes the state of the region from RM_RH_RECOVERING to DM_RH_NOSYNC.
When recovery_complete() is executed between rh_update_states() and
do_writes() in do_mirror(), bios are processed with the region state,
DM_RH_NOSYNC. However, the region data is freed without checking its
pending count when rh_update_states() is called next time.

When bios are finished by mirror_end_io(), __rh_lookup() in rh_dec()
returns NULL even though a valid return value are expected.

This patch removes the state change of the recovery failed region
from DM_RH_RECOVERING to DM_RH_NOSYNC in rh_recovery_end().

Upstream status:
----------------
  Posted on dm-devel
  https://www.redhat.com/archives/dm-devel/2010-January/msg00047.html

Brew Build:
-----------
  https://brewweb.devel.redhat.com/taskinfo?taskID=2198860

Test status:
------------
  Patch was tested with kernel-2.6.18-182.el5, and confirmed that no
  kernel panic happens when dmsetup suspend is executed.

Thanks,
Takahiro Yasui

Signed-off-by: Takahiro Yasui <tyasui@redhat.com>

diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 6b5b527..23c1d65 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -637,10 +637,8 @@ static void rh_recovery_end(struct region *reg, int success)
 	if (success ||
 	    (rh->log->type->get_failure_response(rh->log) == DMLOG_IOERR_IGNORE))
 		list_add(&reg->list, &reg->rh->recovered_regions);
-	else {
-		reg->state = RH_NOSYNC;
+	else
 		list_add(&reg->list, &reg->rh->failed_recovered_regions);
-	}
 	spin_unlock_irq(&rh->region_lock);
 
 	wake(rh->ms);