diff -up autofs-5.0.2/include/automount.h.check-mtab-updated autofs-5.0.2/include/automount.h
--- autofs-5.0.2/include/automount.h.check-mtab-updated 2007-11-20 16:10:13.000000000 +0900
+++ autofs-5.0.2/include/automount.h 2007-11-20 16:10:36.000000000 +0900
@@ -78,6 +78,7 @@ int load_autofs4_module(void);
#define MOUNTED_LOCK _PATH_MOUNTED "~" /* mounts' lock file */
#define MTAB_NOTUPDATED 0x1000 /* mtab succeded but not updated */
#define NOT_MOUNTED 0x0100 /* path notmounted */
+#define MNT_FORCE_FAIL -1
#define _PROC_MOUNTS "/proc/mounts"
/* Constants for lookup modules */
diff -up autofs-5.0.2/modules/mount_bind.c.check-mtab-updated autofs-5.0.2/modules/mount_bind.c
--- autofs-5.0.2/modules/mount_bind.c.check-mtab-updated 2007-11-20 16:10:58.000000000 +0900
+++ autofs-5.0.2/modules/mount_bind.c 2007-11-20 16:11:49.000000000 +0900
@@ -147,7 +147,7 @@ int mount_mount(struct autofs_point *ap,
if ((!ap->ghost && name_len) || !existed)
rmdir_path(ap, fullpath, ap->dev);
- return 1;
+ return err;
} else {
debug(ap->logopt,
MODPREFIX "mounted %s type %s on %s",
diff -up autofs-5.0.2/modules/mount_nfs.c.check-mtab-updated autofs-5.0.2/modules/mount_nfs.c
--- autofs-5.0.2/modules/mount_nfs.c.check-mtab-updated 2007-11-20 16:11:08.000000000 +0900
+++ autofs-5.0.2/modules/mount_nfs.c 2007-11-20 16:12:44.000000000 +0900
@@ -233,6 +233,10 @@ int mount_mount(struct autofs_point *ap,
return 0;
}
+ /* Failed to update mtab, don't try any more */
+ if (err == MNT_FORCE_FAIL)
+ goto forced_fail;
+
/* No hostname, can't be NFS */
if (!this->name) {
this = this->next;
@@ -275,6 +279,7 @@ int mount_mount(struct autofs_point *ap,
this = this->next;
}
+forced_fail:
free_host_list(&hosts);
ap->ghost = save_ghost;
diff -up autofs-5.0.2/daemon/spawn.c.check-mtab-updated autofs-5.0.2/daemon/spawn.c
--- autofs-5.0.2/daemon/spawn.c.check-mtab-updated 2007-11-20 16:06:45.000000000 +0900
+++ autofs-5.0.2/daemon/spawn.c 2007-11-20 16:06:45.000000000 +0900
@@ -25,6 +25,7 @@
#include <time.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/mount.h>
#include "automount.h"
@@ -268,9 +269,11 @@ int spawn_mount(unsigned logopt, ...)
char **argv, **p;
char prog[] = PATH_MOUNT;
char arg0[] = PATH_MOUNT;
+ /* In case we need to use the fake option to mount */
+ char arg_fake[] = "-f";
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
- int ret;
+ int ret, printed = 0;
/* If we use mount locking we can't validate the location */
#ifdef ENABLE_MOUNT_LOCKING
@@ -283,7 +286,8 @@ int spawn_mount(unsigned logopt, ...)
for (argc = 1; va_arg(arg, char *); argc++);
va_end(arg);
- if (!(argv = alloca(sizeof(char *) * argc + 1)))
+ /* Alloc 1 extra slot in case we need to use the "-f" option */
+ if (!(argv = alloca(sizeof(char *) * argc + 2)))
return -1;
argv[0] = arg0;
@@ -304,11 +308,52 @@ int spawn_mount(unsigned logopt, ...)
while (retries--) {
ret = do_spawn(logopt, options, prog, (const char **) argv);
- if (ret & MTAB_NOTUPDATED)
+ if (ret & MTAB_NOTUPDATED) {
+ struct timespec tm = {3, 0};
+
+ /*
+ * If the mount succeeded but the mtab was not
+ * updated, then retry the mount with the -f (fake)
+ * option to just update the mtab.
+ */
+ if (!printed) {
+ debug(logopt, "mount failed with error code 16"
+ ", retrying with the -f option");
+ printed = 1;
+ }
+
+ /*
+ * Move the last two args so do_spawn() can find the
+ * mount target.
+ */
+ if (!argv[argc]) {
+ argv[argc + 1] = NULL;
+ argv[argc] = argv[argc - 1];
+ argv[argc - 1] = argv[argc - 2];
+ argv[argc - 2] = arg_fake;
+ }
+
+ nanosleep(&tm, NULL);
+
continue;
+ }
break;
}
+ /* This is not a fatal error */
+ if (ret == MTAB_NOTUPDATED) {
+ /*
+ * Version 5 requires that /etc/mtab be in sync with
+ * /proc/mounts. If we're unable to update matb after
+ * retrying then we have no choice but umount the mount
+ * and return a fail.
+ */
+ warn(logopt,
+ "Unable to update the mtab file, forcing mount fail!");
+ umount(argv[argc]);
+ ret = MNT_FORCE_FAIL;
+ }
+
return ret;
}
@@ -328,9 +373,11 @@ int spawn_bind_mount(unsigned logopt, ..
char prog[] = PATH_MOUNT;
char arg0[] = PATH_MOUNT;
char bind[] = "--bind";
+ /* In case we need to use the fake option to mount */
+ char arg_fake[] = "-f";
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
- int ret;
+ int ret, printed = 0;
/* If we use mount locking we can't validate the location */
#ifdef ENABLE_MOUNT_LOCKING
@@ -339,8 +386,12 @@ int spawn_bind_mount(unsigned logopt, ..
options = SPAWN_OPT_ACCESS;
#endif
+ /*
+ * Alloc 2 extra slots, one for the bind option and one in case
+ * we need to use the "-f" option
+ */
va_start(arg, logopt);
- for (argc = 1; va_arg(arg, char *); argc++);
+ for (argc = 2; va_arg(arg, char *); argc++);
va_end(arg);
if (!(argv = alloca(sizeof(char *) * argc + 2)))
@@ -356,11 +407,52 @@ int spawn_bind_mount(unsigned logopt, ..
while (retries--) {
ret = do_spawn(logopt, options, prog, (const char **) argv);
- if (ret & MTAB_NOTUPDATED)
+ if (ret & MTAB_NOTUPDATED) {
+ struct timespec tm = {3, 0};
+
+ /*
+ * If the mount succeeded but the mtab was not
+ * updated, then retry the mount with the -f (fake)
+ * option to just update the mtab.
+ */
+ if (!printed) {
+ debug(logopt, "mount failed with error code 16"
+ ", retrying with the -f option");
+ printed = 1;
+ }
+
+ /*
+ * Move the last two args so do_spawn() can find the
+ * mount target.
+ */
+ if (!argv[argc]) {
+ argv[argc + 1] = NULL;
+ argv[argc] = argv[argc - 1];
+ argv[argc - 1] = argv[argc - 2];
+ argv[argc - 2] = arg_fake;
+ }
+
+ nanosleep(&tm, NULL);
+
continue;
+ }
break;
}
+ /* This is not a fatal error */
+ if (ret == MTAB_NOTUPDATED) {
+ /*
+ * Version 5 requires that /etc/mtab be in sync with
+ * /proc/mounts. If we're unable to update matb after
+ * retrying then we have no choice but umount the mount
+ * and return a fail.
+ */
+ warn(logopt,
+ "Unable to update the mtab file, forcing mount fail!");
+ umount(argv[argc]);
+ ret = MNT_FORCE_FAIL;
+ }
+
return ret;
}
@@ -373,7 +465,7 @@ int spawn_umount(unsigned logopt, ...)
char arg0[] = PATH_UMOUNT;
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
- int ret;
+ int ret, printed = 0;
#ifdef ENABLE_MOUNT_LOCKING
options = SPAWN_OPT_LOCK;
@@ -397,9 +489,37 @@ int spawn_umount(unsigned logopt, ...)
while (retries--) {
ret = do_spawn(logopt, options, prog, (const char **) argv);
- if (ret & MTAB_NOTUPDATED)
- continue;
- break;
+ if (ret & MTAB_NOTUPDATED) {
+ /*
+ * If the mount succeeded but the mtab was not
+ * updated, then retry the umount just to update
+ * the mtab.
+ */
+ if (!printed) {
+ debug(logopt, "mount failed with error code 16"
+ ", retrying with the -f option");
+ printed = 1;
+ }
+ } else {
+ /*
+ * umount does not support the "fake" option. Thus,
+ * if we got a return value of MTAB_NOTUPDATED the
+ * first time, that means the umount actually
+ * succeeded. Then, a following umount will fail
+ * due to the fact that nothing was mounted on the
+ * mount point. So, report this as success.
+ */
+ if (retries < MTAB_LOCK_RETRIES - 1)
+ ret = 0;
+ break;
+ }
+ }
+
+ /* This is not a fatal error */
+ if (ret == MTAB_NOTUPDATED) {
+ warn(logopt, "Unable to update the mtab file, /proc/mounts "
+ "and /etc/mtab will differ");
+ ret = 0;
}
return ret;