Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3088

kernel-2.6.18-194.11.1.el5.src.rpm

From: Hans-Joachim Picht <hpicht@redhat.com>
Date: Tue, 20 Jan 2009 16:59:37 +0100
Subject: [s390] cio: I/O error after cable pulls
Message-id: 20090120155937.GH21694@redhat.com
O-Subject: [RHEL5 U4 PATCH 8/8] s390 - cio: I/O error after cable pulls
Bugzilla: 479878
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

Description
============

After some cables to a dasd device have been pulled, the dasd unsuccessfully
tries to submit I/O. After the retries for the error recovery have been
exhausted, an I/O error is generated.
This leads to a machine crash during disk mirroring caused by adevice mapper failure.

This is the backport of a upstream patch provided by Alasdair G Kergon
<agk@redhat.com>.

	dm: detect lost queue
	author	Alasdair G Kergon <agk@redhat.com>
		Fri, 10 Oct 2008 12:37:13 +0000 (13:37 +0100)
	committer	Alasdair G Kergon <agk@redhat.com>
		Fri, 10 Oct 2008 12:37:13 +0000 (13:37 +0100)
	commit	0c2322e4ce144e130c03d813fe92de3798662c5e

	Detect and report buggy drivers that destroy their request_queue.

	Signed-off-by: Alasdair G Kergon <agk@redhat.com>
	Cc: Stefan Raspl <raspl@linux.vnet.ibm.com>
	Cc: Jens Axboe <jens.axboe@oracle.com>
	Cc: Andrew Morton <akpm@linux-foundation.org>

AFAIK the problem is currently only applicable on s390.

Bugzilla
=========

BZ 479878
https://bugzilla.redhat.com/show_bug.cgi?id=479878

Upstream status of the patch:
=============================

The patch provided by Alasdair G Kergon <agk@redhat.com>
is upstream as of git commit 0c2322e4ce144e130c03d813fe92de3798662c5e

Test status:
============

The patch has been tested and fixes the problem.
The fix has been verified by the IBM test department.

Please ACK.

With best regards,

	--Hans

diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 2a01dfd..afac24b 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -980,7 +980,14 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits)
 	for (d = devices->next; d != devices; d = d->next) {
 		struct dm_dev *dd = list_entry(d, struct dm_dev, list);
 		request_queue_t *q = bdev_get_queue(dd->bdev);
-		r |= bdi_congested(&q->backing_dev_info, bdi_bits);
+		char b[BDEVNAME_SIZE];
+
+		if (likely(q))
+			r |= bdi_congested(&q->backing_dev_info, bdi_bits);
+		else
+			DMWARN("%s: any_congested: nonexistent device %s",
+				     dm_device_name(t->md),
+				     bdevname(dd->bdev, b));
 	}
 
 	return r;
@@ -994,8 +1001,16 @@ void dm_table_unplug_all(struct dm_table *t)
 		struct dm_dev *dd = list_entry(d, struct dm_dev, list);
 		request_queue_t *q = bdev_get_queue(dd->bdev);
 
-		if (q->unplug_fn)
-			q->unplug_fn(q);
+		if (likely(q)) {
+			if (q->unplug_fn)
+	                        q->unplug_fn(q);
+		}
+		else {
+			char b[BDEVNAME_SIZE];
+			DMWARN("%s: Cannot unplug nonexistent device %s",
+				     dm_device_name(t->md),
+				     bdevname(dd->bdev, b));
+		}
 	}
 }
 
@@ -1007,12 +1022,21 @@ int dm_table_flush_all(struct dm_table *t)
 	for (d = devices->next; d != devices; d = d->next) {
 		struct dm_dev *dd = list_entry(d, struct dm_dev, list);
 		request_queue_t *q = bdev_get_queue(dd->bdev);
-		int err;
-
-		if (!q->issue_flush_fn)
-			err = -EOPNOTSUPP;
-		else
-			err = q->issue_flush_fn(q, dd->bdev->bd_disk, NULL);
+		int err = 0;
+
+		if (likely(q)) {
+			if (!q->issue_flush_fn)
+				err = -EOPNOTSUPP;
+			else
+				err = q->issue_flush_fn(q, dd->bdev->bd_disk,
+					NULL);
+		}
+		else {
+			char b[BDEVNAME_SIZE];
+			DMWARN("%s: Cannot flush nonexistent device %s",
+                                     dm_device_name(t->md),
+                                     bdevname(dd->bdev, b));
+		}
 
 		if (!ret)
 			ret = err;