From: Thomas Veerman Date: Tue, 18 Aug 2009 11:36:01 +0000 (+0000) Subject: Added a hack to start binaries from the boot image only. In particular, setting X-Git-Tag: v3.1.5~181 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=b47483433c8fc70cad760265737a537d924b0f9b;p=minix.git Added a hack to start binaries from the boot image only. In particular, setting 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. --- diff --git a/commands/simple/mount.c b/commands/simple/mount.c index 911407bf3..f89d06875 100755 --- a/commands/simple/mount.c +++ b/commands/simple/mount.c @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -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); diff --git a/commands/simple/newroot.c b/commands/simple/newroot.c index 0fa1fd77e..e6ea8cc27 100644 --- a/commands/simple/newroot.c +++ b/commands/simple/newroot.c @@ -10,22 +10,36 @@ Replace the current root with a new one #include #include +void usage(void) { + fprintf(stderr, "Usage: newroot [-i] \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 \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; } diff --git a/drivers/memory/ramdisk/rc b/drivers/memory/ramdisk/rc index 6446da30f..4a28f9a10 100644 --- a/drivers/memory/ramdisk/rc +++ b/drivers/memory/ramdisk/rc @@ -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 e73217e19..4e9b0286e 100755 --- 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. diff --git a/include/minix/rs.h b/include/minix/rs.h index 29012b4f3..543f9a8cf 100644 --- a/include/minix/rs.h +++ b/include/minix/rs.h @@ -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 diff --git a/lib/other/_mount.c b/lib/other/_mount.c index 16975923c..8b093157c 100755 --- a/lib/other/_mount.c +++ b/lib/other/_mount.c @@ -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; diff --git a/servers/rs/manager.c b/servers/rs/manager.c index 351b6c603..49b4f17f4 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -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); diff --git a/servers/rs/service.c b/servers/rs/service.c index 2351b4f77..3e0251d41 100644 --- a/servers/rs/service.c +++ b/servers/rs/service.c @@ -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) {