1 /* VTreeFS - vtreefs.c - by Alen Stojanov and David van Moolenbroek */ 2 3 #include "inc.h" 4 5 static int get_work(void); 6 static void send_reply(int err, int transid); 7 static void got_signal(int signal); 8 9 static unsigned int inodes; 10 static struct inode_stat *root_stat; 11 static index_t root_entries; 12 13 /*===========================================================================* 14 * init_server * 15 *===========================================================================*/ 16 static int init_server(int UNUSED(type), sef_init_info_t *UNUSED(info)) 17 { 18 /* Initialize internal state, and register with VFS. 19 */ 20 21 /* Initialize the virtual tree. */ 22 init_inodes(inodes, root_stat, root_entries); 23 24 /* Do not yet allow any requests except REQ_READSUPER. */ 25 fs_mounted = FALSE; 26 27 return OK; 28 } 29 30 /*===========================================================================* 31 * sef_local_startup * 32 *===========================================================================*/ 33 static void sef_local_startup(void) 34 { 35 sef_setcb_init_fresh(init_server); 36 sef_setcb_init_restart(init_server); 37 38 sef_setcb_signal_handler(got_signal); 39 40 /* No support for live update yet. */ 41 42 sef_startup(); 43 } 44 45 /*===========================================================================* 46 * start_vtreefs * 47 *===========================================================================*/ 48 void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes, 49 struct inode_stat *stat, index_t nr_indexed_entries) 50 { 51 /* This is the main routine of this service. The main loop consists of 52 * three major activities: getting new work, processing the work, and 53 * sending the reply. The loop exits when the process is signaled to 54 * exit; due to limitations of SEF, it can not return to the caller. 55 */ 56 int call_nr, err, transid; 57 58 /* Use global variables to work around the inability to pass parameters 59 * through SEF to the initialization function.. 60 */ 61 vtreefs_hooks = hooks; 62 inodes = nr_inodes; 63 root_stat = stat; 64 root_entries = nr_indexed_entries; 65 66 sef_local_startup(); 67 68 for (;;) { 69 get_work(); 70 71 transid = TRNS_GET_ID(fs_m_in.m_type); 72 fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type); 73 if (fs_m_in.m_type == 0) { 74 assert(!IS_VFS_FS_TRANSID(transid)); 75 fs_m_in.m_type = transid; /* Backwards compat. */ 76 transid = 0; 77 } else 78 assert(IS_VFS_FS_TRANSID(transid)); 79 80 call_nr = fs_m_in.m_type; 81 82 if (fs_m_in.m_source != VFS_PROC_NR) { 83 if (vtreefs_hooks->message_hook != NULL) { 84 /* If the request is not among the recognized 85 * requests, call the message hook. 86 */ 87 vtreefs_hooks->message_hook(&fs_m_in); 88 } 89 90 continue; 91 } 92 93 if (fs_mounted || call_nr == REQ_READSUPER) { 94 call_nr -= FS_BASE; 95 96 if (call_nr >= 0 && call_nr < NREQS) { 97 err = (*fs_call_vec[call_nr])(); 98 } else { 99 err = ENOSYS; 100 } 101 } 102 else err = EINVAL; 103 104 send_reply(err, transid); 105 } 106 } 107 108 /*===========================================================================* 109 * get_work * 110 *===========================================================================*/ 111 static int get_work(void) 112 { 113 /* Retrieve work. Return the call number. 114 */ 115 int r; 116 117 if ((r = sef_receive(ANY, &fs_m_in)) != OK) 118 panic("receive failed: %d", r); 119 120 return fs_m_in.m_type; 121 } 122 123 /*===========================================================================* 124 * send_reply * 125 *===========================================================================*/ 126 static void send_reply(int err, int transid) 127 { 128 /* Send a reply to the caller. 129 */ 130 int r; 131 132 fs_m_out.m_type = err; 133 if (IS_VFS_FS_TRANSID(transid)) { 134 fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid); 135 } 136 137 if ((r = ipc_send(fs_m_in.m_source, &fs_m_out)) != OK) 138 panic("unable to send reply: %d", r); 139 } 140 141 /*===========================================================================* 142 * got_signal * 143 *===========================================================================*/ 144 static void got_signal(int signal) 145 { 146 /* We received a signal. If it is a termination signal, and the file 147 * system has already been unmounted, clean up and exit. 148 */ 149 150 if (signal != SIGTERM) 151 return; 152 153 if (fs_mounted) 154 return; 155 156 cleanup_inodes(); 157 158 exit(0); 159 } 160