xref: /minix3/minix/lib/libsffs/main.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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