]> Zhao Yanbai Git Server - minix.git/commitdiff
Added a hack to start binaries from the boot image only. In particular, setting
authorThomas Veerman <thomas@minix3.org>
Tue, 18 Aug 2009 11:36:01 +0000 (11:36 +0000)
committerThomas Veerman <thomas@minix3.org>
Tue, 18 Aug 2009 11:36:01 +0000 (11:36 +0000)
bin_img=1 in the boot monitor will make sure that during the boot procedure the
mfs binary that is part of the boot image is the only binary that is used to
mount partitions. This is useful when for some reason the mfs binary on disk
malfunctions, rendering Minix unable to boot. By setting bin_img=1, the binary
on disk is ignored and the binary in the boot image is used instead.

- 'service' now accepts an additional flag -r. -r implies -c. -r instructs RS
  to first look in memory if the binary has already been copied to memory and
  execute that version, instead of loading the binary from disk. For example,
  the first time a MFS is being started it is copied (-c) to memory and
  executed from there. The second time MFS is being started this way, RS will
  look in memory for a previously copied MFS binary and reuse it if it exists.
- The mount and newroot commands now accept an additional flag -i, which
  instructs them to set the MS_REUSE flag in the mount flags.
- The mount system call now supports the MS_REUSE flag and invokes 'service'
  with the -r flag when MS_REUSE is set.
- /etc/rc and the rc script that's included in the boot image check for the
  existence of the bin_img flag in the boot monitor, and invoke mount and
  newroot with the -i flag accordingly.

commands/simple/mount.c
commands/simple/newroot.c
drivers/memory/ramdisk/rc
etc/rc
include/minix/rs.h
lib/other/_mount.c
servers/rs/manager.c
servers/rs/service.c

index 911407bf3580181f689b24e6e092438389229304..f89d06875a1fc5447d0b14d286bc1173c4884972 100755 (executable)
@@ -6,8 +6,8 @@
 #include <stdlib.h>
 #include <dirent.h>
 #include <string.h>
-#include <unistd.h>
 #include <sys/mount.h>
+#include <unistd.h>
 #include <fcntl.h>
 #include <minix/config.h>
 #include <minix/const.h>
@@ -31,12 +31,12 @@ int main(argc, argv)
 int argc;
 char *argv[];
 {
-  int i, ro, swap, n, v;
+  int i, swap, n, v, mountflags;
   char **ap, *vs, *opt, *err, *type, *args;
   char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
 
   if (argc == 1) list();       /* just list /etc/mtab */
-  ro = 0;
+  mountflags = 0;
   swap = 0;
   type = NULL;
   args = NULL;
@@ -45,11 +45,12 @@ char *argv[];
        if (argv[i][0] == '-') {
                opt = argv[i]+1;
                while (*opt != 0) switch (*opt++) {
-               case 'r':       ro = 1;         break;
-               case 's':       swap = 1;       break;
+               case 'r':       mountflags |= MS_RDONLY;        break;
+               case 's':       swap = 1;                       break;
                case 't':       if (++i == argc) usage();
                                type = argv[i];
                                break;
+               case 'i':       mountflags |= MS_REUSE;         break;                
                case 'o':       if (++i == argc) usage();
                                args = argv[i];
                                break;
@@ -62,7 +63,7 @@ char *argv[];
   *ap = NULL;
   argc = (ap - argv);
 
-  if (ro && swap) usage();
+  if (mountflags & MS_RDONLY && swap) usage();
 
   if (swap) {
        if (argc != 2) usage();
@@ -71,7 +72,7 @@ char *argv[];
        tell(" is swapspace\n");
   } else {
        if (argc != 3) usage();
-       if (mount(argv[1], argv[2], ro, type, args) < 0) {
+       if (mount(argv[1], argv[2], mountflags, type, args) < 0) {
                err = strerror(errno);
                std_err("mount: Can't mount ");
                std_err(argv[1]);
@@ -85,7 +86,7 @@ char *argv[];
        /* The mount has completed successfully. Tell the user. */
        tell(argv[1]);
        tell(" is read-");
-       tell(ro ? "only" : "write");
+       tell(mountflags & MS_RDONLY ? "only" : "write");
        tell(" mounted on ");
        tell(argv[2]);
        tell("\n");
@@ -127,7 +128,8 @@ char *argv[];
                        vs = "-";
        }
   }
-  n = put_mtab_entry(argv[1], swap ? "swap" : argv[2], vs, (ro ? "ro" : "rw") );
+  n = put_mtab_entry(argv[1], swap ? "swap" : argv[2], vs,
+                    (mountflags & MS_RDONLY ? "ro" : "rw") );
   if (n < 0) {
        std_err("mount: /etc/mtab has grown too large\n");
        exit(1);
index 0fa1fd77e3c936fc307d3aaebbd6b339706e2fbf..e6ea8cc27d399e0b707de8f276c167ed706d6e9c 100644 (file)
@@ -10,22 +10,36 @@ Replace the current root with a new one
 #include <string.h>
 #include <sys/mount.h>
 
+void usage(void) {
+       fprintf(stderr, "Usage: newroot [-i] <block-special>\n");
+       fprintf(stderr, "-i: copy mfs binary from boot image to memory\n");
+       exit(1);        
+}
+
 int main(int argc, char *argv[])
 {
        int r;
        char *dev;
+       int mountflags;
 
-       if (argc != 2)
-       {
-               fprintf(stderr, "Usage: newroot <block-special>\n");
-               exit(1);
+       r = 0;
+       mountflags = 0; /* !read-only */
+       
+       if (argc != 2 && argc != 3) usage();
+       if(argc == 2) {
+               dev = argv[1];
+       } else if(argc == 3) {
+               /* -i flag was supposedly entered. Verify.*/            
+               if(strcmp(argv[1], "-i") != 0) usage();
+               mountflags |= MS_REUSE;
+               dev = argv[2];
        }
-       dev= argv[1];
-       r= mount(dev, "/", 0 /* !ro */, NULL, NULL);
-       if (r != 0)
-       {
-               fprintf(stderr, "newroot: mount failed: %s\n", strerror(errno));
+       
+       r = mount(dev, "/", mountflags, NULL, NULL);
+       if (r != 0) {
+               fprintf(stderr, "newroot: mount failed: %s\n",strerror(errno));
                exit(1);
        }
+       
        return 0;
 }
index 6446da30f2d5f3a7bd78bf89f0d5938e39fd4b2c..4a28f9a104ded0fd0142eb070b9fb9c6ca59afd2 100644 (file)
@@ -20,6 +20,11 @@ rootdev=`sysenv rootdev` || echo 'No rootdev?'
 rootdevname=`/bin/dev2name "$rootdev"` ||
        { echo 'No device name for root device'; exit 1; }
 
+if [ "`sysenv bin_img`" = 1 ]
+then
+    bin_img="-i "
+fi
+
 if sysenv cdproberoot >/dev/null
 then
        echo 
@@ -40,5 +45,5 @@ then
        loadramdisk "$ramimagename"
 fi
 echo "Root device name is $rootdevname"
-/bin/newroot "$rootdevname"
+/bin/newroot $bin_img"$rootdevname"
 exec /bin/sh /etc/rc "$@"
diff --git a/etc/rc b/etc/rc
index e73217e19c9738b4f86d8586567375550c3a1e3d..4e9b0286e6fa3d9384e656e7a36d91170cbea45e 100755 (executable)
--- a/etc/rc
+++ b/etc/rc
@@ -73,6 +73,12 @@ start)
     # Any swapspace on a device?
     test "$swap" : '/dev/' && mount -s $swap
 
+    # Use MFS binary only from kernel image?
+    if [ "`sysenv bin_img`" = 1 ]
+    then
+        bin_img="-i "
+    fi
+
     # Are we booting from CD?
     bootcd="`/bin/sysenv bootcd`"
 
@@ -89,6 +95,7 @@ start)
                echo "Setting /usr on cd is $usr"
     fi
  
+
     # Mount the /usr partition unless this is a single floppy Minix.
     if [ ! -d /usr/bin ]
     then
@@ -101,7 +108,8 @@ start)
                echo "usr=/dev/$usr" >/tmp/usr'
            . /tmp/usr
        fi
-       mount $usr_roflag $usr /usr || {
+
+       mount $bin_img $usr_roflag $usr /usr || {
            echo "\
 Please try to mount something else as /usr, then hit CTRL-D to continue startup.
 Mount $usr /usr failed -- Single user."
@@ -129,11 +137,11 @@ Mount $usr /usr failed -- Single user."
        then    echo "fsck /home - $home"
                intr fsck -r $home
        fi
-       mount $usr /usr
+       mount $bin_img $usr /usr
     fi
 
     if [ ! -z "$home" ]
-    then mount $home /home || echo "WARNING: couldn't mount $home on /home"
+    then mount $bin_img $home /home || echo "WARNING: couldn't mount $home on /home"
     fi
 
     # This file is necessary for above 'shutdown -C' check.
index 29012b4f366f05a604c846507b31e01f7741e9ce..543f9a8cf3e8853b31b0234a2a23c71bc951484a 100644 (file)
@@ -41,6 +41,7 @@ struct rs_start
                                 * to restart the driver without accessing FS
                                 */
 #define RF_IPC_VALID   0x02    /* rss_ipc and rss_ipclen are valid */
+#define RF_REUSE       0x04    /* Try to reuse previously copied binary */
 
 #define RSP_LABEL_SIZE 16
 #define RSP_NR_DEVICE  16
index 16975923cea5a894ac2d2fc3af8e93542074ed2e..8b093157c5e25cdf74fbb7fc2b35552ac82689d9 100755 (executable)
@@ -66,6 +66,12 @@ int mountflags;
   if (args == NULL) args = "";
   reuse = 0;
 
+  /* Check mount flags */
+  if(mountflags & MS_REUSE) {
+    reuse = 1;
+    mountflags &= ~MS_REUSE; /* Temporary: turn off to not confuse VFS */
+  }
+
   /* Make FS process label for RS from special name. */
   if(!(label=makelabel(special))) {
        return -1;
@@ -78,6 +84,7 @@ int mountflags;
   }
   strcpy(path, FSPATH);
   strcat(path, type);
+  
   if(stat(path, &statbuf) != 0) {
        errno = EINVAL;
        return -1;
@@ -95,19 +102,17 @@ int mountflags;
        return -1;
   }
 
-  if(mountflags & MS_REUSE) {
-    reuse = 1;
-    mountflags &= ~MS_REUSE; /* Temporary: turn off to not confuse VFS */
-  }
 
-  sprintf(cmd, _PATH_SERVICE " up %s -label '%s' -config " _PATH_DRIVERS_CONF
+
+  sprintf(cmd, _PATH_SERVICE " %sup %s -label '%s' -config " _PATH_DRIVERS_CONF
        " -args '%s%s' -printep yes",
-       path, label, args[0] ? "-o " : "", args);
+         reuse ? "-r ": "", path, label, args[0] ? "-o " : "", args);
 
   if(!(pipe = popen(cmd, "r"))) {
        fprintf(stderr, "mount: couldn't run %s\n", cmd);
        return -1;
   }
+  
   if(fscanf(pipe, "%d", &ep) != 1 || ep <= 0) {
        fprintf(stderr, "mount: couldn't parse endpoint from %s\n", cmd);
        errno = EINVAL;
index 351b6c60319a6170dfa7fce5ac0aab66c01a09a6..49b4f17f4314c3db8daacd2e34d5768cbdf6075b 100644 (file)
@@ -29,6 +29,8 @@ FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags,
 FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
 FORWARD _PROTOTYPE( int fork_nb, (void) );
 FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
+FORWARD _PROTOTYPE( int copy_exec, (struct rproc *rp_src,
+       struct rproc *rp_dst) );
 FORWARD _PROTOTYPE( void run_script, (struct rproc *rp) );
 FORWARD _PROTOTYPE( char *get_next_label, (char *ptr, char *label,
        char *caller_label) );
@@ -66,8 +68,6 @@ int flags;                                    /* extra flags, if any */
   int r;
   endpoint_t ep;                               /* new endpoint no. */
 
-printf("RS: in do_up\n");
-
   /* See if there is a free entry in the table with system processes. */
   for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
       rp = &rproc[slot_nr];                    /* get pointer to slot */
@@ -122,6 +122,7 @@ printf("RS: in do_up\n");
   rp->r_nice= 0;
 
   rp->r_exec= NULL;
+
   if (do_copy)
   {
        s= read_exec(rp);
@@ -283,9 +284,32 @@ message *m_ptr;                                    /* request message pointer */
        rp->r_ipc_list[0]= '\0';
 
   rp->r_exec= NULL;
-  if (rs_start.rss_flags & RF_COPY)
-  {
-       s= read_exec(rp);
+  if (rs_start.rss_flags & RF_COPY) {
+       int exst_cpy;
+       struct rproc *rp2;
+       exst_cpy = 0;
+       
+       if(rs_start.rss_flags & RF_REUSE) {
+               char *cmd = rp->r_cmd;
+                int i;
+                
+                for(i = 0; i < NR_SYS_PROCS; i++) {
+                       rp2 = &rproc[i];
+                        if(strcmp(rp->r_cmd, rp2->r_cmd) == 0 &&
+                           rp2->r_exec != NULL) {
+                                /* We have found the same binary that's
+                                 * already been copied */
+                                 exst_cpy = 1;
+                                 break;
+                        }
+                }
+         }                
+
+       if(!exst_cpy)
+               s = read_exec(rp);
+       else
+               s = copy_exec(rp, rp2); 
+
        if (s != OK)
                return s;
   }
@@ -405,9 +429,9 @@ PUBLIC int do_down(message *m_ptr)
       if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
        if(rs_verbose)
          printf("RS: stopping '%s' (%d)\n", label, rp->r_pid);
-         stop_service(rp,RS_EXITING);
-         if (rp->r_pid == -1)
-         {
+       stop_service(rp,RS_EXITING);
+       if (rp->r_pid == -1)
+       {
                /* Process is already gone */
                rp->r_flags = 0;                        /* release slot */
                if (rp->r_exec)
@@ -418,12 +442,12 @@ PUBLIC int do_down(message *m_ptr)
                proc = _ENDPOINT_P(rp->r_proc_nr_e);
                rproc_ptr[proc] = NULL;
                return(OK);
-         }
+       }
 
-         /* Late reply - send a reply when process dies. */
-         rp->r_flags |= RS_LATEREPLY;
-         rp->r_caller = m_ptr->m_source;
-         return EDONTREPLY;
+       /* Late reply - send a reply when process dies. */
+       rp->r_flags |= RS_LATEREPLY;
+       rp->r_caller = m_ptr->m_source;
+       return EDONTREPLY;
       }
   }
   if(rs_verbose) printf("RS: do_down: '%s' not found\n", label);
@@ -762,8 +786,7 @@ endpoint_t *endpoint;
   message m;
 
   use_copy= (rp->r_exec != NULL);
-
-
+  
   /* Now fork and branch for parent and child process (and check for error). */
   if (use_copy) {
   if(rs_verbose) printf("RS: fork_nb..\n");
@@ -940,6 +963,23 @@ PRIVATE pid_t fork_nb()
   return(_syscall(PM_PROC_NR, FORK_NB, &m));
 }
 
+PRIVATE int copy_exec(rp_dst, rp_src)
+struct rproc *rp_dst, *rp_src;
+{
+       /* Copy binary from rp_src to rp_dst. */
+       rp_dst->r_exec_len = rp_src->r_exec_len;
+       rp_dst->r_exec = malloc(rp_dst->r_exec_len);
+       if(rp_dst->r_exec == NULL)
+               return ENOMEM;
+
+       memcpy(rp_dst->r_exec, rp_src->r_exec, rp_dst->r_exec_len);
+       if(rp_dst->r_exec_len != 0 && rp_dst->r_exec != NULL)
+               return OK;
+               
+        rp_dst->r_exec = NULL;
+        return EIO;
+}
+
 PRIVATE int read_exec(rp)
 struct rproc *rp;
 {
@@ -947,9 +987,10 @@ struct rproc *rp;
        char *e_name;
        struct stat sb;
 
+
        e_name= rp->r_argv[0];
        r= stat(e_name, &sb);
-       if (r != 0)
+       if (r != 0) 
                return -errno;
 
        fd= open(e_name, O_RDONLY);
index 2351b4f776842866686011f5d344c92aebdb1a6b..3e0251d41d08a89afb072434227c8b4e70a9a570 100644 (file)
@@ -133,10 +133,11 @@ PRIVATE int parse_arguments(int argc, char **argv)
   char *hz;
   int req_nr;
   int c, i;
-  int c_flag;
+  int c_flag, r_flag;
 
-  c_flag= 0;
-  while (c= getopt(argc, argv, "ci?"), c != -1)
+  c_flag = 0;
+  r_flag = 0;
+  while (c= getopt(argc, argv, "rci?"), c != -1)
   {
        switch(c)
        {
@@ -144,7 +145,11 @@ PRIVATE int parse_arguments(int argc, char **argv)
                print_usage(argv[ARG_NAME], "wrong number of arguments");
                exit(EINVAL);
        case 'c':
-               c_flag= 1;
+               c_flag = 1;
+               break;
+       case 'r':
+               c_flag = 1; /* -r implies -c */
+               r_flag = 1;
                break;
        case 'i':
                /* Legacy - remove later */
@@ -184,13 +189,15 @@ PRIVATE int parse_arguments(int argc, char **argv)
   }
 
   if (req_nr == RS_UP) {
-
-       req_nr= RS_START;
+      req_nr= RS_START;
 
       rs_start.rss_flags= RF_IPC_VALID;
       if (c_flag)
        rs_start.rss_flags |= RF_COPY;
 
+      if(r_flag)
+        rs_start.rss_flags |= RF_REUSE;
+        
       if (do_run)
       {
        /* Set default recovery script for RUN */
@@ -198,8 +205,10 @@ PRIVATE int parse_arguments(int argc, char **argv)
        req_nr = RS_START;
       }
 
+#if 0
       if (req_nr == RS_UP && c_flag)
        req_nr= RS_UP_COPY;
+#endif 
 
       /* Verify argument count. */ 
       if (argc - 1 < optind+ARG_PATH) {