main.c

Go to the documentation of this file.
00001 /* This file contains the main program of the File System.  It consists of
00002  * a loop that gets messages requesting work, carries out the work, and sends
00003  * replies.
00004  *
00005  * The entry points into this file are:
00006  *   main:      main program of the File System
00007  *   reply:     send a reply to a process after the requested work is done
00008  *
00009  */
00010 
00011 struct super_block;             /* proto.h needs to know this */
00012 
00013 #include "fs.h"
00014 #include <fcntl.h>
00015 #include <string.h>
00016 #include <stdio.h>
00017 #include <signal.h>
00018 #include <stdlib.h>
00019 #include <sys/ioc_memory.h>
00020 #include <sys/svrctl.h>
00021 #include <sys/select.h>
00022 #include <minix/callnr.h>
00023 #include <minix/com.h>
00024 #include <minix/keymap.h>
00025 #include <minix/const.h>
00026 #include <minix/endpoint.h>
00027 #include "buf.h"
00028 #include "file.h"
00029 #include "fproc.h"
00030 #include "inode.h"
00031 #include "param.h"
00032 #include "super.h"
00033 
00034 FORWARD _PROTOTYPE( void fs_init, (void)                                );
00035 FORWARD _PROTOTYPE( void get_work, (void)                               );
00036 FORWARD _PROTOTYPE( void init_root, (void)                              );
00037 
00038 /*===========================================================================*
00039  *                              main                                         *
00040  *===========================================================================*/
00041 PUBLIC int main()
00042 {
00043 /* This is the main program of the file system.  The main loop consists of
00044  * three major activities: getting new work, processing the work, and sending
00045  * the reply.  This loop never terminates as long as the file system runs.
00046  */
00047   int error;
00048 
00049   fs_init();
00050 
00051 
00052   /* This is the main loop that gets work, processes it, and sends replies. */
00053   while (TRUE) {
00054         get_work();             /* sets who and call_nr */
00055         fp = &fproc[who_p];     /* pointer to proc table struct */
00056         super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
00057 
00058         /* Check for special control messages first. */
00059         if (call_nr == PROC_EVENT) {
00060                 /* Assume FS got signal. Synchronize, but don't exit. */
00061                 do_sync();
00062         } else if (call_nr == SYN_ALARM) {
00063                 /* Alarm timer expired. Used only for select(). Check it. */
00064                 fs_expire_timers(m_in.NOTIFY_TIMESTAMP);
00065         } else if ((call_nr & NOTIFY_MESSAGE)) {
00066                 /* Device notifies us of an event. */
00067                 dev_status(&m_in);
00068         } else {
00069                 /* Call the internal function that does the work. */
00070                 if (call_nr < 0 || call_nr >= NCALLS) { 
00071                         error = ENOSYS;
00072                 /* Not supposed to happen. */
00073                         printf("FS, warning illegal %d system call by %d\n", call_nr, who_e);
00074                 } else if (fp->fp_pid == PID_FREE) {
00075                         error = ENOSYS;
00076                         printf("FS, bad process, who = %d, call_nr = %d, endpt1 = %d\n",
00077                                  who_e, call_nr, m_in.endpt1);
00078                 } else {
00079                         error = (*call_vec[call_nr])();
00080                 }
00081 
00082                 /* Copy the results back to the user and send reply. */
00083                 if (error != SUSPEND) { reply(who_e, error); }
00084                 if (rdahed_inode != NIL_INODE) {
00085                         read_ahead(); /* do block read ahead */
00086                 }
00087         }
00088   }
00089   return(OK);                           /* shouldn't come here */
00090 }
00091 
00092 /*===========================================================================*
00093  *                              get_work                                     *
00094  *===========================================================================*/
00095 PRIVATE void get_work()
00096 {  
00097   /* Normally wait for new input.  However, if 'reviving' is
00098    * nonzero, a suspended process must be awakened.
00099    */
00100   register struct fproc *rp;
00101 
00102   if (reviving != 0) {
00103         /* Revive a suspended process. */
00104         for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) 
00105                 if (rp->fp_pid != PID_FREE && rp->fp_revived == REVIVING) {
00106                         who_p = (int)(rp - fproc);
00107                         who_e = rp->fp_endpoint;
00108                         call_nr = rp->fp_fd & BYTE;
00109                         m_in.fd = (rp->fp_fd >>8) & BYTE;
00110                         m_in.buffer = rp->fp_buffer;
00111                         m_in.nbytes = rp->fp_nbytes;
00112                         rp->fp_suspended = NOT_SUSPENDED; /*no longer hanging*/
00113                         rp->fp_revived = NOT_REVIVING;
00114                         reviving--;
00115                         return;
00116                 }
00117         panic(__FILE__,"get_work couldn't revive anyone", NO_NUM);
00118   }
00119 
00120   for(;;) {
00121     /* Normal case.  No one to revive. */
00122     if (receive(ANY, &m_in) != OK)
00123         panic(__FILE__,"fs receive error", NO_NUM);
00124     who_e = m_in.m_source;
00125     who_p = _ENDPOINT_P(who_e);
00126     if(who_p < -NR_TASKS || who_p >= NR_PROCS)
00127         panic(__FILE__,"receive process out of range", who_p);
00128     if(who_p >= 0 && fproc[who_p].fp_endpoint == NONE) {
00129         printf("FS: ignoring request from %d, endpointless slot %d (%d)\n",
00130                 m_in.m_source, who_p, m_in.m_type);
00131         continue;
00132     }
00133     if(who_p >= 0 && fproc[who_p].fp_endpoint != who_e) {
00134         printf("FS: receive endpoint inconsistent (%d, %d, %d).\n",
00135                 who_e, fproc[who_p].fp_endpoint, who_e);
00136         panic(__FILE__, "FS: inconsistent endpoint ", NO_NUM);
00137         continue;
00138     }
00139     call_nr = m_in.m_type;
00140     return;
00141   }
00142 }
00143 
00144 /*===========================================================================*
00145  *                              buf_pool                                     *
00146  *===========================================================================*/
00147 PRIVATE void buf_pool(void)
00148 {
00149 /* Initialize the buffer pool. */
00150 
00151   register struct buf *bp;
00152 
00153   bufs_in_use = 0;
00154   front = &buf[0];
00155   rear = &buf[NR_BUFS - 1];
00156 
00157   for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
00158         bp->b_blocknr = NO_BLOCK;
00159         bp->b_dev = NO_DEV;
00160         bp->b_next = bp + 1;
00161         bp->b_prev = bp - 1;
00162   }
00163   buf[0].b_prev = NIL_BUF;
00164   buf[NR_BUFS - 1].b_next = NIL_BUF;
00165 
00166   for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
00167   buf_hash[0] = front;
00168 
00169 }
00170 
00171 /*===========================================================================*
00172  *                              reply                                        *
00173  *===========================================================================*/
00174 PUBLIC void reply(whom, result)
00175 int whom;                       /* process to reply to */
00176 int result;                     /* result of the call (usually OK or error #) */
00177 {
00178 /* Send a reply to a user process.  If the send fails, just ignore it. */
00179   int s;
00180   m_out.reply_type = result;
00181   s = send(whom, &m_out);
00182   if (s != OK) printf("FS: couldn't send reply %d to %d: %d\n",
00183         result, whom, s);
00184 }
00185 
00186 /*===========================================================================*
00187  *                              fs_init                                      *
00188  *===========================================================================*/
00189 PRIVATE void fs_init()
00190 {
00191 /* Initialize global variables, tables, etc. */
00192   register struct inode *rip;
00193   register struct fproc *rfp;
00194   message mess;
00195   int s;
00196 
00197   /* Initialize the process table with help of the process manager messages. 
00198    * Expect one message for each system process with its slot number and pid. 
00199    * When no more processes follow, the magic process number NONE is sent. 
00200    * Then, stop and synchronize with the PM.
00201    */
00202   do {
00203         if (OK != (s=receive(PM_PROC_NR, &mess)))
00204                 panic(__FILE__,"FS couldn't receive from PM", s);
00205         if (NONE == mess.PR_ENDPT) break; 
00206 
00207         rfp = &fproc[mess.PR_SLOT];
00208         rfp->fp_pid = mess.PR_PID;
00209         rfp->fp_endpoint = mess.PR_ENDPT;
00210         rfp->fp_realuid = (uid_t) SYS_UID;
00211         rfp->fp_effuid = (uid_t) SYS_UID;
00212         rfp->fp_realgid = (gid_t) SYS_GID;
00213         rfp->fp_effgid = (gid_t) SYS_GID;
00214         rfp->fp_umask = ~0;
00215    
00216   } while (TRUE);                       /* continue until process NONE */
00217   mess.m_type = OK;                     /* tell PM that we succeeded */
00218   s=send(PM_PROC_NR, &mess);            /* send synchronization message */
00219 
00220   /* All process table entries have been set. Continue with FS initialization.
00221    * Certain relations must hold for the file system to work at all. Some 
00222    * extra block_size requirements are checked at super-block-read-in time.
00223    */
00224   if (OPEN_MAX > 127) panic(__FILE__,"OPEN_MAX > 127", NO_NUM);
00225   if (NR_BUFS < 6) panic(__FILE__,"NR_BUFS < 6", NO_NUM);
00226   if (V1_INODE_SIZE != 32) panic(__FILE__,"V1 inode size != 32", NO_NUM);
00227   if (V2_INODE_SIZE != 64) panic(__FILE__,"V2 inode size != 64", NO_NUM);
00228   if (OPEN_MAX > 8 * sizeof(long))
00229          panic(__FILE__,"Too few bits in fp_cloexec", NO_NUM);
00230 
00231   /* The following initializations are needed to let dev_opcl succeed .*/
00232   fp = (struct fproc *) NULL;
00233   who_e = who_p = FS_PROC_NR;
00234 
00235   buf_pool();                   /* initialize buffer pool */
00236   build_dmap();                 /* build device table and map boot driver */
00237   init_root();                  /* init root device and load super block */
00238   init_select();                /* init select() structures */
00239 
00240   /* The root device can now be accessed; set process directories. */
00241   for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
00242         FD_ZERO(&(rfp->fp_filp_inuse));
00243         if (rfp->fp_pid != PID_FREE) {
00244                 rip = get_inode(root_dev, ROOT_INODE);
00245                 dup_inode(rip);
00246                 rfp->fp_rootdir = rip;
00247                 rfp->fp_workdir = rip;
00248         } else  rfp->fp_endpoint = NONE;
00249   }
00250 }
00251 
00252 /*===========================================================================*
00253  *                              init_root                                    *
00254  *===========================================================================*/
00255 PRIVATE void init_root()
00256 {
00257   int bad;
00258   register struct super_block *sp;
00259   register struct inode *rip = NIL_INODE;
00260   int s;
00261 
00262   /* Open the root device. */
00263   root_dev = DEV_IMGRD;
00264   if ((s=dev_open(root_dev, FS_PROC_NR, R_BIT|W_BIT)) != OK)
00265         panic(__FILE__,"Cannot open root device", s);
00266 
00267 #if ENABLE_CACHE2
00268   /* The RAM disk is a second level block cache while not otherwise used. */
00269   init_cache2(ram_size);
00270 #endif
00271 
00272   /* Initialize the super_block table. */
00273   for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
00274         sp->s_dev = NO_DEV;
00275 
00276   /* Read in super_block for the root file system. */
00277   sp = &super_block[0];
00278   sp->s_dev = root_dev;
00279 
00280   /* Check super_block for consistency. */
00281   bad = (read_super(sp) != OK);
00282   if (!bad) {
00283         rip = get_inode(root_dev, ROOT_INODE);  /* inode for root dir */
00284         if ( (rip->i_mode & I_TYPE) != I_DIRECTORY || rip->i_nlinks < 3) bad++;
00285   }
00286   if (bad) panic(__FILE__,"Invalid root file system", NO_NUM);
00287 
00288   sp->s_imount = rip;
00289   dup_inode(rip);
00290   sp->s_isup = rip;
00291   sp->s_rd_only = 0;
00292   return;
00293 }

Generated on Fri Apr 14 22:56:41 2006 for minix by  doxygen 1.4.6