1 /* This file contains the SFFS initialization code and message loop. 2 * 3 * The entry points into this file are: 4 * sffs_init initialization 5 * sffs_signal signal handler 6 * sffs_loop main message loop 7 * 8 * Created: 9 * April 2009 (D.C. van Moolenbroek) 10 */ 11 12 #include "inc.h" 13 14 /*===========================================================================* 15 * sffs_init * 16 *===========================================================================*/ 17 int sffs_init(char *name, const struct sffs_table *table, 18 struct sffs_params *params) 19 { 20 /* Initialize this file server. Called at startup time. 21 */ 22 int i; 23 24 /* Make sure that the given path prefix doesn't end with a slash. */ 25 i = strlen(params->p_prefix); 26 while (i > 0 && params->p_prefix[i - 1] == '/') i--; 27 params->p_prefix[i] = 0; 28 29 state.s_mounted = FALSE; 30 state.s_signaled = FALSE; 31 32 sffs_name = name; 33 sffs_table = table; 34 sffs_params = params; 35 36 return OK; 37 } 38 39 /*===========================================================================* 40 * sffs_signal * 41 *===========================================================================*/ 42 void sffs_signal(int signo) 43 { 44 45 /* Only check for termination signal, ignore anything else. */ 46 if (signo != SIGTERM) return; 47 48 /* We can now terminate if we have also been unmounted. */ 49 state.s_signaled = TRUE; 50 51 if (state.s_mounted) { 52 dprintf(("%s: got SIGTERM, still mounted\n", sffs_name)); 53 } else { 54 dprintf(("%s: got SIGTERM, shutting down\n", sffs_name)); 55 56 /* Break out of the main loop, giving the main program the chance to 57 * perform further cleanup. This causes sef_receive() to return with 58 * an EINTR error code. 59 */ 60 sef_cancel(); 61 } 62 } 63 64 /*===========================================================================* 65 * get_work * 66 *===========================================================================*/ 67 static int get_work(endpoint_t *who_e) 68 { 69 /* Receive a request message from VFS. Return TRUE if a new message is ready 70 * to be processed, or FALSE if sef_stop() was called from the signal handler. 71 */ 72 int r; 73 74 if ((r = sef_receive(ANY, &m_in)) != OK) { 75 if (r != EINTR) 76 panic("receive failed: %d", r); 77 78 return FALSE; 79 } 80 81 *who_e = m_in.m_source; 82 return TRUE; 83 } 84 85 /*===========================================================================* 86 * send_reply * 87 *===========================================================================*/ 88 static void send_reply( 89 int err, /* resulting error code */ 90 int transid 91 ) 92 { 93 /* Send a reply message to the requesting party, with the given error code. 94 */ 95 int r; 96 97 m_out.m_type = err; 98 if (IS_VFS_FS_TRANSID(transid)) { 99 /* If a transaction ID was set, reset it */ 100 m_out.m_type = TRNS_ADD_ID(m_out.m_type, transid); 101 } 102 if ((r = ipc_send(m_in.m_source, &m_out)) != OK) 103 printf("%s: ipc_send failed (%d)\n", sffs_name, r); 104 } 105 106 /*===========================================================================* 107 * sffs_loop * 108 *===========================================================================*/ 109 void sffs_loop(void) 110 { 111 /* The main function of this file server. After initializing, loop, receiving 112 * one request from VFS at a time, processing it, and sending a reply back to 113 * VFS. Termination occurs when we both have been unmounted and have received 114 * a termination signal. 115 */ 116 endpoint_t who_e; 117 int call_nr, err, transid; 118 119 while (state.s_mounted || !state.s_signaled) { 120 if (!get_work(&who_e)) 121 continue; /* Recheck running conditions */ 122 123 transid = TRNS_GET_ID(m_in.m_type); 124 m_in.m_type = TRNS_DEL_ID(m_in.m_type); 125 if (m_in.m_type == 0) { 126 assert(!IS_VFS_FS_TRANSID(transid)); 127 m_in.m_type = transid; /* Backwards compat. */ 128 transid = 0; 129 } else 130 assert(IS_VFS_FS_TRANSID(transid)); 131 132 call_nr = m_in.m_type; 133 if (who_e != VFS_PROC_NR) { 134 continue; 135 } 136 137 if (state.s_mounted || call_nr == REQ_READSUPER) { 138 call_nr -= FS_BASE; 139 140 dprintf(("%s: call %d\n", sffs_name, call_nr)); 141 142 if (call_nr >= 0 && call_nr < NREQS) { 143 err = (*call_vec[call_nr])(); 144 } else { 145 err = ENOSYS; 146 } 147 148 dprintf(("%s: call %d result %d\n", sffs_name, call_nr, err)); 149 } 150 else err = EINVAL; 151 152 send_reply(err, transid); 153 } 154 } 155