From: Douglas Gilbert <dougg@torque.net>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: James Bottomley <James.Bottomley@SteelEye.com>,
Jens Axboe <axboe@suse.de>,
SCSI development list <linux-scsi@vger.kernel.org>
Subject: Re: [PATCH] Improve code for detecting errors near the end of a CD
Date: Sat, 15 Oct 2005 10:49:45 +1000 [thread overview]
Message-ID: <43505229.8010502@torque.net> (raw)
In-Reply-To: <Pine.LNX.4.44L0.0510141603110.6253-100000@iolanthe.rowland.org>
Alan Stern wrote:
> James:
>
> This revised patch (as572b) improves the code in sr.c that detects where
> read/write errors occurred and moves it to a separate (but inline) routine
> for greater clarity.
>
> The original code contained a glaring mistake: testing
> (SCpnt->sense_buffer[0] & 0x90) to see if the Information field in the
> sense data is valid. The Valid bit is 0x80; the test against 0x90 can
> never fail, thanks to an earlier test: (SCpnt->sense_buffer[0] & 0x7f) ==
> 0x70).
>
> The patch is careful to check that the error sector is within the range of
> blocks that were supposed to be transferred, and it rounds the reported
> number of bytes transferred down to a multiple of the block layer's block
> size.
>
> The major enhancement is that the patch uses the Residue to calculate the
> error sector, if the sense data doesn't already provide it. This helps
> with a drive I use. Since the Residue isn't always reported correctly,
> the patch is careful to check that it has a reasonable value: somewhere
> strictly between 0 and the total transfer length.
Alan,
In include/scsi/scsi_eh.h there are several helper functions
to aid processing SCSI errors. This includes SCSI sense data
descriptor format (which won't be needed for DVD/HD/BD for
some time with a (2**32 * 2048) byte maximum using existing
fixed sense data format). However there is
scsi_get_sense_info_fld() to fetch the info field.
sd, st and sg have been converted to use these helpers,
where appropriate.
MMC-4 does not mention that the valid bit needs to
be set on a MEDIUM/HARDWARE error and I have seen
real life examples of this. [So it's poorly defined
if one gets a medium error on lba 0.] You may also like to
consider deferred errors which can occur according to
MMC-4.
Doug Gilbert
> Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
>
> ---
>
> Index: usb-2.6/drivers/scsi/sr.c
> ===================================================================
> --- usb-2.6.orig/drivers/scsi/sr.c
> +++ usb-2.6/drivers/scsi/sr.c
> @@ -203,7 +203,44 @@ int sr_media_change(struct cdrom_device_
> }
> return retval;
> }
> -
> +
> +/*
> + * Use the information from a failed command to compute how much data
> + * was transferred successfully, and find the sector that caused the
> + * error. Be careful to avoid errors from numerical overflow.
> + */
> +static inline int calc_good_bytes(struct scsi_cmnd *SCpnt,
> + long *error_sector, int hw_blocksize,
> + int sectors_per_bio_block)
> +{
> + int req_bytes = SCpnt->bufflen;
> + unsigned int sectors = 0;
> +
> + if (SCpnt->sense_buffer[0] & 0x80) {
> + /* The Information field is valid; use it */
> + unsigned int start_block, error_block, blocks;
> +
> + start_block = (unsigned int) SCpnt->request->sector /
> + (hw_blocksize >> 9);
> + error_block = (SCpnt->sense_buffer[3] << 24) |
> + (SCpnt->sense_buffer[4] << 16) |
> + (SCpnt->sense_buffer[5] << 8) |
> + SCpnt->sense_buffer[6];
> + blocks = error_block - start_block;
> + if (blocks < req_bytes / hw_blocksize)
> + sectors = blocks * (hw_blocksize >> 9);
> + } else {
> + /* Fall back on the Residue */
> + if (SCpnt->resid > 0 && SCpnt->resid < req_bytes)
> + sectors = (req_bytes - SCpnt->resid) >> 9;
> + }
> + *error_sector = SCpnt->request->sector + sectors;
> +
> + /* Round the amount to a multiple of the block layer's block size */
> + sectors &= ~(sectors_per_bio_block - 1);
> + return sectors << 9;
> +}
> +
> /*
> * rw_intr is the interrupt routine for the device driver.
> *
> @@ -235,25 +272,17 @@ static void rw_intr(struct scsi_cmnd * S
> case MEDIUM_ERROR:
> case VOLUME_OVERFLOW:
> case ILLEGAL_REQUEST:
> - if (!(SCpnt->sense_buffer[0] & 0x90))
> - break;
> if (!blk_fs_request(SCpnt->request))
> break;
> - error_sector = (SCpnt->sense_buffer[3] << 24) |
> - (SCpnt->sense_buffer[4] << 16) |
> - (SCpnt->sense_buffer[5] << 8) |
> - SCpnt->sense_buffer[6];
> if (SCpnt->request->bio != NULL)
> block_sectors =
> bio_sectors(SCpnt->request->bio);
> if (block_sectors < 4)
> block_sectors = 4;
> - if (cd->device->sector_size == 2048)
> - error_sector <<= 2;
> - error_sector &= ~(block_sectors - 1);
> - good_bytes = (error_sector - SCpnt->request->sector) << 9;
> - if (good_bytes < 0 || good_bytes >= this_count)
> - good_bytes = 0;
> +
> + good_bytes = calc_good_bytes(SCpnt, &error_sector,
> + cd->device->sector_size,
> + block_sectors);
> /*
> * The SCSI specification allows for the value
> * returned by READ CAPACITY to be up to 75 2K
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
next prev parent reply other threads:[~2005-10-15 0:48 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-10-14 20:07 [PATCH] Improve code for detecting errors near the end of a CD Alan Stern
2005-10-15 0:49 ` Douglas Gilbert [this message]
2005-10-15 2:36 ` Alan Stern
2005-10-15 3:35 ` Douglas Gilbert
2005-10-19 20:32 ` Alan Stern
2005-10-20 2:56 ` Douglas Gilbert
2005-10-20 16:04 ` Alan Stern
2005-10-21 3:05 ` Douglas Gilbert
-- strict thread matches above, loose matches on Subject: below --
2005-09-29 18:44 Alan Stern
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=43505229.8010502@torque.net \
--to=dougg@torque.net \
--cc=James.Bottomley@SteelEye.com \
--cc=axboe@suse.de \
--cc=linux-scsi@vger.kernel.org \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.