From: Ben Gras Date: Fri, 22 Jul 2005 18:28:32 +0000 (+0000) Subject: . added cd-probe logic; tries to find the right root filesystem X-Git-Tag: v3.1.0~568 X-Git-Url: http://zhaoyanbai.com/repos/doc/tz-art.htm?a=commitdiff_plain;h=6e8f484b3b9f24cfec663475a1a213ef63f530c1;p=minix.git . 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) --- diff --git a/servers/fs/Makefile b/servers/fs/Makefile index 9b94b1c84..fbe337dac 100644 --- a/servers/fs/Makefile +++ b/servers/fs/Makefile @@ -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) diff --git a/servers/fs/cdprobe.c b/servers/fs/cdprobe.c new file mode 100644 index 000000000..fa2615fe6 --- /dev/null +++ b/servers/fs/cdprobe.c @@ -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 +#include + +/*===========================================================================* + * 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; +} + diff --git a/servers/fs/main.c b/servers/fs/main.c index fbac0851f..d3403a730 100644 --- a/servers/fs/main.c +++ b/servers/fs/main.c @@ -15,6 +15,7 @@ struct super_block; /* proto.h needs to know this */ #include "fs.h" #include #include +#include #include #include #include @@ -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) - printf("FS: Warning, couldn't get monitor param: %d\n", i); + 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,22 +373,34 @@ 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); - bp1->b_dirt = DIRTY; + 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(bp1, FULL_DATA_BLOCK); + } 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); + 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."); printf("\n\n"); diff --git a/servers/fs/proto.h b/servers/fs/proto.h index 0f813ddc0..d0cb5644b 100644 --- a/servers/fs/proto.h +++ b/servers/fs/proto.h @@ -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)); diff --git a/servers/fs/select.c b/servers/fs/select.c index 044890800..91ca0de1e 100644 --- a/servers/fs/select.c +++ b/servers/fs/select.c @@ -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 * diff --git a/servers/fs/super.c b/servers/fs/super.c index a4bfcf3d5..e3d2b0e71 100644 --- a/servers/fs/super.c +++ b/servers/fs/super.c @@ -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; diff --git a/servers/fs/timers.c b/servers/fs/timers.c index 6130b75e0..b0253c61d 100644 --- a/servers/fs/timers.c +++ b/servers/fs/timers.c @@ -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;