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; }