patch-2.4.7 linux/drivers/scsi/sd.c
Next file: linux/drivers/scsi/sg.c
Previous file: linux/drivers/scsi/scsi_scan.c
Back to the patch index
Back to the overall index
- Lines: 209
- Date:
Thu Jul 5 11:28:17 2001
- Orig file:
v2.4.6/linux/drivers/scsi/sd.c
- Orig date:
Tue Jul 3 17:08:20 2001
diff -u --recursive --new-file v2.4.6/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
@@ -22,6 +22,12 @@
*
* Modified by Torben Mathiasen tmm@image.dk
* Resource allocation fixes in sd_init and cleanups.
+ *
+ * Modified by Alex Davis <letmein@erols.com>
+ * Fix problem where partition info not being read in sd_open.
+ *
+ * Modified by Alex Davis <letmein@erols.com>
+ * Fix problem where removable media could be ejected after sd_open.
*/
#include <linux/config.h>
@@ -372,7 +378,8 @@
(SCpnt->request.cmd == WRITE) ? "writing" : "reading",
this_count, SCpnt->request.nr_sectors));
- SCpnt->cmnd[1] = (SCpnt->lun << 5) & 0xe0;
+ SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
+ ((SCpnt->lun << 5) & 0xe0) : 0;
if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
if (this_count > 0xffff)
@@ -424,7 +431,7 @@
static int sd_open(struct inode *inode, struct file *filp)
{
- int target;
+ int target, retval = -ENXIO;
Scsi_Device * SDev;
target = DEVICE_NR(inode->i_rdev);
@@ -448,24 +455,40 @@
while (rscsi_disks[target].device->busy)
barrier();
+ /*
+ * The following code can sleep.
+ * Module unloading must be prevented
+ */
+ SDev = rscsi_disks[target].device;
+ if (SDev->host->hostt->module)
+ __MOD_INC_USE_COUNT(SDev->host->hostt->module);
+ if (sd_template.module)
+ __MOD_INC_USE_COUNT(sd_template.module);
+ SDev->access_count++;
+
if (rscsi_disks[target].device->removable) {
+ SDev->allow_revalidate = 1;
check_disk_change(inode->i_rdev);
+ SDev->allow_revalidate = 0;
/*
* If the drive is empty, just let the open fail.
*/
- if (!rscsi_disks[target].ready)
- return -ENXIO;
+ if ((!rscsi_disks[target].ready) && !(filp->f_flags & O_NDELAY)) {
+ retval = -ENOMEDIUM;
+ goto error_out;
+ }
/*
* Similarly, if the device has the write protect tab set,
* have the open fail if the user expects to be able to write
* to the thing.
*/
- if ((rscsi_disks[target].write_prot) && (filp->f_mode & 2))
- return -EROFS;
+ if ((rscsi_disks[target].write_prot) && (filp->f_mode & 2)) {
+ retval = -EROFS;
+ goto error_out;
+ }
}
- SDev = rscsi_disks[target].device;
/*
* It is possible that the disk changing stuff resulted in the device
* being taken offline. If this is the case, report this to the user,
@@ -473,26 +496,31 @@
* the open actually succeeded.
*/
if (!SDev->online) {
- return -ENXIO;
+ goto error_out;
}
/*
* See if we are requesting a non-existent partition. Do this
* after checking for disk change.
*/
- if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0)
- return -ENXIO;
+ if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0) {
+ goto error_out;
+ }
if (SDev->removable)
- if (!SDev->access_count)
+ if (SDev->access_count==1)
if (scsi_block_when_processing_errors(SDev))
scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL);
- SDev->access_count++;
+
+ return 0;
+
+error_out:
+ SDev->access_count--;
if (SDev->host->hostt->module)
- __MOD_INC_USE_COUNT(SDev->host->hostt->module);
+ __MOD_DEC_USE_COUNT(SDev->host->hostt->module);
if (sd_template.module)
- __MOD_INC_USE_COUNT(sd_template.module);
- return 0;
+ __MOD_DEC_USE_COUNT(sd_template.module);
+ return retval;
}
static int sd_release(struct inode *inode, struct file *file)
@@ -746,7 +774,8 @@
while (retries < 3) {
cmd[0] = TEST_UNIT_READY;
- cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
+ cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ?
+ ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
memset((void *) &cmd[2], 0, 8);
SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0;
@@ -787,7 +816,8 @@
if (!spintime) {
printk("%s: Spinning up disk...", nbuff);
cmd[0] = START_STOP;
- cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
+ cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ?
+ ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
cmd[1] |= 1; /* Return immediately */
memset((void *) &cmd[2], 0, 8);
cmd[4] = 1; /* Start spin cycle */
@@ -820,7 +850,8 @@
retries = 3;
do {
cmd[0] = READ_CAPACITY;
- cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
+ cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ?
+ ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
memset((void *) &cmd[2], 0, 8);
memset((void *) buffer, 0, 8);
SRpnt->sr_cmd_len = 0;
@@ -977,7 +1008,8 @@
memset((void *) &cmd[0], 0, 8);
cmd[0] = MODE_SENSE;
- cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
+ cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ?
+ ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
cmd[2] = 0x3f; /* Get all pages */
cmd[4] = 8; /* But we only want the 8 byte header */
SRpnt->sr_cmd_len = 0;
@@ -1183,16 +1215,9 @@
static int sd_detect(Scsi_Device * SDp)
{
- char nbuff[6];
if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD)
return 0;
-
- sd_devname(sd_template.dev_noticed++, nbuff);
- printk("Detected scsi %sdisk %s at scsi%d, channel %d, id %d, lun %d\n",
- SDp->removable ? "removable " : "",
- nbuff,
- SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
-
+ sd_template.dev_noticed++;
return 1;
}
@@ -1201,6 +1226,7 @@
unsigned int devnum;
Scsi_Disk *dpnt;
int i;
+ char nbuff[6];
if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD)
return 0;
@@ -1224,10 +1250,15 @@
SD_GENDISK(i).de_arr[devnum] = SDp->de;
if (SDp->removable)
SD_GENDISK(i).flags[devnum] |= GENHD_FL_REMOVABLE;
+ sd_devname(i, nbuff);
+ printk("Attached scsi %sdisk %s at scsi%d, channel %d, id %d, lun %d\n",
+ SDp->removable ? "removable " : "",
+ nbuff, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
return 0;
}
#define DEVICE_BUSY rscsi_disks[target].device->busy
+#define ALLOW_REVALIDATE rscsi_disks[target].device->allow_revalidate
#define USAGE rscsi_disks[target].device->access_count
#define CAPACITY rscsi_disks[target].capacity
#define MAYBE_REINIT sd_init_onedisk(target)
@@ -1248,7 +1279,7 @@
target = DEVICE_NR(dev);
- if (DEVICE_BUSY || USAGE > maxusage) {
+ if (DEVICE_BUSY || (ALLOW_REVALIDATE == 0 && USAGE > maxusage)) {
printk("Device busy for revalidation (usage=%d)\n", USAGE);
return -EBUSY;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)