Ok... Yet another round of fixes for smbmount and autofs.
authorMichael Warfield <mhw@samba.org>
Sun, 31 Jan 1999 21:28:55 +0000 (21:28 +0000)
committerMichael Warfield <mhw@samba.org>
Sun, 31 Jan 1999 21:28:55 +0000 (21:28 +0000)
1)  The earlier fix for the smbmount race conditions broke the PID
registration with smbfs.  That fix has been backed out and
replaced by a signalling convention from the child smbmount
process back to the parent telling the parent when it is safe
to exit.

2)  Fixing all of this uncovered a NASTY deadly embrace between smbmount,
smbmnt, and autofs.  This was caused by the setsid call in the
daemon code.  The smbmnt process no longer was registered as
"magic" because it was no longer in the autofs process group.
Many many kudos and thanks to H Peter Anvin for giving me the
clue to solving this agravating puzzle.  The setsid was moved
down the where the child signals the parent and a warn left in
its place in the daemonize code.

3)  Fixed (actually worked around with a BUTT UGLY HACK) a problem with
SMB_GET_MOUNTPID in smbumount.c.  The smb_fs.h header file has
the parameter to this ioctl defined as a uid_t.  Unfortunately
that's a 32 bit quantity under glibc and it's currently a 16 bit
quantity in kernel space.  Undefined the macro and redefined
it with a parameter of __kernel_uid_t.  That should keep us
out of trouble till I can have someone fix smb_fs.h in the
kernel sources...

source/client/smbmount.c
source/client/smbumount.c

index 2cfd166688eba34f3d5a472fa8e711987950dbbb..3c2d2074986ee61e48bf3d7fb9ca160da1dda0e0 100644 (file)
@@ -38,7 +38,7 @@ static struct smb_conn_opt conn_options;
 #endif
 
 /* Uncomment this to allow debug the smbmount daemon */
 #endif
 
 /* Uncomment this to allow debug the smbmount daemon */
-#define SMBFS_DEBUG 1
+/* #define SMBFS_DEBUG 1 */
 
 pstring cur_dir = "\\";
 pstring cd_path = "";
 
 pstring cur_dir = "\\";
 pstring cd_path = "";
@@ -71,7 +71,6 @@ extern int name_type;
 extern int max_protocol;
 int port = SMB_PORT;
 
 extern int max_protocol;
 int port = SMB_PORT;
 
-
 time_t newer_than = 0;
 int archive_level = 0;
 
 time_t newer_than = 0;
 int archive_level = 0;
 
@@ -181,20 +180,51 @@ static BOOL chkpath(char *path,BOOL report)
   return(CVAL(inbuf,smb_rcls) == 0);
 }
 
   return(CVAL(inbuf,smb_rcls) == 0);
 }
 
+static void
+exit_parent( int sig )
+{
+       /* parent simply exits when child says go... */
+       exit(0);
+}
+
 static void
 daemonize(void)
 {
 static void
 daemonize(void)
 {
-       int i;
-       if ((i = fork()) < 0)
+       int j, status;
+       pid_t child_pid;
+
+       signal( SIGTERM, exit_parent );
+
+       if ((child_pid = fork()) < 0)
        {
                DEBUG(0, ("could not fork\n"));
        }
        {
                DEBUG(0, ("could not fork\n"));
        }
-       if (i > 0)
+       if (child_pid > 0)
        {
        {
-               /* parent simply exits */
-               exit(0);
+               while( 1 ) {
+                       j = waitpid( child_pid, &status, 0 );
+                       if( j < 0 ) {
+                               if( EINTR == errno ) {
+                                       continue;
+                               }
+                               status = errno;
+                       }
+                       break;
+               }
+               /* If we get here - the child exited with some error status */
+               exit(status);
        }
        }
-       setsid();
+       /* Programmers Note:
+               Danger Will Robinson!  Danger!
+
+               There use to be a call to setsid() here.  This does no
+               harm to normal mount operations, but it broke automounting.
+               The setsid call has been moved to just before the child
+               sends the SIGTERM to the parent.  All of our deadly embrace
+               conditions with autofs will have been cleared by then...
+               -mhw-
+       */
+       signal( SIGTERM, SIG_DFL );
        chdir("/");
 }
 
        chdir("/");
 }
 
@@ -255,7 +285,8 @@ static void
 send_fs_socket(char *mount_point, char *inbuf, char *outbuf)
 {
        int fd, closed = 0, res = 1;
 send_fs_socket(char *mount_point, char *inbuf, char *outbuf)
 {
        int fd, closed = 0, res = 1;
-       int first_time = 1;
+
+       pid_t parentpid = getppid();
 
        while (1)
        {
 
        while (1)
        {
@@ -278,6 +309,15 @@ send_fs_socket(char *mount_point, char *inbuf, char *outbuf)
                        DEBUG(0, ("smbmount: ioctl failed, res=%d\n", res));
                }
 
                        DEBUG(0, ("smbmount: ioctl failed, res=%d\n", res));
                }
 
+               if( parentpid ) {
+                       /* Ok...  We are going to kill the parent.  Now
+                               is the time to break the process group... */
+                       setsid();
+                       /* Send a signal to the parent to terminate */
+                       kill( parentpid, SIGTERM );
+                       parentpid = 0;
+               }
+
                close_sockets();
                close(fd);
                /*
                close_sockets();
                close(fd);
                /*
@@ -291,15 +331,6 @@ send_fs_socket(char *mount_point, char *inbuf, char *outbuf)
                }
 #endif
 
                }
 #endif
 
-               if( first_time ) {
-       /*
-        * Create the background process after trying the mount.
-        * to avoid race conditions with automount and other processes.
-        */
-                       first_time = 0;
-                       daemonize();
-               }
-
                /*
                 * Wait for a signal from smbfs ...
                 */
                /*
                 * Wait for a signal from smbfs ...
                 */
@@ -368,6 +399,12 @@ static void cmd_mount(char *inbuf,char *outbuf)
 
        DEBUG(3, ("mount command: %s\n", mount_command));
 
 
        DEBUG(3, ("mount command: %s\n", mount_command));
 
+       /*
+               Set up to return as a daemon child and wait in the parent
+               until the child say it's ready...
+       */
+       daemonize();
+
        if ((retval = system(mount_command)) != 0)
        {
                DEBUG(0,("mount failed\n"));
        if ((retval = system(mount_command)) != 0)
        {
                DEBUG(0,("mount failed\n"));
index 5e072274c953875e56b4f74ccd33dd55db26db56..84188542e59f4bc7ad6c13bf3953fe542e58b0e0 100644 (file)
 #include <linux/smb_mount.h>
 #include <linux/smb_fs.h>
 
 #include <linux/smb_mount.h>
 #include <linux/smb_fs.h>
 
+/* This is a (hopefully) temporary hack due to the fact that
+       sizeof( uid_t ) != sizeof( __kernel_uid_t ) under glibc.
+       This may change in the future and smb.h may get fixed in the
+       future.  In the mean time, it's ugly hack time - get over it.
+*/
+#undef SMB_IOC_GETMOUNTUID
+#define        SMB_IOC_GETMOUNTUID             _IOR('u', 1, __kernel_uid_t)
+
 static char *progname;
 
 static void
 static char *progname;
 
 static void