]> Zhao Yanbai Git Server - minix.git/commitdiff
. added cd-probe logic; tries to find the right root filesystem
authorBen Gras <ben@minix3.org>
Fri, 22 Jul 2005 18:28:32 +0000 (18:28 +0000)
committerBen Gras <ben@minix3.org>
Fri, 22 Jul 2005 18:28:32 +0000 (18:28 +0000)
  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)

servers/fs/Makefile
servers/fs/cdprobe.c [new file with mode: 0644]
servers/fs/main.c
servers/fs/proto.h
servers/fs/select.c
servers/fs/super.c
servers/fs/timers.c

index 9b94b1c846ff94f383bcfedbf6cf3ac56d9ab97e..fbe337daccc7929ad2f05dfd13855120baab3b6e 100644 (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)
diff --git a/servers/fs/cdprobe.c b/servers/fs/cdprobe.c
new file mode 100644 (file)
index 0000000..fa2615f
--- /dev/null
@@ -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;
+}
+
index fbac0851fb6249da2874394e372efb0e70de08a0..d3403a73035654d98a1c4310506ac2d7adbb045d 100644 (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)
-      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");
index 0f813ddc04f2bbed4b822d634b0def6c8274e371..d0cb5644b36d8c4b0d0b8dbd19763cbc2c13a977 100644 (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));
index 0448908008278ad300bbe08c30bdce85217334e0..91ca0de1e9d86eb5c4594a5f9e42e23f4a3848c8 100644 (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                            *
index a4bfcf3d57bac331021f866147e801eb0930969b..e3d2b0e717a6eb6d7d8f42a76864a91f40f5fa76 100644 (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;
index 6130b75e0b7e6109663f0fb1089ff4e0f26ff57e..b0253c61dee3946a24aa0269511587d8d885307b 100644 (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;