[PATCH] mount: retry on ENOMEDIUM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Due to a change in kernel behaviour when opening CDROM devices,
we need to retry the open/mount call when ENOMEDIUM is returned.

Explanation from Tejun Heo:
Okay, the difference is from the addition of cdrom_get_media_event()
call to both sr_drive_status() and ide_cdrom_drive_status().
Previously, the cdrom driver can't differentiate between tray closed
w/ no media and tray open and always returned tray open, which
triggers close and retry in the open logic which probably have delayed
things enough to get the media recognized.

Now the cdrom driver can discern between tray closed w/o media and
device not ready for other reasons and returns -ENOMEDIUM on the
former.  This is all good and dandy but the problem seems that some
drives report no media right after the tray is closed but it hasn't
properly detected the media yet.

It seems the only way to work around the problem is via sensible
retries (e.g.  try three times 5 secs apart) and I don't think we can
add that type of retry logic into cdrom open path.  Please note that
the previous logic wasn't water proof.  Some drives can take longer to
recognize the media is there and could have failed the in-kernel retry
too.  Also, reading the media can take quite some time and during that
period the drive reports media present but device not ready.  The
driver will retry the command (e.g. READ TOC for open) five times but
all of them can fail w/ EMEDIUMTYPE.

Signed-off-by: Matthias Koenig <mkoenig@xxxxxxx>
---

 mount/fsprobe_volumeid.c |   15 +++++++++++++--
 mount/mount.c            |   11 +++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/mount/fsprobe_volumeid.c b/mount/fsprobe_volumeid.c
index 7c98dc6..1ef788c 100644
--- a/mount/fsprobe_volumeid.c
+++ b/mount/fsprobe_volumeid.c
@@ -3,6 +3,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <stddef.h>
+#include <errno.h>
 #include <sys/mount.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
@@ -15,6 +16,8 @@
 #include "pathnames.h"
 #include "sundries.h"
 
+#define MAX_RETRIES 5
+
 enum probe_type {
 	VOLUME_ID_NONE,
 	VOLUME_ID_LABEL,
@@ -30,10 +33,18 @@ static char
 	struct volume_id *id;
 	const char *val;
 	char *value = NULL;
+	int retries = 0;
 
+retry:
 	fd = open(device, O_RDONLY);
-	if (fd < 0)
-		return NULL;
+	if (fd < 0) {
+		if (errno == ENOMEDIUM && retries < MAX_RETRIES) {
+			++retries;
+			sleep(3);
+			goto retry;
+		} else
+			return NULL;
+	}
 
 	id = volume_id_open_fd(fd);
 	if (!id) {
diff --git a/mount/mount.c b/mount/mount.c
index bed792d..5d50bca 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -1061,6 +1061,7 @@ cdrom_setspeed(const char *spec) {
 static int
 try_mount_one (const char *spec0, const char *node0, const char *types0,
 	       const char *opts0, int freq, int pass, int ro) {
+#define MAX_RETRIES 5
   int res = 0, status = 0, special = 0;
   int mnt5_res = 0;		/* only for gcc */
   int mnt_err;
@@ -1072,6 +1073,7 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
   int loop = 0;
   const char *loopdev = 0, *loopfile = 0;
   struct stat statbuf;
+  int retries = 0;	/* Nr of retries for mount in case of ENOMEDIUM */
 
   /* copies for freeing on exit */
   const char *opts1, *spec1, *node1, *types1, *extra_opts1;
@@ -1134,6 +1136,7 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
       goto out;
   }
 
+mount_retry:
   block_signals (SIG_BLOCK);
 
   if (!fake) {
@@ -1363,6 +1366,14 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
       }
       break;
     }
+    case ENOMEDIUM:
+      if (retries < MAX_RETRIES) {
+              ++retries;
+              sleep(3);
+              goto mount_retry;
+      }
+      error(_("mount: No medium found on %s"), spec);
+      break;
     default:
       error ("mount: %s", strerror (mnt_err)); break;
     }

--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux