[8964] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

[PATCH] O_NONBLOCK and SCSI removables ... please respond

daemon@ATHENA.MIT.EDU (Chip Salzenberg)
Fri Jun 9 02:26:04 2000

Date:	Thu, 8 Jun 2000 22:15:53 -0700
From:	Chip Salzenberg <chip@valinux.com>
To:	Eric Youngdale <eric@andante.org>
Cc:	linux-scsi@vger.rutgers.edu
Message-ID: <20000608221553.J453@perlsupport.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

(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 ( dan@lectra.fr )
      */
-
     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. -              <chip@valinux.com>
"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 majordomo@vger.rutgers.edu

home help back first fref pref prev next nref lref last post