Commit a19bafa6 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] scsi stuff

The patch below cleans up some SCSI stuff.

The main purpose is to avoid trying to read the partition table
of a removable disk when the drive has told us that no media
are present. (Right now we try to read a 4K block and fail and
retry and fail, and give an I/O error on the first sector,
then try to read the second sector and fail and retry ...)

Unused fields  sector_bit_size  and  sector_bit_shift  in
struct scsi_disk were removed. The field  has_part_table
(that has nothing to do with partition tables) was
renamed to  has_been_registered . The field  ready  was
renamed to  media_present .
The overly long  sd_init_onedisk()  was split up.

When we notice that no media are present anymore, the
partitions are removed from /proc/partitions, but the
drive remains, with size 0.

A future patch will remove the field  capacity  - there are
all too many places where capacities are stored - but the
present patch is large enough already.

There is also a quite independent patch in scsi_error.c
(yesterday someone had an infinite loop retrying to read
bad media) - this patch honours the SCpnt->retries.
In case you applied this already, just ignore the scsi_error.c part.

Also some "Overrides for Emacs" were removed.
parent 2b4b6c20
...@@ -177,9 +177,10 @@ static int show_partition(struct seq_file *part, void *v) ...@@ -177,9 +177,10 @@ static int show_partition(struct seq_file *part, void *v)
if (sgp == gendisk_head) if (sgp == gendisk_head)
seq_puts(part, "major minor #blocks name\n\n"); seq_puts(part, "major minor #blocks name\n\n");
/* show all non-0 size partitions of this disk */ /* show the full disk and all non-0 size partitions of it */
for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) { for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) {
if (sgp->part[n].nr_sects == 0) int minormask = (1<<sgp->minor_shift) - 1;
if ((n & minormask) && sgp->part[n].nr_sects == 0)
continue; continue;
seq_printf(part, "%4d %4d %10d %s\n", seq_printf(part, "%4d %4d %10d %s\n",
sgp->major, n, sgp->sizes[n], sgp->major, n, sgp->sizes[n],
......
...@@ -2048,7 +2048,7 @@ static int esp_do_data_finale(struct NCR_ESP *esp, ...@@ -2048,7 +2048,7 @@ static int esp_do_data_finale(struct NCR_ESP *esp,
* and not only for the entire host adapter as it is now, the workaround * and not only for the entire host adapter as it is now, the workaround
* is way to expensive performance wise. * is way to expensive performance wise.
* Instead, it turns out that when this happens the target has disconnected * Instead, it turns out that when this happens the target has disconnected
* allready but it doesn't show in the interrupt register. Compensate for * already but it doesn't show in the interrupt register. Compensate for
* that here to try and avoid a SCSI bus reset. * that here to try and avoid a SCSI bus reset.
*/ */
if(!esp->fas_premature_intr_workaround && (fifocnt == 1) && if(!esp->fas_premature_intr_workaround && (fifocnt == 1) &&
......
...@@ -1095,6 +1095,8 @@ int scsi_decide_disposition(Scsi_Cmnd * SCpnt) ...@@ -1095,6 +1095,8 @@ int scsi_decide_disposition(Scsi_Cmnd * SCpnt)
*/ */
STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
{ {
int rtn;
/* /*
* First check the host byte, to see if there is anything in there * First check the host byte, to see if there is anything in there
* that would indicate what we need to do. * that would indicate what we need to do.
...@@ -1102,20 +1104,25 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) ...@@ -1102,20 +1104,25 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
if (host_byte(SCpnt->result) == DID_RESET) { if (host_byte(SCpnt->result) == DID_RESET) {
if (SCpnt->flags & IS_RESETTING) { if (SCpnt->flags & IS_RESETTING) {
/* /*
* OK, this is normal. We don't know whether in fact the * OK, this is normal. We don't know whether in fact
* command in question really needs to be rerun or not - * the command in question really needs to be rerun
* if this was the original data command then the answer is yes, * or not - if this was the original data command then
* otherwise we just flag it as success. * the answer is yes, otherwise we just flag it as
* success.
*/ */
SCpnt->flags &= ~IS_RESETTING; SCpnt->flags &= ~IS_RESETTING;
return NEEDS_RETRY; goto maybe_retry;
} }
/* /*
* Rats. We are already in the error handler, so we now get to try * Rats. We are already in the error handler, so we now
* and figure out what to do next. If the sense is valid, we have * get to try and figure out what to do next. If the sense
* a pretty good idea of what to do. If not, we mark it as failed. * is valid, we have a pretty good idea of what to do.
* If not, we mark it as failed.
*/ */
return scsi_check_sense(SCpnt); rtn = scsi_check_sense(SCpnt);
if (rtn == NEEDS_RETRY)
goto maybe_retry;
return rtn;
} }
if (host_byte(SCpnt->result) != DID_OK) { if (host_byte(SCpnt->result) != DID_OK) {
return FAILED; return FAILED;
...@@ -1127,14 +1134,18 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) ...@@ -1127,14 +1134,18 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
return FAILED; return FAILED;
} }
/* /*
* Now, check the status byte to see if this indicates anything special. * Now, check the status byte to see if this indicates
* anything special.
*/ */
switch (status_byte(SCpnt->result)) { switch (status_byte(SCpnt->result)) {
case GOOD: case GOOD:
case COMMAND_TERMINATED: case COMMAND_TERMINATED:
return SUCCESS; return SUCCESS;
case CHECK_CONDITION: case CHECK_CONDITION:
return scsi_check_sense(SCpnt); rtn = scsi_check_sense(SCpnt);
if (rtn == NEEDS_RETRY)
goto maybe_retry;
return rtn;
case CONDITION_GOOD: case CONDITION_GOOD:
case INTERMEDIATE_GOOD: case INTERMEDIATE_GOOD:
case INTERMEDIATE_C_GOOD: case INTERMEDIATE_C_GOOD:
...@@ -1149,6 +1160,14 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt) ...@@ -1149,6 +1160,14 @@ STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
return FAILED; return FAILED;
} }
return FAILED; return FAILED;
maybe_retry:
if ((++SCpnt->retries) < SCpnt->allowed) {
return NEEDS_RETRY;
} else {
/* No more retries - report this one back to upper level */
return SUCCESS;
}
} }
/* /*
......
...@@ -127,7 +127,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd, ...@@ -127,7 +127,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
/* gag this error, VFS will log it anyway /axboe */ /* gag this error, VFS will log it anyway /axboe */
/* printk(KERN_INFO "Disc change detected.\n"); */ /* printk(KERN_INFO "Disc change detected.\n"); */
break; break;
}; }
default: /* Fall through for non-removable media */ default: /* Fall through for non-removable media */
printk("SCSI error: host %d id %d lun %d return code = %x\n", printk("SCSI error: host %d id %d lun %d return code = %x\n",
dev->host->host_no, dev->host->host_no,
...@@ -139,7 +139,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd, ...@@ -139,7 +139,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
sense_error(SRpnt->sr_sense_buffer[0]), sense_error(SRpnt->sr_sense_buffer[0]),
SRpnt->sr_sense_buffer[2] & 0xf); SRpnt->sr_sense_buffer[2] & 0xf);
}; }
result = SRpnt->sr_result; result = SRpnt->sr_result;
...@@ -152,7 +152,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd, ...@@ -152,7 +152,7 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
} }
/* /*
* This interface is depreciated - users should use the scsi generic (sg) * This interface is deprecated - users should use the scsi generic (sg)
* interface instead, as this is a more flexible approach to performing * interface instead, as this is a more flexible approach to performing
* generic SCSI commands on a device. * generic SCSI commands on a device.
* *
...@@ -516,22 +516,3 @@ int kernel_scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) ...@@ -516,22 +516,3 @@ int kernel_scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
set_fs(oldfs); set_fs(oldfs);
return tmp; return tmp;
} }
/*
* Overrides for Emacs so that we almost follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
This diff is collapsed.
...@@ -11,9 +11,6 @@ ...@@ -11,9 +11,6 @@
*/ */
#ifndef _SD_H #ifndef _SD_H
#define _SD_H #define _SD_H
/*
$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/07/24 06:27:38 root Exp root $
*/
#ifndef _SCSI_H #ifndef _SCSI_H
#include "scsi.h" #include "scsi.h"
...@@ -26,13 +23,11 @@ ...@@ -26,13 +23,11 @@
extern struct hd_struct *sd; extern struct hd_struct *sd;
typedef struct scsi_disk { typedef struct scsi_disk {
unsigned capacity; /* size in blocks */ unsigned capacity; /* size in 512-byte sectors */
Scsi_Device *device; Scsi_Device *device;
unsigned char ready; /* flag ready for FLOPTICAL */ unsigned char media_present;
unsigned char write_prot; /* flag write_protect for rmvable dev */ unsigned char write_prot;
unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */ unsigned has_been_registered:1;
unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
unsigned has_part_table:1; /* has partition table */
} Scsi_Disk; } Scsi_Disk;
extern int revalidate_scsidisk(kdev_t dev, int maxusage); extern int revalidate_scsidisk(kdev_t dev, int maxusage);
...@@ -48,22 +43,3 @@ extern kdev_t sd_find_target(void *host, int tgt); ...@@ -48,22 +43,3 @@ extern kdev_t sd_find_target(void *host, int tgt);
#define SD_PARTITION(i) (((major(i) & SD_MAJOR_MASK) << 8) | (minor(i) & 255)) #define SD_PARTITION(i) (((major(i) & SD_MAJOR_MASK) << 8) | (minor(i) & 255))
#endif #endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
...@@ -24,8 +24,6 @@ typedef struct { ...@@ -24,8 +24,6 @@ typedef struct {
Scsi_Device *device; Scsi_Device *device;
unsigned int vendor; /* vendor code, see sr_vendor.c */ unsigned int vendor; /* vendor code, see sr_vendor.c */
unsigned long ms_offset; /* for reading multisession-CD's */ unsigned long ms_offset; /* for reading multisession-CD's */
unsigned char sector_bit_size; /* sector size = 2^sector_bit_size */
unsigned char sector_bit_shift; /* sectors/FS block = 2^sector_bit_shift */
unsigned needs_sector_size:1; /* needs to get sector size */ unsigned needs_sector_size:1; /* needs to get sector size */
unsigned use:1; /* is this device still supportable */ unsigned use:1; /* is this device still supportable */
unsigned xa_flag:1; /* CD has XA sectors ? */ unsigned xa_flag:1; /* CD has XA sectors ? */
......
...@@ -412,8 +412,8 @@ void grok_partitions(kdev_t dev, long size) ...@@ -412,8 +412,8 @@ void grok_partitions(kdev_t dev, long size)
g->part[first_minor].nr_sects = size; g->part[first_minor].nr_sects = size;
/* No such device or no minors to use for partitions */ /* No minors to use for partitions */
if (!size || minors == 1) if (minors == 1)
return; return;
if (g->sizes) { if (g->sizes) {
...@@ -422,6 +422,11 @@ void grok_partitions(kdev_t dev, long size) ...@@ -422,6 +422,11 @@ void grok_partitions(kdev_t dev, long size)
g->sizes[i] = 0; g->sizes[i] = 0;
} }
blk_size[g->major] = g->sizes; blk_size[g->major] = g->sizes;
/* No such device (e.g., media were just removed) */
if (!size)
return;
check_partition(g, mk_kdev(g->major, first_minor), 1 + first_minor); check_partition(g, mk_kdev(g->major, first_minor), 1 + first_minor);
/* /*
......
...@@ -223,23 +223,4 @@ typedef struct scsi_lun { ...@@ -223,23 +223,4 @@ typedef struct scsi_lun {
/* Used to get the PCI location of a device */ /* Used to get the PCI location of a device */
#define SCSI_IOCTL_GET_PCI 0x5387 #define SCSI_IOCTL_GET_PCI 0x5387
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment