Blob Blame History Raw
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;