[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[dm-devel] [PATCH] Use SCSI sense data in dm-mpath bio-end_io if available



Good morning Alasdair & list,

the attached two patches enable SCSI sense data to be available in the
bio-end_io path and use it in dm-mpath's hwhandler as well as dm-emc.c.

Please test and let us know the results.


Sincerely,
    Lars Marowsky-Brée <lmb suse de>

-- 
High Availability & Clustering
SUSE Labs, Research and Development
SUSE LINUX Products GmbH - A Novell Business

From: Jens Axboe <axboe suse de>
Subject: Make SCSI sense data available in bio end_io path
Patch-mainline: 2.6.13
References: 62498

Make the sense data available in the bio end_io path on request.


Signed-off-by: Lars Marowsky-Bree <lmb suse de>
Signed-off-by: Jens Axboe <axboe suse de>

diff -urp -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.6.5/drivers/block/ll_rw_blk.c linux-2.6.5/drivers/block/ll_rw_blk.c
--- /opt/kernel/linux-2.6.5/drivers/block/ll_rw_blk.c	2005-04-01 09:41:07.000000000 +0200
+++ linux-2.6.5/drivers/block/ll_rw_blk.c	2005-04-01 10:11:43.000000000 +0200
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
+#include <linux/cdrom.h>
 
 /*
  * for max sense size
@@ -2989,6 +2990,7 @@ static int __end_that_request_first(stru
 				    int nr_bytes)
 {
 	int total_bytes, bio_nbytes, error, next_idx = 0;
+	struct request_sense *s = NULL;
 	struct bio *bio;
 
 	/*
@@ -2998,6 +3000,12 @@ static int __end_that_request_first(stru
 	if (end_io_error(uptodate))
 		error = !uptodate ? -EIO : uptodate;
 
+	if (req->sense && req->sense_len) {
+		s = req->sense;
+		if (!s->valid)
+			s = NULL;
+	}
+
 	/*
 	 * for a REQ_BLOCK_PC request, we want to carry any eventual
 	 * sense key with us all the way through
@@ -3023,6 +3031,9 @@ static int __end_that_request_first(stru
 	while ((bio = req->bio)) {
 		int nbytes;
 
+		if (s)
+			bio_set_sense(bio, s->sense_key, s->asc, s->ascq);
+
 		if (nr_bytes >= bio->bi_size) {
 			req->bio = bio->bi_next;
 			nbytes = bio->bi_size;
diff -urp -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.6.5/drivers/scsi/scsi_lib.c linux-2.6.5/drivers/scsi/scsi_lib.c
--- /opt/kernel/linux-2.6.5/drivers/scsi/scsi_lib.c	2005-04-01 09:41:06.000000000 +0200
+++ linux-2.6.5/drivers/scsi/scsi_lib.c	2005-04-01 10:51:20.000000000 +0200
@@ -517,9 +517,21 @@ static struct scsi_cmnd *scsi_end_reques
 {
 	request_queue_t *q = cmd->device->request_queue;
 	struct request *req = cmd->request;
+	int sense_override = 0;
 	unsigned long flags;
 
 	/*
+	 * if room for sense wasn't supplied for this request, override with
+	 * what we have stored for the duration of the end_io handling. this
+	 * allows passing of sense to the block layer.
+	 */
+	if (!req->sense && (cmd->sense_buffer[0] & 0x70)) {
+		req->sense = cmd->sense_buffer;
+		req->sense_len = 8 + cmd->sense_buffer[7];
+		sense_override = 1;
+	}
+
+	/*
 	 * If there are blocks left over at the end, set up the command
 	 * to queue the remainder of them.
 	 */
@@ -545,6 +557,9 @@ static struct scsi_cmnd *scsi_end_reques
 		}
 	}
 
+	if (sense_override)
+		req->sense = NULL;
+
 	add_disk_randomness(req->rq_disk);
 
 	spin_lock_irqsave(q->queue_lock, flags);
diff -urp -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.6.5/fs/bio.c linux-2.6.5/fs/bio.c
--- /opt/kernel/linux-2.6.5/fs/bio.c	2005-04-01 09:41:14.000000000 +0200
+++ linux-2.6.5/fs/bio.c	2005-04-01 10:54:16.000000000 +0200
@@ -108,6 +108,7 @@ inline void bio_init(struct bio *bio)
 	bio->bi_bdev = NULL;
 	bio->bi_flags = 1 << BIO_UPTODATE;
 	bio->bi_rw = 0;
+	bio->bi_error = 0;
 	bio->bi_vcnt = 0;
 	bio->bi_idx = 0;
 	bio->bi_phys_segments = 0;
diff -urp -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.6.5/include/linux/bio.h linux-2.6.5/include/linux/bio.h
--- /opt/kernel/linux-2.6.5/include/linux/bio.h	2005-04-01 09:41:08.000000000 +0200
+++ linux-2.6.5/include/linux/bio.h	2005-04-01 10:14:54.000000000 +0200
@@ -66,6 +66,7 @@ struct bio {
 	unsigned long		bi_rw;		/* bottom bits READ/WRITE,
 						 * top bits priority
 						 */
+	unsigned int		bi_error;	/* -Exx or sense */
 
 	unsigned short		bi_vcnt;	/* how many bio_vec's */
 	unsigned short		bi_idx;		/* current index into bvl_vec */
@@ -211,6 +212,23 @@ struct bio {
  */
 #define bio_get(bio)	atomic_inc(&(bio)->bi_cnt)
 
+enum {
+	BIO_ERROR_ERRNO = 1,
+	BIO_ERROR_SENSE,
+};
+
+/*
+ * Extended error reporting. The upper 8 bits are flag values, the bottom
+ * 24 can be used for extended errors (such as sense).
+ */
+static inline void bio_set_sense(struct bio *bio, char key, char asc, char ascq)
+{
+	bio->bi_error = (BIO_ERROR_SENSE << 24) | (key << 16) | (asc << 8) | ascq;
+}
+
+#define bio_errno_valid(bio)	((bio)->bi_error & (BIO_ERROR_ERRNO << 24))
+#define bio_sense_valid(bio)	((bio)->bi_error & (BIO_ERROR_SENSE << 24))
+#define bio_sense_value(bio)	((bio)->bi_error & 0xffffff)
 
 /*
  * A bio_pair is used when we need to split a bio.

From: Lars Marowsky-Bree <lmb suse de>
Subject: Use SCSI sense data in dm-mpath bio end_io path
Patch-mainline: 2.6.13
Suse-bugzilla: 62498

Use the sense data in the dm-mpath hardware handlers.

Signed-off-by: Jens Axboe <axboe suse de>

Index: linux-2.6.5/drivers/md/dm-emc.c
===================================================================
--- linux-2.6.5.orig/drivers/md/dm-emc.c	2005-04-11 13:59:37.825222738 +0200
+++ linux-2.6.5/drivers/md/dm-emc.c	2005-04-11 14:14:04.772636876 +0200
@@ -290,12 +290,10 @@ static void emc_dtr(struct hw_handler *h
 
 static unsigned emc_err(struct hw_handler *hwh, struct bio *bio)
 {
-	/* FIXME: Patch from axboe still missing */
-#if 0
 	int sense;
 
-	if (bio->bi_error & BIO_SENSE) {
-		sense = bio->bi_error & 0xffffff; /* sense key / asc / ascq */
+	if (bio_sense_valid(bio)) {
+		sense = bio_sense_value(bio); /* sense key / asc / ascq */
 
 		if (sense == 0x020403) {
 			/* LUN Not Ready - Manual Intervention Required
@@ -306,21 +304,20 @@ static unsigned emc_err(struct hw_handle
 			 * progress, we should set FAIL_PATH too.
 			 * This indicates we might have to do a SCSI
 			 * inquiry in the end_io path. Ugh. */
-			return MP_BYPASS_PG | MP_RETRY_IO;
+			return MP_BYPASS_PG;
 		} else if (sense == 0x052501) {
 			/* An array based copy is in progress. Do not
 			 * fail the path, do not bypass to another PG,
 			 * do not retry. Fail the IO immediately.
 			 * (Actually this is the same conclusion as in
 			 * the default handler, but lets make sure.) */
-			return 0;
+			return MP_ERROR_IO;
 		} else if (sense == 0x062900) {
 			/* Unit Attention Code. This is the first IO 
 			 * to the new path, so just retry. */
-			return MP_RETRY_IO;
+			return 0;
 		}
 	}
-#endif
 
 	/* Try default handler */
 	return dm_scsi_err_handler(hwh, bio);
Index: linux-2.6.5/drivers/md/dm-hw-handler.c
===================================================================
--- linux-2.6.5.orig/drivers/md/dm-hw-handler.c	2005-04-11 13:59:37.805225704 +0200
+++ linux-2.6.5/drivers/md/dm-hw-handler.c	2005-04-11 14:14:49.225050588 +0200
@@ -153,13 +153,12 @@ unsigned dm_scsi_err_handler(struct hw_h
 {
 	int sense_key, asc, ascq;
 
-#if 0
-	if (bio->bi_error & BIO_SENSE) {
+	if (bio_sense_valid(bio)) {
 		/* FIXME: This is just an initial guess. */
 		/* key / asc / ascq */
-		sense_key = (bio->bi_error >> 16) & 0xff;
-		asc = (bio->bi_error >> 8) & 0xff;
-		ascq = bio->bi_error & 0xff;
+		sense_key = (bio_sense_value(bio) >> 16) & 0xff;
+		asc = (bio_sense_value(bio) >> 8) & 0xff;
+		ascq = bio_sense_value(bio) & 0xff;
 
 		switch (sense_key) {
 			/* This block as a whole comes from the device.
@@ -204,7 +203,6 @@ unsigned dm_scsi_err_handler(struct hw_h
 			return 0;
 		}
 	}
-#endif
 
 	/* We got no idea how to decode the other kinds of errors ->
 	 * assume generic error condition. */

Attachment: pgp00000.pgp
Description: PGP signature


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]