1 #include "fs.h" 2 #include <assert.h> 3 #include <minix/callnr.h> 4 #include <signal.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <unistd.h> 8 #include <minix/dmap.h> 9 #include <minix/endpoint.h> 10 #include <minix/vfsif.h> 11 #include <minix/optset.h> 12 #include "buf.h" 13 #include "inode.h" 14 15 /* Declare some local functions. */ 16 static void get_work(message *m_in); 17 static void reply(endpoint_t who, message *m_out); 18 19 /* SEF functions and variables. */ 20 static void sef_local_startup(void); 21 static int sef_cb_init_fresh(int type, sef_init_info_t *info); 22 static void sef_cb_signal_handler(int signo); 23 24 EXTERN int env_argc; 25 EXTERN char **env_argv; 26 27 static struct optset optset_table[] = { 28 { "sb", OPT_INT, &opt.block_with_super, 0 }, 29 { "orlov", OPT_BOOL, &opt.use_orlov, TRUE }, 30 { "oldalloc", OPT_BOOL, &opt.use_orlov, FALSE }, 31 { "mfsalloc", OPT_BOOL, &opt.mfsalloc, TRUE }, 32 { "reserved", OPT_BOOL, &opt.use_reserved_blocks, TRUE }, 33 { "prealloc", OPT_BOOL, &opt.use_prealloc, TRUE }, 34 { "noprealloc", OPT_BOOL, &opt.use_prealloc, FALSE }, 35 { NULL, 0, NULL, 0 } 36 }; 37 38 /*===========================================================================* 39 * main * 40 *===========================================================================*/ 41 int main(int argc, char *argv[]) 42 { 43 /* This is the main routine of this service. The main loop consists of 44 * three major activities: getting new work, processing the work, and 45 * sending the reply. The loop never terminates, unless a panic occurs. 46 */ 47 int error = OK, ind, transid; 48 unsigned short test_endian = 1; 49 50 /* SEF local startup. */ 51 env_setargs(argc, argv); 52 sef_local_startup(); 53 54 le_CPU = (*(unsigned char *) &test_endian == 0 ? 0 : 1); 55 56 /* Server isn't tested on big endian CPU */ 57 ASSERT(le_CPU == 1); 58 59 while(!unmountdone || !exitsignaled) { 60 endpoint_t src; 61 62 /* Wait for request message. */ 63 get_work(&fs_m_in); 64 65 transid = TRNS_GET_ID(fs_m_in.m_type); 66 fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type); 67 if (fs_m_in.m_type == 0) { 68 assert(!IS_VFS_FS_TRANSID(transid)); 69 fs_m_in.m_type = transid; /* Backwards compat. */ 70 transid = 0; 71 } else 72 assert(IS_VFS_FS_TRANSID(transid)); 73 74 src = fs_m_in.m_source; 75 caller_uid = INVAL_UID; /* To trap errors */ 76 caller_gid = INVAL_GID; 77 req_nr = fs_m_in.m_type; 78 79 if (req_nr < FS_BASE) { 80 fs_m_in.m_type += FS_BASE; 81 req_nr = fs_m_in.m_type; 82 } 83 ind = req_nr - FS_BASE; 84 85 if (ind < 0 || ind >= NREQS) { 86 printf("mfs: bad request %d\n", req_nr); 87 printf("ind = %d\n", ind); 88 error = EINVAL; 89 } else { 90 error = (*fs_call_vec[ind])(); 91 } 92 93 fs_m_out.m_type = error; 94 if (IS_VFS_FS_TRANSID(transid)) { 95 /* If a transaction ID was set, reset it */ 96 fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid); 97 } 98 reply(src, &fs_m_out); 99 100 if (error == OK) 101 read_ahead(); /* do block read ahead */ 102 } 103 104 return 0; 105 } 106 107 /*===========================================================================* 108 * sef_local_startup * 109 *===========================================================================*/ 110 static void sef_local_startup() 111 { 112 /* Register init callbacks. */ 113 sef_setcb_init_fresh(sef_cb_init_fresh); 114 sef_setcb_init_restart(sef_cb_init_fail); 115 116 /* No live update support for now. */ 117 118 /* Register signal callbacks. */ 119 sef_setcb_signal_handler(sef_cb_signal_handler); 120 121 /* Let SEF perform startup. */ 122 sef_startup(); 123 } 124 125 /*===========================================================================* 126 * sef_cb_init_fresh * 127 *===========================================================================*/ 128 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) 129 { 130 /* Initialize the Minix file server. */ 131 int i; 132 133 /* Defaults */ 134 opt.use_orlov = TRUE; 135 opt.mfsalloc = FALSE; 136 opt.use_reserved_blocks = FALSE; 137 opt.block_with_super = 0; 138 opt.use_prealloc = FALSE; 139 140 /* If we have been given an options string, parse options from there. */ 141 for (i = 1; i < env_argc - 1; i++) 142 if (!strcmp(env_argv[i], "-o")) 143 optset_parse(optset_table, env_argv[++i]); 144 145 lmfs_may_use_vmcache(1); 146 147 /* Init inode table */ 148 for (i = 0; i < NR_INODES; ++i) { 149 inode[i].i_count = 0; 150 cch[i] = 0; 151 } 152 153 init_inode_cache(); 154 155 /* just a small number before we find out the block size at mount time */ 156 lmfs_buf_pool(10); 157 158 return(OK); 159 } 160 161 /*===========================================================================* 162 * sef_cb_signal_handler * 163 *===========================================================================*/ 164 static void sef_cb_signal_handler(int signo) 165 { 166 /* Only check for termination signal, ignore anything else. */ 167 if (signo != SIGTERM) return; 168 169 exitsignaled = 1; 170 (void) fs_sync(); 171 172 /* If unmounting has already been performed, exit immediately. 173 * We might not get another message. 174 */ 175 if (unmountdone) exit(0); 176 } 177 178 /*===========================================================================* 179 * get_work * 180 *===========================================================================*/ 181 static void get_work(m_in) 182 message *m_in; /* pointer to message */ 183 { 184 int r, srcok = 0; 185 endpoint_t src; 186 187 do { 188 if ((r = sef_receive(ANY, m_in)) != OK) /* wait for message */ 189 panic("sef_receive failed: %d", r); 190 src = m_in->m_source; 191 192 if(src == VFS_PROC_NR) { 193 if(unmountdone) 194 printf("ext2: unmounted: unexpected message from FS\n"); 195 else 196 srcok = 1; /* Normal FS request. */ 197 198 } else 199 printf("ext2: unexpected source %d\n", src); 200 } while(!srcok); 201 202 assert((src == VFS_PROC_NR && !unmountdone)); 203 } 204 205 206 /*===========================================================================* 207 * reply * 208 *===========================================================================*/ 209 static void reply( 210 endpoint_t who, 211 message *m_out /* report result */ 212 ) 213 { 214 if (OK != ipc_send(who, m_out)) /* send the message */ 215 printf("ext2(%d) was unable to send reply\n", sef_self()); 216 } 217