. 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:
parent
f73af8573a
commit
6e8f484b3b
7 changed files with 176 additions and 51 deletions
|
@ -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
87
servers/fs/cdprobe.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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.");
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue