On Sun, 2006-08-27 at 15:52 +0800, Ian Kent wrote:
> On Fri, 25 Aug 2006, Ian Kent wrote:
> 
> > On Fri, 2006-08-25 at 14:22 +0100, Matt Bernstein wrote:
> > > At 14:09 +0100 Matt Bernstein wrote:
> > > 
> > > > At 19:18 +0800 Ian Kent wrote:
> > > >
> > > >> Could you try this patch please.
> > > >
> > > > Thanks.. now my messages are slightly different (though it still fails).
> > > >
> > > > Aug 25 14:07:19 laurel automount[17416]: attempting to mount entry 
> > > > /homes/mb
> > > > Aug 25 14:07:19 laurel automount[17416]: mount(nfs): nfs: mount failure 
> > > > :/home/cream/home71/mb on /homes/mb
> > > > Aug 25 14:07:19 laurel automount[17416]: failed to mount /homes/mb
> > > 
> > > Actually, this only happens when the target isn't already mounted. It 
> > > does 
> > > perform a bind mount if there's something to bind to. Now what we need to 
> > > do (I think) is tickle the target in case it's another automount point, a 
> > > la our-bad-patch-for-autofs4.
> > 
> > Shouldn't need to do that.
> > This my be due to changes in the lookup flags in the kernel over time.
> > I haven't reviewed that for some time now.
> 
> And that seems OK.
> 
> Can you try this patch in addition to the previous patch please.

There was a mistake in this patch.
Use this one instead please.

-- 

diff --git a/daemon/direct.c b/daemon/direct.c
index 9a1cd59..cfa13ad 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -273,8 +273,7 @@ static int unlink_mount_tree(struct auto
                        continue;
 
                if (strcmp(mnt->fs_type, "autofs"))
-                       rv = spawnll(log_debug,
-                            PATH_UMOUNT, PATH_UMOUNT, "-l", mnt->path, NULL);
+                       rv = spawn_umount(log_debug, "-l", mnt->path, NULL);
                else
                        rv = umount2(mnt->path, MNT_DETACH);
                if (rv == -1) {
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 38d0b7a..9ceb015 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -95,8 +95,7 @@ static int unlink_mount_tree(struct auto
                }
 
                if (strcmp(this->fs_type, "autofs"))
-                       rv = spawnll(log_debug,
-                           PATH_UMOUNT, PATH_UMOUNT, "-l", this->path, NULL);
+                       rv = spawn_umount(log_debug, "-l", this->path, NULL);
                else
                        rv = umount2(this->path, MNT_DETACH);
                if (rv == -1) {
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 7dc4a81..84df3b9 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -20,6 +20,7 @@ #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <dirent.h>
 #include <unistd.h>
 #include <time.h>
 #include <sys/wait.h>
@@ -27,9 +28,11 @@ #include <sys/stat.h>
 
 #include "automount.h"
 
-#ifdef ENABLE_MOUNT_LOCKING
 static pthread_mutex_t spawn_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
+
+#define SPAWN_OPT_NONE         0x0000
+#define SPAWN_OPT_LOCK         0x0001
+#define SPAWN_OPT_OPENDIR      0x0002
 
 inline void dump_core(void)
 {
@@ -83,26 +86,15 @@ void reset_signals(void)
 
 #define ERRBUFSIZ 2047         /* Max length of error string excl \0 */
 
-#ifdef ENABLE_MOUNT_LOCKING
-void spawn_unlock(void *arg)
-{
-       int *use_lock = (int *) arg;
-
-       if (*use_lock) {
-               if (pthread_mutex_unlock(&spawn_mutex))
-                       warn(LOGOPT_NONE, "failed to unlock spawn_mutex");
-       }
-       return;
-}
-#endif
-
-static int do_spawn(logger *log, int use_lock, const char *prog, const
char *const *argv)
+static int do_spawn(logger *log, unsigned int options, const char
*prog, const char *const *argv)
 {
        pid_t f;
        int status, pipefd[2];
        char errbuf[ERRBUFSIZ + 1], *p, *sp;
        int errp, errn;
        int cancel_state;
+       unsigned int use_lock = options & SPAWN_OPT_LOCK;
+       unsigned int use_opendir = options & SPAWN_OPT_OPENDIR;
        sigset_t allsigs, tmpsig, oldsig;
 
        if (pipe(pipefd))
@@ -113,16 +105,11 @@ static int do_spawn(logger *log, int use
        sigfillset(&allsigs);
        pthread_sigmask(SIG_BLOCK, &allsigs, &oldsig);
 
-#ifdef ENABLE_MOUNT_LOCKING
        if (use_lock) {
-               if (pthread_mutex_lock(&spawn_mutex)) {
-                       log(LOGOPT_ANY, "failed to lock spawn_mutex");
-                       pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
-                       pthread_setcancelstate(cancel_state, NULL);
-                       return -1;
-               }
+               status = pthread_mutex_lock(&spawn_mutex);
+               if (status)
+                       fatal(status);
        }
-#endif
 
        f = fork();
        if (f == 0) {
@@ -132,6 +119,26 @@ #endif
                dup2(pipefd[1], STDERR_FILENO);
                close(pipefd[1]);
 
+               /* Bind mount - check target exists */
+               if (use_opendir) {
+                       char **pargv = (char **) argv;
+                       int argc = 0;
+                       pid_t pgrp = getpgrp();
+                       DIR *dfd;
+
+                       /* what to mount must always be second last */
+                       while (*pargv++)
+                               argc++;
+                       argc -= 2;
+
+                       /* Set non-autofs program group to trigger mount */
+                       setpgrp();
+                       if ((dfd = opendir(argv[argc])) == NULL)
+                               _exit(errno);
+                       closedir(dfd);
+                       setpgid(0, pgrp);
+               }
+
                execv(prog, (char *const *) argv);
                _exit(255);     /* execv() failed */
        } else {
@@ -144,10 +151,12 @@ #endif
 
                if (f < 0) {
                        close(pipefd[0]);
+                       if (use_lock) {
+                               status = pthread_mutex_unlock(&spawn_mutex);
+                               if (status)
+                                       fatal(status);
+                       }
                        pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
-#ifdef ENABLE_MOUNT_LOCKING
-                       spawn_unlock(&use_lock);
-#endif
                        pthread_setcancelstate(cancel_state, NULL);
                        return -1;
                }
@@ -193,10 +202,12 @@ #endif
                if (waitpid(f, &status, 0) != f)
                        status = -1;    /* waitpid() failed */
 
+               if (use_lock) {
+                       status = pthread_mutex_unlock(&spawn_mutex);
+                       if (status)
+                               fatal(status);
+               }
                pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
-#ifdef ENABLE_MOUNT_LOCKING
-               spawn_unlock(&use_lock);
-#endif
                pthread_setcancelstate(cancel_state, NULL);
 
                return status;
@@ -205,7 +216,7 @@ #endif
 
 int spawnv(logger *log, const char *prog, const char *const *argv)
 {
-       return do_spawn(log, 0, prog, argv);
+       return do_spawn(log, SPAWN_OPT_NONE, prog, argv);
 }
 
 int spawnl(logger *log, const char *prog, ...)
@@ -226,28 +237,114 @@ int spawnl(logger *log, const char *prog
        while ((*p++ = va_arg(arg, char *)));
        va_end(arg);
 
-       return do_spawn(log, 0, prog, (const char **) argv);
+       return do_spawn(log, SPAWN_OPT_NONE, prog, (const char **) argv);
 }
 
+int spawn_mount(logger *log, ...)
+{
+       va_list arg;
+       int argc;
+       char **argv, **p;
+       char prog[] = PATH_MOUNT;
+       char arg0[] = PATH_MOUNT;
+       unsigned int options;
+
+       /* If we use mount locking we can't validate the location */
 #ifdef ENABLE_MOUNT_LOCKING
-int spawnll(logger *log, const char *prog, ...)
+       options = SPAWN_OPT_LOCK;
+#else
+       options = SPAWN_OPT_NONE;
+#endif
+
+       va_start(arg, log);
+       for (argc = 1; va_arg(arg, char *); argc++);
+       va_end(arg);
+
+       if (!(argv = alloca(sizeof(char *) * argc + 1)))
+               return -1;
+
+       argv[0] = arg0;
+
+       va_start(arg, log);
+       p = argv + 1;
+       while ((*p++ = va_arg(arg, char *)));
+       va_end(arg);
+
+       return do_spawn(log, options, prog, (const char **) argv);
+}
+
+/*
+ * For bind mounts that depend on the target being mounted (possibly
+ * itself an automount) we attempt to mount the target using an opendir
+ * call. For this to work the location must be the second last arg.
+ *
+ * NOTE: If mount locking is enabled this type of recursive mount
cannot
+ *      work.
+ */
+int spawn_bind_mount(logger *log, ...)
 {
        va_list arg;
        int argc;
        char **argv, **p;
+       char prog[] = PATH_MOUNT;
+       char arg0[] = PATH_MOUNT;
+       char bind[] = "--bind";
+       unsigned int options;
 
-       va_start(arg, prog);
+       /* If we use mount locking we can't validate the location */
+#ifdef ENABLE_MOUNT_LOCKING
+       options = SPAWN_OPT_LOCK;
+#else
+       options = SPAWN_OPT_OPENDIR;
+#endif
+
+       va_start(arg, log);
        for (argc = 1; va_arg(arg, char *); argc++);
        va_end(arg);
 
-       if (!(argv = alloca(sizeof(char *) * argc)))
+       if (!(argv = alloca(sizeof(char *) * argc + 2)))
                return -1;
 
-       va_start(arg, prog);
-       p = argv;
+       argv[0] = arg0;
+       argv[1] = bind;
+
+       va_start(arg, log);
+       p = argv + 2;
        while ((*p++ = va_arg(arg, char *)));
        va_end(arg);
 
-       return do_spawn(log, 1, prog, (const char **) argv);
+       return do_spawn(log, options, prog, (const char **) argv);
 }
+
+int spawn_umount(logger *log, ...)
+{
+       va_list arg;
+       int argc;
+       char **argv, **p;
+       char prog[] = PATH_UMOUNT;
+       char arg0[] = PATH_UMOUNT;
+       unsigned int options;
+
+#ifdef ENABLE_MOUNT_LOCKING
+       options = SPAWN_OPT_LOCK;
+#else
+       options = SPAWN_OPT_NONE;
 #endif
+
+       va_start(arg, log);
+       for (argc = 1; va_arg(arg, char *); argc++);
+       va_end(arg);
+
+       if (!(argv = alloca(sizeof(char *) * argc + 1)))
+               return -1;
+
+       argv[0] = arg0;
+
+       va_start(arg, log);
+       p = argv + 1;
+       while ((*p++ = va_arg(arg, char *)));
+       va_end(arg);
+
+       return do_spawn(log, options, prog, (const char **) argv);
+}
+
diff --git a/include/automount.h b/include/automount.h
index 1f4fc6b..9c2de00 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -195,12 +195,10 @@ inline void dump_core(void);
 int aquire_lock(void);
 void release_lock(void);
 int spawnl(logger *log, const char *prog, ...);
-#ifdef ENABLE_MOUNT_LOCKING
-int spawnll(logger *log, const char *prog, ...);
-#else
-#define spawnll        spawnl
-#endif
 int spawnv(logger *log, const char *prog, const char *const *argv);
+int spawn_mount(logger *log, ...);
+int spawn_bind_mount(logger *log, ...);
+int spawn_umount(logger *log, ...);
 void reset_signals(void);
 int do_mount(struct autofs_point *ap, const char *root, const char
*name,
             int name_len, const char *what, const char *fstype,
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
index b584250..fbbc515 100644
--- a/lib/parse_subs.c
+++ b/lib/parse_subs.c
@@ -304,9 +304,9 @@ int umount_ent(struct autofs_point *ap, 
         * and EBADSLT relates to CD changer not responding.
         */
        if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
-               rv = spawnll(log_debug, PATH_UMOUNT, PATH_UMOUNT, path, NULL);
+               rv = spawn_umount(log_debug, path, NULL);
        } else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
-               rv = spawnll(log_debug, PATH_UMOUNT, PATH_UMOUNT, path, NULL);
+               rv = spawn_umount(log_debug, path, NULL);
        }
 
        /* We are doing a forced shutcwdown down so unlink busy mounts */
@@ -324,7 +324,7 @@ int umount_ent(struct autofs_point *ap, 
 
                if (ap->state == ST_SHUTDOWN_FORCE) {
                        msg("forcing umount of %s", path);
-                       rv = spawnll(log_debug, PATH_UMOUNT, PATH_UMOUNT, "-l", 
path, NULL);
+                       rv = spawn_umount(log_debug, "-l", path, NULL);
                }
 
                /*
diff --git a/modules/mount_bind.c b/modules/mount_bind.c
index 96ca29b..1cdb1c6 100644
--- a/modules/mount_bind.c
+++ b/modules/mount_bind.c
@@ -56,9 +56,7 @@ int mount_init(void **context)
        if (lstat(tmp1, &st1) == -1)
                goto out;
 
-       err = spawnl(log_debug,
-                    PATH_MOUNT, PATH_MOUNT, "-n", "--bind", tmp1, tmp2, NULL);
-
+       err = spawn_mount(log_debug, "-n", "--bind", tmp1, tmp2, NULL);
        if (err == 0 &&
            lstat(tmp2, &st2) == 0 &&
            st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
@@ -67,8 +65,7 @@ int mount_init(void **context)
 
        debug(LOGOPT_NONE, MODPREFIX "bind_works = %d", bind_works);
 
-       spawnl(log_debug,
-              PATH_UMOUNT, PATH_UMOUNT, "-n", tmp2, NULL);
+       spawn_umount(log_debug, "-n", tmp2, NULL);
 
       out:
        rmdir(tmp2);
@@ -149,10 +146,8 @@ int mount_mount(struct autofs_point *ap,
                      "calling mount --bind " SLOPPY " -o %s %s %s",
                      options, what, fullpath);
 
-               err = spawnll(log_debug,
-                            PATH_MOUNT, PATH_MOUNT, "--bind",
-                            SLOPPYOPT "-o", options,
-                            what, fullpath, NULL);
+               err = spawn_bind_mount(log_debug,
+                            SLOPPYOPT "-o", options, what, fullpath, NULL);
 
                if (err) {
                        if (ap->type != LKP_INDIRECT)
diff --git a/modules/mount_changer.c b/modules/mount_changer.c
index eb29c8c..b817d36 100644
--- a/modules/mount_changer.c
+++ b/modules/mount_changer.c
@@ -80,8 +80,7 @@ int mount_mount(struct autofs_point *ap,
 
        debug(ap->logopt, MODPREFIX "calling umount %s", what);
 
-       err = spawnll(log_debug,
-                    PATH_UMOUNT, PATH_UMOUNT, what, NULL);
+       err = spawn_umount(log_debug, what, NULL);
        if (err) {
                error(ap->logopt,
                      MODPREFIX
@@ -116,16 +115,14 @@ int mount_mount(struct autofs_point *ap,
                      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
                      fstype, options, what, fullpath);
 
-               err = spawnll(log_debug,
-                            PATH_MOUNT, PATH_MOUNT, "-t", fstype,
+               err = spawn_mount(log_debug, "-t", fstype,
                             SLOPPYOPT "-o", options, what, fullpath, NULL);
        } else {
                debug(ap->logopt,
                      MODPREFIX "calling mount -t %s %s %s",
                      fstype, what, fullpath);
 
-               err = spawnll(log_debug, PATH_MOUNT, PATH_MOUNT,
-                            "-t", fstype, what, fullpath, NULL);
+               err = spawn_mount(log_debug, "-t", fstype, what, fullpath, 
NULL);
        }
 
        if (err) {
diff --git a/modules/mount_ext2.c b/modules/mount_ext2.c
index 7774adf..45f0615 100644
--- a/modules/mount_ext2.c
+++ b/modules/mount_ext2.c
@@ -132,16 +132,13 @@ #endif
                debug(ap->logopt,
                      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
                      fstype, options, what, fullpath);
-               err = spawnll(log_debug,
-                            PATH_MOUNT, PATH_MOUNT, "-t", fstype,
+               err = spawn_mount(log_debug, "-t", fstype,
                             SLOPPYOPT "-o", options, what, fullpath, NULL);
        } else {
                debug(ap->logopt,
                      MODPREFIX "calling mount -t %s %s %s",
                      fstype, what, fullpath);
-               err = spawnll(log_debug,
-                            PATH_MOUNT, PATH_MOUNT, "-t", fstype,
-                            what, fullpath, NULL);
+               err = spawn_mount(log_debug, "-t", fstype, what, fullpath, 
NULL);
        }
 
        if (err) {
diff --git a/modules/mount_generic.c b/modules/mount_generic.c
index ad726e7..1f43baa 100644
--- a/modules/mount_generic.c
+++ b/modules/mount_generic.c
@@ -93,15 +93,12 @@ int mount_mount(struct autofs_point *ap,
                      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
                      fstype, options, what, fullpath);
 
-               err = spawnll(log_debug,
-                            PATH_MOUNT, PATH_MOUNT, "-t", fstype,
+               err = spawn_mount(log_debug, "-t", fstype,
                             SLOPPYOPT "-o", options, what, fullpath, NULL);
        } else {
                debug(ap->logopt, MODPREFIX "calling mount -t %s %s %s",
                      fstype, what, fullpath);
-               err = spawnll(log_debug,
-                            PATH_MOUNT, PATH_MOUNT, "-t", fstype,
-                            what, fullpath, NULL);
+               err = spawn_mount(log_debug, "-t", fstype, what, fullpath, 
NULL);
        }
 
        if (err) {
diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index 8b4ddac..55e4f98 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -225,17 +225,15 @@ int mount_mount(struct autofs_point *ap,
                              MODPREFIX "calling mount -t nfs " SLOPPY 
                              "-o %s %s %s", nfsoptions, loc, fullpath);
 
-                       err = spawnll(log_debug,
-                                    PATH_MOUNT, PATH_MOUNT, "-t",
-                                    "nfs", SLOPPYOPT "-o", nfsoptions,
-                                    loc, fullpath, NULL);
+                       err = spawn_mount(log_debug,
+                                         "-t", "nfs", SLOPPYOPT "-o",
+                                         nfsoptions, loc, fullpath, NULL);
                } else {
                        debug(ap->logopt,
                              MODPREFIX "calling mount -t nfs %s %s",
                              loc, fullpath);
-                       err = spawnll(log_debug,
-                                    PATH_MOUNT, PATH_MOUNT, "-t",
-                                    "nfs", loc, fullpath, NULL);
+                       err = spawn_mount(log_debug,
+                                         "-t", "nfs", loc, fullpath, NULL);
                }
 
                if (!err) {

_______________________________________________
autofs mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/autofs

Reply via email to