(I've sent these patches before and gotten no reply.  Alan won't even
look at them until you do.  Help?  Please??)

I am using the below patches in a production kernel that needs to open
devices with removable media (/dev/sr# and /dev/sd[a-z]) even when the
media are missing.  This is of course what the O_NONBLOCK flag was
invented for.  But at least with the stock 2.2 kernel, O_NONBLOCK
doesn't work with SCSI devices.  (It does work with IDE devices.)

These patches make O_NONBLOCK work with SCSI devices.

The first patch is for SCSI disks; the second patch is for SCSI CDs.

------------------------------------------------------------------------
Index: drivers/scsi/sd.c
@@ -151,34 +151,41 @@ static int sd_open(struct inode * inode,
      * is being re-read.
      */
-
     while (rscsi_disks[target].device->busy)
         barrier();
-    if(rscsi_disks[target].device->removable) {
+
+    /*
+     * When opening removable disks, we check media...
+     * ... unless media don't matter, due to O_NONBLOCK.
+     */
+    if (rscsi_disks[target].device->removable
+        && !(filp->f_flags & O_NONBLOCK))
+    {
+        /*
+         * Note disk change and/or removal.
+         * Also try to read new partition table (if any).
+         */
        check_disk_change(inode->i_rdev);
 
-       /*
-        * If the drive is empty, just let the open fail.
-        */
-       if ( !rscsi_disks[target].ready )
-           return -ENXIO;
+        /*
+         * If the drive is empty, let the open fail.
+         */
+       if (rscsi_disks[target].ready)
+            return -ENXIO;
 
-       /*
-        * 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 the device has the write protect tab set,
+         * let the open fail if the user expects to be able to write.
+         */
+        if ( (rscsi_disks[target].write_prot) && (filp->f_mode & 2) )
+            return -EROFS;
     }
 
     /*
-     * 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, and don't pretend that
-     * the open actually succeeded.
+     * It is possible that the disk changing stuff (or something
+     * else?) resulted in the device being taken offline.
+     * If so, let the open fail.
      */
-    if( !rscsi_disks[target].device->online )
-    {
+    if (!rscsi_disks[target].device->online)
         return -ENXIO;
-    }
 
     /*
@@ -1069,5 +1076,4 @@ static int check_scsidisk_media_change(k
     int target;
     struct inode inode;
-    int flag = 0;
 
     target =  DEVICE_NR(full_dev);
@@ -1121,9 +1127,9 @@ static int check_scsidisk_media_change(k
      * struct and tested at open !  Daniel Roche ( [EMAIL PROTECTED] )
      */
-
     rscsi_disks[target].ready = 1;     /* FLOPTICAL */
 
     retval = rscsi_disks[target].device->changed;
-    if(!flag) rscsi_disks[target].device->changed = 0;
+    rscsi_disks[target].device->changed = 0;
+
     return retval;
 }
------------------------------------------------------------------------
Index: drivers/scsi/sr.h
@@ -29,5 +29,5 @@
        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        :1;                     /* (was needs_sector_size)             
+ */
        unsigned        ten:1;                  /* support ten byte commands           
 */
        unsigned        remap:1;                /* support remapping                   
 */

Index: drivers/scsi/sr.c
@@ -154,21 +154,17 @@ int sr_media_change(struct cdrom_device_
        retval = scsi_CDs[MINOR(cdi->dev)].device->changed;
        scsi_CDs[MINOR(cdi->dev)].device->changed = 0;
-       /* If the disk changed, the capacity will now be different,
-        * so we force a re-read of this information */
+
+       /*
+        * If the disk changed, the sector size and capacity may be
+        * different, so we force a re-read of this information.
+        */
        if (retval) {
+               /* discover new sector size */
+               get_sectorsize(MINOR(cdi->dev));
+
                /* check multisession offset etc */
                sr_cd_check(cdi);
-
-               /* 
-                * If the disk changed, the capacity will now be different,
-                * so we force a re-read of this information 
-                * Force 2048 for the sector size so that filesystems won't
-                * be trying to use something that is too small if the disc
-                * has changed.
-                */
-               scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
-
-               scsi_CDs[MINOR(cdi->dev)].sector_size = 2048;
        }
+
        return retval;
 }
@@ -384,6 +380,4 @@ static void rw_intr(Scsi_Cmnd * SCpnt)
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
 {
-       check_disk_change(cdi->dev);
-
        if (MINOR(cdi->dev) >= sr_template.dev_max
            || !scsi_CDs[MINOR(cdi->dev)].device) {
@@ -403,12 +397,4 @@ static int sr_open(struct cdrom_device_i
                __MOD_INC_USE_COUNT(sr_template.module);
 
-       /* If this device did not have media in the drive at boot time, then
-        * we would have been unable to get the sector size.  Check to see if
-        * this is the case, and try again.
-        */
-
-       if (scsi_CDs[MINOR(cdi->dev)].needs_sector_size)
-               get_sectorsize(MINOR(cdi->dev));
-
        return 0;
 }
@@ -894,5 +880,4 @@ void get_sectorsize(int i)
                scsi_CDs[i].capacity = 0x1fffff;
                scsi_CDs[i].sector_size = 2048;         /* A guess, just in case */
-               scsi_CDs[i].needs_sector_size = 1;
        } else {
 #if 0
@@ -927,14 +912,14 @@ void get_sectorsize(int i)
                               i, scsi_CDs[i].sector_size);
                        scsi_CDs[i].capacity = 0;
-                       scsi_CDs[i].needs_sector_size = 1;
+                       break;
                }
+       }
+
+       /*
+        * Add this so that we have the ability to correctly gauge
+        * what the device is capable of.
+        */
+       sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
 
-               /*
-                * Add this so that we have the ability to correctly gauge
-                * what the device is capable of.
-                */
-               scsi_CDs[i].needs_sector_size = 0;
-               sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
-       };
        scsi_free(buffer, 512);
 }
@@ -1021,5 +1006,5 @@ void get_capabilities(int i)
                        cdrom_number_of_slots(&(scsi_CDs[i].cdi));
        if (scsi_CDs[i].cdi.capacity <= 1)
-                /* not a changer */
+               /* not a changer */
                scsi_CDs[i].cdi.mask |= CDC_SELECT_DISC;
        /*else    I don't think it can close its tray
@@ -1149,5 +1134,4 @@ void sr_finish()
                scsi_CDs[i].capacity = 0x1fffff;
                scsi_CDs[i].sector_size = 2048;         /* A guess, just in case */
-               scsi_CDs[i].needs_sector_size = 1;
                scsi_CDs[i].device->changed = 1;        /* force recheck CD type */
 #if 0
------------------------------------------------------------------------

-- 
Chip Salzenberg              - a.k.a. -              <[EMAIL PROTECTED]>
"I wanted to play hopscotch with the impenetrable mystery of existence,
    but he stepped in a wormhole and had to go in early."  // MST3K

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]

Reply via email to