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.
This commit is contained in:
Thomas Veerman 2009-08-18 11:36:01 +00:00
parent 47a2bfeddd
commit b47483433c
8 changed files with 136 additions and 51 deletions

View file

@ -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);

View 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);
}
dev= argv[1];
r= mount(dev, "/", 0 /* !ro */, NULL, NULL);
if (r != 0)
{
fprintf(stderr, "newroot: mount failed: %s\n", strerror(errno));
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];
}
r = mount(dev, "/", mountflags, NULL, NULL);
if (r != 0) {
fprintf(stderr, "newroot: mount failed: %s\n",strerror(errno));
exit(1);
}
return 0;
}

View 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 "$@"

14
etc/rc
View file

@ -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.

View 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

View file

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

View 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);

View 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) {