linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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
> 


  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).