Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 226

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

diff -up autofs-5.0.1/daemon/spawn.c.check-mtab-updated autofs-5.0.1/daemon/spawn.c
--- autofs-5.0.1/daemon/spawn.c.check-mtab-updated	2007-10-30 16:38:03.000000000 +0900
+++ autofs-5.0.1/daemon/spawn.c	2007-10-30 16:47:36.000000000 +0900
@@ -34,6 +34,8 @@ static pthread_mutex_t spawn_mutex = PTH
 #define SPAWN_OPT_LOCK		0x0001
 #define SPAWN_OPT_ACCESS	0x0002
 
+#define MTAB_LOCK_RETRIES	3
+
 inline void dump_core(void)
 {
 	sigset_t segv;
@@ -266,7 +268,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, printed = 0;
 
 	/* If we use mount locking we can't validate the location */
 #ifdef ENABLE_MOUNT_LOCKING
@@ -279,7 +285,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;
@@ -289,7 +296,43 @@ int spawn_mount(unsigned logopt, ...)
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
-	return do_spawn(logopt, options, prog, (const char **) argv);
+	while (retries--) {
+		ret = do_spawn(logopt, options, prog, (const char **) argv);
+		if (ret & MTAB_NOTUPDATED) {
+			/*
+			 * 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;
+			}
+			continue;
+		}
+		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;
 }
 
 /*
@@ -308,7 +351,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, printed = 0;
 
 	/* If we use mount locking we can't validate the location */
 #ifdef ENABLE_MOUNT_LOCKING
@@ -317,8 +364,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)))
@@ -332,7 +383,43 @@ int spawn_bind_mount(unsigned logopt, ..
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
-	return do_spawn(logopt, options, prog, (const char **) argv);
+	while (retries--) {
+		ret = do_spawn(logopt, options, prog, (const char **) argv);
+		if (ret & MTAB_NOTUPDATED) {
+			/*
+			 * 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;
+			}
+			continue;
+		}
+		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;
 }
 
 int spawn_umount(unsigned logopt, ...)
@@ -343,6 +430,8 @@ int spawn_umount(unsigned logopt, ...)
 	char prog[] = PATH_UMOUNT;
 	char arg0[] = PATH_UMOUNT;
 	unsigned int options;
+	unsigned int retries = MTAB_LOCK_RETRIES;
+	int ret, printed = 0;
 
 #ifdef ENABLE_MOUNT_LOCKING
 	options = SPAWN_OPT_LOCK;
@@ -364,6 +453,41 @@ int spawn_umount(unsigned logopt, ...)
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
-	return do_spawn(logopt, options, prog, (const char **) argv);
+	while (retries--) {
+		ret = do_spawn(logopt, options, prog, (const char **) argv);
+		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;
 }