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 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list