[Debburn-devel] handling device opening failures

Eduard Bloch edi at gmx.de
Sun Oct 1 14:43:28 UTC 2006


#include <hallo.h>

Hi, it looks like myprevious message has not come trough, so I resend it
directly to the list, see below. I intend to apply this patch RSN. The
idea behind it is simple:

 - don't stop scanning when access is not permitted (errno=EACCES or
   EPERM)
 - retry only on EBUSY and reduce the number of efforts.


> #include <hallo.h>
> * Graham [Sat, Sep 30 2006, 01:16:46PM]:
> > Package: wodim
> > Version: 5:1.0~pre4-1.1
> > 
> > Writing a CD fails on my system. It looks like another problem caused
> > by cdrecord trying to open devices that it doesn't need to; see also
> > my bug report #370603, which covers the "-scanbus" case.
> 
> That was a different case. "-scanbus" had no option to skip busy/failed
> devices. "wodim" should work in that case and just skip the unuseable
> devices.

Ok, Graham is right it was not a big deal to reproduce it. The current
code does inded break when a device could not be opened because of
permission problems when libscg scans (to build its list of "intuitive"
SCSI addresses). We had already two cludges to work around this problems,
one was from Andreas Metzler to not scan over all devices when the user
already specified a device name, and another from me to stop looping
forever when exclusiv open fails. However, the last part was only used
conditionaly for atapi devices. With SCSI (eg. a mixture of usb-attached
harddisks and external recorder which I just used), it fails: -scanbus
runs well (because of the endless looping prevention) but opening fails.

Now, I rewrote the code a bit more and ask for comments. It consolidates
the previous workarounds. I consider adding it to the stable branch RSN,
most likely for pre5.

Eduard.

-- 
<Getty> HA! Ich habs <klatsch> Ich Idiot
-------------- next part --------------
Index: libscg/scsi-linux-sg.c
===================================================================
--- libscg/scsi-linux-sg.c	(Revision 351)
+++ libscg/scsi-linux-sg.c	(Arbeitskopie)
@@ -242,25 +242,21 @@
 #endif
 LOCAL	void	sg_settimeout	__PR((int f, int timeout));
 
-int    sg_open_excl    __PR((char *device, int mode, int quickAndQuiet));
+int    sg_open_excl    __PR((char *device, int mode));
 
 int
-sg_open_excl(device, mode, quickAndQuiet)
+sg_open_excl(device, mode)
        char    *device;
        int     mode;
-       int quickAndQuiet;
 {
        int f;
        int i;
        f = open(device, mode|O_EXCL);
-       if(!quickAndQuiet)
-          for (i = 0; (i < 10) && (f == -1 && (errno == EACCES || errno == EBUSY)); i++) {
-             fprintf(stderr, "Error trying to open %s exclusively (%s)... retrying in 1 second.\n", device, strerror(errno));
-             usleep(1000000 + 100000.0 * rand()/(RAND_MAX+1.0));
-             f = open(device, mode|O_EXCL);
-          }
-       if (f == -1 && errno != EACCES && errno != EBUSY) {
-           f = open(device, mode);
+       // try to reopen locked/busy devices up to five times
+       for (i = 0; (i < 5) && (f == -1 && errno == EBUSY); i++) {
+	       fprintf(stderr, "Error trying to open %s exclusively (%s)... %s\n", device, strerror(errno), (i<5)?"retrying in 1 second.":"giving up.");
+	       usleep(1000000 + 100000.0 * rand()/(RAND_MAX+1.0));
+	       f = open(device, mode|O_EXCL);
        }
        return f;
 }
@@ -448,7 +444,7 @@
 	if (use_ata) for (i=2*busno+tgt >= 0 ? 2*busno+tgt:0; i <= 25; i++) {
 		js_snprintf(devname, sizeof (devname), "/dev/hd%c", i+'a');
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK, 1);
+		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
 		if (f < 0) {
 			/*
 			 * Set up error string but let us clear it later
@@ -489,7 +485,7 @@
 	if (nopen == 0) for (i = 0; i < 32; i++) {
 		js_snprintf(devname, sizeof (devname), "/dev/sg%d", i);
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK, 0);
+		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
 		if (f < 0) {
 			/*
 			 * Set up error string but let us clear it later
@@ -498,6 +494,8 @@
 			if (scgp->errstr)
 				js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 							"Cannot open '/dev/sg*'");
+			if(errno == EACCES || errno==EPERM)
+				continue;
 			if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
 				if (scgp->errstr)
 					js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
@@ -518,7 +516,7 @@
 	if (nopen == 0) for (i = 0; i <= 25; i++) {
 		js_snprintf(devname, sizeof (devname), "/dev/sg%c", i+'a');
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK, 0);
+		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
 		if (f < 0) {
 			/*
 			 * Set up error string but let us clear it later
@@ -527,6 +525,8 @@
 			if (scgp->errstr)
 				js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 							"Cannot open '/dev/sg*'");
+			if(errno == EACCES || errno==EPERM)
+				continue;
 			if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
 				if (scgp->errstr)
 					js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
@@ -570,7 +570,7 @@
 			 */
 		}
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(device, O_RDWR | O_NONBLOCK, 0);
+		f = sg_open_excl(device, O_RDWR | O_NONBLOCK);
 /*		if (f < 0 && errno == ENOENT)*/
 /*			goto openpg;*/
 


More information about the Debburn-devel mailing list