Scsi removable disk patch

Richard Waltham (dormouse@farsrobt.demon.co.uk)
Sat, 14 Jun 1997 12:56:34 +0100 (BST)


Hi,

The behaviour of the scsi code with removable drives that automatically
spindown has been getting to me so I set out to fix it.

Problem was if the drive had spun down. Executing a command on that drive
would fail first time round, even though the drive would eventually spin up,
and the command would then have to be repeated, annoying and unnecessary.

eg e2fsck /dev/sdb3. First time it would fail saying it couldn't read the
partition table. Repeating the command and it executed OK.

After much digging through various bits of code, (I know a bit more about
the block device drivers than a couple of weeks ago:)) seems the root of the
problem is in sd.c - check_scsidisk_media_change() - called while opening the
device. This was always reporting not ready even for a drive with a
cartridge.

This does a test unit ready and fails if the drive is not ready for ANY
reason - and this will happen if the disk has no cartridge installed OR it
has spundown. Changing the test unit ready to a Start/Stop command fixes it.
With no cartridge installed it still fails, correctly, but now with a
cartridge installed it spins up and either reports disk changed if it has
been changed or executes normally if the cartridge hasn't been changed.

eg the Start/Stop command reports NOT READY with no cartridge, UNIT
ATTENTION if the cartridge has changed (or has been ejected and reinserted),
or GOOD STATUS if the cartridge has not changed.

This patch has been tested using kernel 2.0.29, ncr53c8xx 2.3 scsi driver,
with iomega jaz 1GB and Fujitsu 2512a MO drives. I have also tried it with
2.1.42 where the code affected is currently the same.

Patch is against 2.0.29 but also applies to 2.1.42 OK. Would be a useful
addition to 2.0.31:)

Richard

--------------------------------------------------------------------------
--- linux-2.0.29/include/scsi/scsi_ioctl.h Thu Jun 12 10:23:39 1997
+++ linux/include/scsi/scsi_ioctl.h Thu Jun 12 10:22:29 1997
@@ -5,6 +5,7 @@
#define SCSI_IOCTL_TEST_UNIT_READY 2
#define SCSI_IOCTL_BENCHMARK_COMMAND 3
#define SCSI_IOCTL_SYNC 4 /* Request synchronous parameters */
+#define SCSI_IOCTL_SPIN_UP_UNIT 5
/* The door lock/unlock constants are compatible with Sun constants for
the cdrom */
#define SCSI_IOCTL_DOORLOCK 0x5380 /* lock the eject mechanism */
--- linux-2.0.29/drivers/scsi/sd.c Thu Jun 12 12:42:32 1997
+++ linux/drivers/scsi/sd.c Thu Jun 12 12:44:09 1997
@@ -966,7 +966,14 @@
if(!rscsi_disks[target].device->removable) return 0;

inode.i_rdev = full_dev; /* This is all we really need here */
- retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);
+
+ /* Using Start/Stop enables differentiation between drive with
+ * no cartridge loaded - NOT READY, drive with changed cartridge -
+ * UNIT ATTENTION, or with same cartridge - GOOD STATUS.
+ * This also handles drives that auto spin down. eg iomega jaz 1GB
+ * as this will spin up the drive.
+ */
+ retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_SPIN_UP_UNIT, 0);

if(retval){ /* Unable to test, unit probably not ready. This usually
* means there is no disc in the drive. Mark as changed,
--- linux-2.0.29/drivers/scsi/scsi_ioctl.c Thu Jun 12 10:23:42 1997
+++ linux/drivers/scsi/scsi_ioctl.c Thu Jun 12 11:33:27 1997
@@ -378,6 +378,13 @@
scsi_cmd[4] = 0;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
break;
+ case SCSI_IOCTL_SPIN_UP_UNIT:
+ scsi_cmd[0] = START_STOP;
+ scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
+ scsi_cmd[4] = 1;
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
+ break;
default :
return -EINVAL;
}
--------------------------------------------------------------------------

-- 
 Richard Waltham   |               Work: richard@digtalinterface.demon.co.uk
   At home in      |               Home:       dormouse@farsrobt.demon.co.uk
 Southampton UK    |                                  Compuserve 100421.1276