forked from pool/util-linux
124 lines
3.8 KiB
Diff
124 lines
3.8 KiB
Diff
mount: retry on ENOMEDIUM
|
|
|
|
From: Matthias Koenig <mkoenig@suse.de>
|
|
|
|
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@suse.de>
|
|
---
|
|
|
|
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;
|
|
}
|