Use SCSI sense data in dm-mpath bio-end_io if available
Subsystems (4)
PATCH 1/1 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 <[email protected]>
Signature · 3 lines
High Availability & Clustering SUSE Labs, Research and Development SUSE LINUX Products GmbH - A Novell Business
From: Jens Axboe <[email protected]>
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 <[email protected]>
Signed-off-by Jens Axboe <[email protected]>
drivers/block/ll_rw_blk.c renamed from opt/kernel/linux-2.6.5/drivers/block/ll_rw_blk.c +11 -0
@@ -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(struif (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(struwhile ((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;
drivers/scsi/scsi_lib.c renamed from opt/kernel/linux-2.6.5/drivers/scsi/scsi_lib.c +15 -0
@@ -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);
fs/bio.c renamed from opt/kernel/linux-2.6.5/fs/bio.c +1 -0
@@ -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 ;
include/linux/bio.h renamed from opt/kernel/linux-2.6.5/include/linux/bio.h +18 -0
@@ -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 <[email protected]>
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 <[email protected]>
drivers/md/dm-emc.c +5 -8
@@ -290,12 +290,10 @@ static void emc_dtr(struct hw_handler *hstatic 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);
drivers/md/dm-hw-handler.c +4 -6
@@ -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_hreturn 0 ; } } -#endif /* We got no idea how to decode the other kinds of errors -> * assume generic error condition. */