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

[master] Sleep if the kickstart file read fails (#537361)



If a read from a block device (like USB key) or a cdrom (USB cdrom) fails, sleep
a bit to give the device some time to initialize. Return status of the mount
command is checked so waiting occurs only if there is a reasonable chance that
the device might eventually come online. This required extending our existing
mounting methods to report the correct mount error code.
---
 isys/imount.c      |   40 ++++++++++++++++++++++++++++++++++++++--
 isys/imount.h      |   14 +++++++++++---
 loader/cdinstall.c |    8 ++++++++
 loader/kickstart.c |    8 ++++++++
 loader/method.c    |   12 ++++++++++--
 5 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/isys/imount.c b/isys/imount.c
index a62e223..46686c2 100644
--- a/isys/imount.c
+++ b/isys/imount.c
@@ -189,8 +189,29 @@ int mountCommandWrapper(int mode, char *dev, char *where, char *fs,
         free(device);
     }
 
-    if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status)))
-       return IMOUNT_ERR_OTHER;
+    if (!WIFEXITED(status))
+        return IMOUNT_ERR_OTHER;
+    else if ( (rc = WEXITSTATUS(status)) ) {
+        /* Refer to 'man mount' for the meaning of the error codes. */
+        switch (rc) {
+        case 1:
+            return IMOUNT_ERR_PERMISSIONS;
+        case 2:
+            return IMOUNT_ERR_SYSTEM;
+        case 4:
+            return IMOUNT_ERR_MOUNTINTERNAL;
+        case 8:
+            return IMOUNT_ERR_USERINTERRUPT;
+        case 16:
+            return IMOUNT_ERR_MTAB;
+        case 32:
+            return IMOUNT_ERR_MOUNTFAILURE;
+        case 64:
+            return IMOUNT_ERR_PARTIALSUCC;
+        default:
+            return IMOUNT_ERR_OTHER;
+        }
+    }
 
     return 0;
 }
@@ -230,6 +251,21 @@ int mkdirChain(char * origChain) {
     return 0;
 }
 
+/* Returns true iff it is possible that the mount command that have returned
+ * 'errno' might succeed at a later time (think e.g. not yet initialized USB
+ * device, etc.) */
+int mountMightSucceedLater(int mountRc)
+{
+    int rc;
+    switch (errno) {
+    case IMOUNT_ERR_MOUNTFAILURE:
+        rc = 1;
+    default:
+        rc = 0;
+    }
+    return rc;
+}
+
 static int mkdirIfNone(char * directory) {
     int rc, mkerr;
     char * chptr;
diff --git a/isys/imount.h b/isys/imount.h
index 95cca38..9fa6769 100644
--- a/isys/imount.h
+++ b/isys/imount.h
@@ -20,9 +20,16 @@
 #ifndef H_IMOUNT
 #define H_IMOUNT
 
-#define IMOUNT_ERR_ERRNO	1
-#define IMOUNT_ERR_OTHER	2
-#define IMOUNT_ERR_MODE		3
+#define IMOUNT_ERR_ERRNO          1
+#define IMOUNT_ERR_OTHER          2
+#define IMOUNT_ERR_MODE           3
+#define IMOUNT_ERR_PERMISSIONS    4
+#define IMOUNT_ERR_SYSTEM         5
+#define IMOUNT_ERR_MOUNTINTERNAL  6
+#define IMOUNT_ERR_USERINTERRUPT  7
+#define IMOUNT_ERR_MTAB           8
+#define IMOUNT_ERR_MOUNTFAILURE   9
+#define IMOUNT_ERR_PARTIALSUCC    10
 
 #include <sys/mount.h>		/* for umount() */
 
@@ -36,5 +43,6 @@
 int doPwMount(char *dev, char *where, char *fs, char *options, char **err);
 int doPwUmount(char *where, char **err);
 int mkdirChain(char * origChain);
+int mountMightSucceedLater(int mountRc);
 
 #endif
diff --git a/loader/cdinstall.c b/loader/cdinstall.c
index d74396e..cc39691 100644
--- a/loader/cdinstall.c
+++ b/loader/cdinstall.c
@@ -490,6 +490,14 @@ int kickstartFromCD(char *kssrc) {
     logMessage(INFO, "getting kickstart file from first CDROM");
 
     devices = getDevices(DEVICE_CDROM);
+    /* usb can take some time to settle, even with the various hacks we
+     * have in place.  some systems use portable USB CD-ROM drives, try to
+     * make sure there really isn't one before bailing */
+    for (i = 0; !devices && i < 10; ++i) {
+        logMessage(INFO, "sleeping to wait for a USB CD-ROM");
+        sleep(2);
+        devices = getDevices(DEVICE_CDROM);
+    }
     if (!devices) {
         logMessage(ERROR, "No CDROM devices found!");
         return 1;
diff --git a/loader/kickstart.c b/loader/kickstart.c
index b92c6da..cbd26b3 100644
--- a/loader/kickstart.c
+++ b/loader/kickstart.c
@@ -252,6 +252,14 @@ int kickstartFromRemovable(char *kssrc) {
 
     logMessage(INFO, "doing kickstart from removable media");
     devices = getDevices(DEVICE_DISK);
+    /* usb can take some time to settle, even with the various hacks we
+     * have in place. some systems use portable USB CD-ROM drives, try to
+     * make sure there really isn't one before bailing. */
+    for (i = 0; !devices && i < 10; ++i) {
+        logMessage(INFO, "sleeping to wait for a USB disk");
+        sleep(2);
+        devices = getDevices(DEVICE_DISK);
+    }
     if (!devices) {
         logMessage(ERROR, "no disks");
         return 1;
diff --git a/loader/method.c b/loader/method.c
index ebfe557..12a2fa8 100644
--- a/loader/method.c
+++ b/loader/method.c
@@ -466,12 +466,20 @@ int copyFileAndLoopbackMount(int fd, char * dest, char * device, char * mntpoint
       3 - file named path not there
 */
 int getFileFromBlockDevice(char *device, char *path, char * dest) {
-    int rc;
+    int rc, i;
     char file[4096];
 
     logMessage(INFO, "getFileFromBlockDevice(%s, %s)", device, path);
 
-    if (doPwMount(device, "/tmp/mnt", "auto", "ro", NULL)) {
+    /* some USB thumb drives and hard drives are slow to initialize */
+    /* retry up to 5 times or 31 seconds */
+    rc = doPwMount(device, "/tmp/mnt", "auto", "ro", NULL);
+    for (i = 0; mountMightSucceedLater(rc) && i < 5; ++i) {
+        logMessage(INFO, "sleeping to wait for USB storage devices");
+        sleep(1 << i);
+        rc = doPwMount(device, "/tmp/mnt", "auto", "ro", NULL);
+    }
+    if (rc) {
         logMessage(ERROR, "failed to mount /dev/%s: %m", device);
         return 2;
     }
-- 
1.6.2.5


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