. added cd-probe logic; tries to find the right root filesystem

if the boot monitor parameter is set. it also sets a boot monitor
  parameter (by talking to the PM) so userland knows it.
. ramdisk copy code made slightly smarter
. various select() prettifications (work in progress)
This commit is contained in:
Ben Gras 2005-07-22 18:28:32 +00:00
parent f73af8573a
commit 6e8f484b3b
7 changed files with 176 additions and 51 deletions

View file

@ -16,7 +16,8 @@ LIBS = -lsys -lsysutil -ltimers
OBJ = main.o open.o read.o write.o pipe.o dmap.o \
device.o path.o mount.o link.o super.o inode.o \
cache.o cache2.o filedes.o stadir.o protect.o time.o \
cmostime.o lock.o misc.o utility.o select.o timers.o table.o
cmostime.o lock.o misc.o utility.o select.o timers.o table.o \
cdprobe.o
# build local binary
all build: $(SERVER)

87
servers/fs/cdprobe.c Normal file
View file

@ -0,0 +1,87 @@
/* This file contains some code to guess where we have to load the
* RAM image device from, if started from CD. (In this case it's hard
* to tell where this is without diving into BIOS heuristics.)
*
* There is some nasty hard-codery in here (e.g. AT minor device numbers,
* MINIX cd label) that can be improved on.
*
* Changes:
* Jul 14, 2005 Created (Ben Gras)
*/
#include "fs.h"
#include "super.h"
#include <minix/com.h>
#include <string.h>
/*===========================================================================*
* cdprobe *
*===========================================================================*/
PUBLIC int cdprobe(void)
{
#define CD_SECTOR 2048
#define AT_MAJOR 3
#define AT_MINORS 4
int i, minors[AT_MINORS] = { 0, 5, 10, 15 }, dev = 0, found = 0;
char pvd[CD_SECTOR];
for(i = 0; i < AT_MINORS && !found; i++) {
struct super_block probe_super;
int r, minor;
dev = (AT_MAJOR << MAJOR) | minors[i];
/* 1. The drive should be a CD - which is not write-openable.
* Check for this.
*/
if((r = dev_open(dev, FS_PROC_NR, R_BIT|W_BIT)) == OK) {
dev_close(dev);
continue;
}
/* 2. The drive should be a CD. Open whole drive and
* check for the PVD.
*/
if((r = dev_open(dev, FS_PROC_NR, R_BIT)) != OK) {
continue;
}
if((r = dev_io(DEV_READ, dev, FS_PROC_NR, pvd,
16*CD_SECTOR, sizeof(pvd), 0)) != sizeof(pvd)) {
dev_close(dev);
continue;
}
dev_close(dev);
/* Check PVD ID. */
if(pvd[0] != 1 || pvd[1] != 'C' || pvd[2] != 'D' ||
pvd[3] != '0' || pvd[4] != '0' || pvd[5] != '1' || pvd[6] != 1 ||
strncmp(pvd + 40, "MINIX", 5)) {
continue;
}
/* 3. Both c0dXp1 and p2 should have a superblock. */
for(minor = minors[i]+2; minor <= minors[i]+3; minor++) {
dev = (AT_MAJOR << MAJOR) | minor;
if((r = dev_open(dev, FS_PROC_NR, R_BIT)) != OK)
continue;
probe_super.s_dev = dev;
r = read_super(&probe_super);
dev_close(dev);
if(r != OK) {
break;
}
}
if(minor > minors[i]+3) {
/* Success? Then set dev to p1. */
dev = (AT_MAJOR << MAJOR) | (minors[i]+2);
found = 1;
break;
}
}
if(!found) return NO_DEV;
return dev;
}

View file

@ -15,6 +15,7 @@ struct super_block; /* proto.h needs to know this */
#include "fs.h"
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/ioc_memory.h>
@ -34,12 +35,11 @@ struct super_block; /* proto.h needs to know this */
FORWARD _PROTOTYPE( void fs_init, (void) );
FORWARD _PROTOTYPE( int igetenv, (char *var) );
FORWARD _PROTOTYPE( int igetenv, (char *var, int optional) );
FORWARD _PROTOTYPE( void get_work, (void) );
FORWARD _PROTOTYPE( void load_ram, (void) );
FORWARD _PROTOTYPE( void load_super, (Dev_t super_dev) );
/*===========================================================================*
* main *
*===========================================================================*/
@ -225,6 +225,7 @@ PRIVATE void fs_init()
map_controllers(); /* map controller devices to drivers */
load_ram(); /* init RAM disk, load if it is root */
load_super(root_dev); /* load super block for root device */
init_select(); /* init select() structures */
/* The root device can now be accessed; set process directories. */
@ -242,19 +243,22 @@ PRIVATE void fs_init()
/*===========================================================================*
* igetenv *
*===========================================================================*/
PRIVATE int igetenv(key)
PRIVATE int igetenv(key, optional)
char *key;
int optional;
{
/* Ask kernel for an integer valued boot environment variable. */
char value[64];
int i;
if ((i = get_mon_param(key, value, sizeof(value))) != OK)
if ((i = get_mon_param(key, value, sizeof(value))) != OK) {
if(!optional)
printf("FS: Warning, couldn't get monitor param: %d\n", i);
return 0;
}
return(atoi(value));
}
/*===========================================================================*
* load_ram *
*===========================================================================*/
@ -276,18 +280,38 @@ PRIVATE void load_ram(void)
int block_size_image, block_size_ram, ramfs_block_size;
/* Get some boot environment variables. */
root_dev = igetenv("rootdev");
image_dev = igetenv("ramimagedev");
ram_size_kb = igetenv("ramsize");
root_dev = igetenv("rootdev", 0);
image_dev = igetenv("ramimagedev", 0);
ram_size_kb = igetenv("ramsize", 0);
/* Open the root device. */
if (dev_open(root_dev, FS_PROC_NR, R_BIT|W_BIT) != OK) {
if (dev_open(root_dev, FS_PROC_NR, R_BIT|W_BIT) != OK)
panic(__FILE__,"Cannot open root device",NO_NUM);
}
/* If we must initialize a ram disk, get details from the image device. */
if (root_dev == DEV_RAM || root_dev != image_dev) {
u32_t fsmax;
u32_t fsmax, probedev;
/* If we are running from CD, see if we can find it. */
if(igetenv("cdproberoot", 1) && (probedev=cdprobe()) != NO_DEV) {
char devnum[10];
struct sysgetenv env;
/* If so, this is our new RAM image device. */
image_dev = probedev;
/* Tell PM about it, so userland can find out about it
* with sysenv interface.
*/
env.key = "cdproberoot";
env.keylen = strlen(env.key);
sprintf(devnum, "%d", probedev);
env.val = devnum;
env.vallen = strlen(devnum);
svrctl(MMSETPARAM, &env);
}
/* Open image device for RAM root. */
if (dev_open(image_dev, FS_PROC_NR, R_BIT) != OK)
panic(__FILE__,"Cannot open RAM image device", NO_NUM);
@ -349,21 +373,33 @@ PRIVATE void load_ram(void)
block_size_ram = get_block_size(DEV_RAM);
block_size_image = get_block_size(image_dev);
if(block_size_ram != block_size_image) {
printf("ram block size: %d image block size: %d\n",
/* RAM block size has to be a multiple of the root image block
* size to make copying easier.
*/
if(block_size_image % block_size_ram) {
printf("\nram block size: %d image block size: %d\n",
block_size_ram, block_size_image);
panic(__FILE__,"ram disk and image disk block sizes must match", NO_NUM);
panic(__FILE__, "ram disk block size must be a multiple of the image disk block size", NO_NUM);
}
/* Loading blocks from image device. */
for (b = 0; b < (block_t) lcount; b++) {
int rb, factor;
bp = rahead(&inode[0], b, (off_t)block_size_image * b, block_size_image);
bp1 = get_block(root_dev, b, NO_READ);
memcpy(bp1->b_data, bp->b_data, (size_t) block_size_image);
factor = block_size_image/block_size_ram;
for(rb = 0; rb < factor; rb++) {
bp1 = get_block(root_dev, b * factor + rb, NO_READ);
memcpy(bp1->b_data, bp->b_data + rb * block_size_ram,
(size_t) block_size_ram);
bp1->b_dirt = DIRTY;
put_block(bp, FULL_DATA_BLOCK);
put_block(bp1, FULL_DATA_BLOCK);
printf("\b\b\b\b\b\b\b%5ldK ", ((long) b * block_size_image)/1024L);
}
put_block(bp, FULL_DATA_BLOCK);
printf("\b\b\b\b\b\b\b\b%6ldK ", ((long) b * block_size_image)/1024L);
}
/* Commit changes to RAM so dev_io will see it. */
do_sync();
printf("\rRAM disk of %u kb loaded.\33[K", ram_size_kb);
if (root_dev == DEV_RAM) printf(" RAM disk is used as root FS.");

View file

@ -184,9 +184,14 @@ _PROTOTYPE( int do_select, (void) );
_PROTOTYPE( int select_callback, (struct filp *, int ops) );
_PROTOTYPE( void select_forget, (int fproc) );
_PROTOTYPE( void select_timeout_check, (timer_t *) );
_PROTOTYPE( void init_select, (void) );
_PROTOTYPE( int select_notified, (message *) );
/* timers.c */
_PROTOTYPE( void fs_set_timer, (timer_t *tp, int delta, tmr_func_t watchdog, int arg));
_PROTOTYPE( void fs_expire_timers, (clock_t now));
_PROTOTYPE( void fs_cancel_timer, (timer_t *tp));
_PROTOTYPE( void fs_init_timer, (timer_t *tp));
/* cdprobe.c */
_PROTOTYPE( int cdprobe, (void));

View file

@ -58,9 +58,7 @@ FORWARD _PROTOTYPE(int select_reevaluate, (struct filp *fp));
FORWARD _PROTOTYPE(int select_request_file, (struct filp *f, int *ops, int block));
FORWARD _PROTOTYPE(int select_match_file, (struct filp *f));
FORWARD _PROTOTYPE(int select_request_tty, (struct filp *f, int *ops, int block));
FORWARD _PROTOTYPE(int select_request_inet, (struct filp *f, int *ops, int block));
FORWARD _PROTOTYPE(int select_request_log, (struct filp *f, int *ops, int block));
FORWARD _PROTOTYPE(int select_request_general, (struct filp *f, int *ops, int block));
FORWARD _PROTOTYPE(int select_major_match, (int match_major, struct filp *file));
FORWARD _PROTOTYPE(void select_cancel_all, (struct selectentry *e));
@ -80,13 +78,13 @@ PRIVATE struct fdtype {
/* SELFD_FILE */
{ select_request_file, select_match_file, 0 },
/* SELFD_TTY (also PTY) */
{ select_request_tty, NULL, TTY_MAJOR },
{ select_request_general, NULL, TTY_MAJOR },
/* SELFD_INET */
{ select_request_inet, NULL, INET_MAJOR },
{ select_request_general, NULL, INET_MAJOR },
/* SELFD_PIPE (pipe(2) pipes and FS FIFOs) */
{ select_request_pipe, select_match_pipe, 0 },
/* SELFD_LOG (/dev/klog) */
{ select_request_log, NULL, LOG_MAJOR },
{ select_request_general, NULL, LOG_MAJOR },
};
/* Open Group:
@ -128,25 +126,9 @@ PRIVATE int select_request_tty(struct filp *f, int *ops, int block)
}
/*===========================================================================*
* select_request_inet *
* select_request_general *
*===========================================================================*/
PRIVATE int select_request_inet(struct filp *f, int *ops, int block)
{
int r, rops;
rops = *ops;
if(block) rops |= SEL_NOTIFY;
*ops = dev_io(DEV_SELECT, f->filp_ino->i_zone[0], rops, NULL, 0, 0, 0);
printf("select_request_inet: got reply %d from inet for %d on %d\n",
*ops, rops, f->filp_ino->i_zone[0]);
if(*ops < 0)
return SEL_ERR;
return SEL_OK;
}
/*===========================================================================*
* select_request_log *
*===========================================================================*/
PRIVATE int select_request_log(struct filp *f, int *ops, int block)
PRIVATE int select_request_general(struct filp *f, int *ops, int block)
{
int r, rops;
rops = *ops;
@ -536,7 +518,6 @@ PUBLIC int select_callback(struct filp *fp, int ops)
* operations that we are still interested in, if any.
*/
restart_callback:
want_ops = 0;
type = -1;
for(s = 0; s < MAXSELECTS; s++) {
@ -613,6 +594,16 @@ PUBLIC int select_notified(message *m)
return OK;
}
/*===========================================================================*
* init_select *
*===========================================================================*/
PUBLIC void init_select(void)
{
int s;
for(s = 0; s < MAXSELECTS; s++)
fs_init_timer(&selecttab[s].timer);
}
/*===========================================================================*
* int select_forget *

View file

@ -1,5 +1,4 @@
/* This file manages the super block table and the related data structures,
* namely, the bit maps that keep track of which zones and which inodes are
/* This file manages the super block table and the related data structures, * namely, the bit maps that keep track of which zones and which inodes are
* allocated and which are free. When a new inode or zone is needed, the
* appropriate bit map is searched for a free entry.
*
@ -174,9 +173,11 @@ PUBLIC int get_block_size(dev_t dev)
if(dev == NO_DEV)
panic(__FILE__,"request for block size of NO_DEV", NO_NUM);
for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
if (sp->s_dev == dev)
for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
if (sp->s_dev == dev) {
return(sp->s_block_size);
}
}
/* no mounted filesystem? use this block size then. */
return MIN_BLOCK_SIZE;

View file

@ -19,7 +19,6 @@ PUBLIC void fs_set_timer(timer_t *tp, int ticks, tmr_func_t watchdog, int arg)
if((r = getuptime(&now)) != OK)
panic(__FILE__, "FS couldn't get uptime from system task.", NO_NUM);
tmr_inittimer(tp);
tmr_arg(tp)->ta_int = arg;
old_head = tmrs_settimer(&fs_timers, tp, now+ticks, watchdog, &new_head);
@ -54,6 +53,11 @@ PUBLIC void fs_expire_timers(clock_t now)
#endif
}
PUBLIC void fs_init_timer(timer_t *tp)
{
tmr_inittimer(tp);
}
PUBLIC void fs_cancel_timer(timer_t *tp)
{
clock_t new_head, old_head;