xref: /minix3/minix/lib/libfsdriver/fsdriver.c (revision 289b04677a1b234d09a045a727f5e614a6c8d716)
189c9de7dSDavid van Moolenbroek 
289c9de7dSDavid van Moolenbroek #include "fsdriver.h"
389c9de7dSDavid van Moolenbroek 
489c9de7dSDavid van Moolenbroek /* Library-local variables. */
5*289b0467SDavid van Moolenbroek dev_t fsdriver_device;
689c9de7dSDavid van Moolenbroek ino_t fsdriver_root;
789c9de7dSDavid van Moolenbroek int fsdriver_mounted = FALSE;
889c9de7dSDavid van Moolenbroek 
989c9de7dSDavid van Moolenbroek static int fsdriver_running;
1089c9de7dSDavid van Moolenbroek 
1189c9de7dSDavid van Moolenbroek /*
1289c9de7dSDavid van Moolenbroek  * Process an incoming VFS request, and send a reply.  If the message is not
1389c9de7dSDavid van Moolenbroek  * a file system request from VFS, pass it on to the generic message handler.
1489c9de7dSDavid van Moolenbroek  * Multithreaded file systems should indicate that the reply is to be sent to
1589c9de7dSDavid van Moolenbroek  * VFS asynchronously.
1689c9de7dSDavid van Moolenbroek  */
1789c9de7dSDavid van Moolenbroek void
fsdriver_process(const struct fsdriver * __restrict fdp,const message * __restrict m_ptr,int ipc_status,int asyn_reply)1889c9de7dSDavid van Moolenbroek fsdriver_process(const struct fsdriver * __restrict fdp,
1989c9de7dSDavid van Moolenbroek 	const message * __restrict m_ptr, int ipc_status, int asyn_reply)
2089c9de7dSDavid van Moolenbroek {
2189c9de7dSDavid van Moolenbroek 	message m_out;
2289c9de7dSDavid van Moolenbroek 	unsigned int call_nr;
2389c9de7dSDavid van Moolenbroek 	int r, transid;
2489c9de7dSDavid van Moolenbroek 
2589c9de7dSDavid van Moolenbroek 	/* Is this a file system request at all? */
2689c9de7dSDavid van Moolenbroek 	if (is_ipc_notify(ipc_status) || m_ptr->m_source != VFS_PROC_NR) {
2789c9de7dSDavid van Moolenbroek 		if (fdp->fdr_other != NULL)
2889c9de7dSDavid van Moolenbroek 			fdp->fdr_other(m_ptr, ipc_status);
2989c9de7dSDavid van Moolenbroek 
3089c9de7dSDavid van Moolenbroek 		return; /* do not send a reply */
3189c9de7dSDavid van Moolenbroek 	}
3289c9de7dSDavid van Moolenbroek 
3389c9de7dSDavid van Moolenbroek 	/* Call the appropriate function. */
3489c9de7dSDavid van Moolenbroek 	transid = TRNS_GET_ID(m_ptr->m_type);
3589c9de7dSDavid van Moolenbroek 	call_nr = TRNS_DEL_ID(m_ptr->m_type);
3689c9de7dSDavid van Moolenbroek 
3789c9de7dSDavid van Moolenbroek 	memset(&m_out, 0, sizeof(m_out));
3889c9de7dSDavid van Moolenbroek 
3989c9de7dSDavid van Moolenbroek 	if (fsdriver_mounted || call_nr == REQ_READSUPER) {
4089c9de7dSDavid van Moolenbroek 		call_nr -= FS_BASE;	/* unsigned; wrapping is intended */
4189c9de7dSDavid van Moolenbroek 
4289c9de7dSDavid van Moolenbroek 		if (call_nr < NREQS && fsdriver_callvec[call_nr] != NULL)
4389c9de7dSDavid van Moolenbroek 			r = (fsdriver_callvec[call_nr])(fdp, m_ptr, &m_out);
4489c9de7dSDavid van Moolenbroek 		else
4589c9de7dSDavid van Moolenbroek 			r = ENOSYS;
4689c9de7dSDavid van Moolenbroek 	} else
4789c9de7dSDavid van Moolenbroek 		r = EINVAL;
4889c9de7dSDavid van Moolenbroek 
4989c9de7dSDavid van Moolenbroek 	/* Send a reply. */
5089c9de7dSDavid van Moolenbroek 	m_out.m_type = TRNS_ADD_ID(r, transid);
5189c9de7dSDavid van Moolenbroek 
5289c9de7dSDavid van Moolenbroek 	if (asyn_reply)
5389c9de7dSDavid van Moolenbroek 		r = asynsend(m_ptr->m_source, &m_out);
5489c9de7dSDavid van Moolenbroek 	else
5589c9de7dSDavid van Moolenbroek 		r = ipc_send(m_ptr->m_source, &m_out);
5689c9de7dSDavid van Moolenbroek 
5789c9de7dSDavid van Moolenbroek 	if (r != OK)
5889c9de7dSDavid van Moolenbroek 		printf("fsdriver: sending reply failed (%d)\n", r);
5989c9de7dSDavid van Moolenbroek 
6089c9de7dSDavid van Moolenbroek 	if (fdp->fdr_postcall != NULL)
6189c9de7dSDavid van Moolenbroek 		fdp->fdr_postcall();
6289c9de7dSDavid van Moolenbroek }
6389c9de7dSDavid van Moolenbroek 
6489c9de7dSDavid van Moolenbroek /*
6589c9de7dSDavid van Moolenbroek  * Terminate the file server as soon as the file system has been unmounted.
6689c9de7dSDavid van Moolenbroek  */
6789c9de7dSDavid van Moolenbroek void
fsdriver_terminate(void)6889c9de7dSDavid van Moolenbroek fsdriver_terminate(void)
6989c9de7dSDavid van Moolenbroek {
7089c9de7dSDavid van Moolenbroek 
7189c9de7dSDavid van Moolenbroek 	fsdriver_running = FALSE;
7289c9de7dSDavid van Moolenbroek 
7389c9de7dSDavid van Moolenbroek 	sef_cancel();
7489c9de7dSDavid van Moolenbroek }
7589c9de7dSDavid van Moolenbroek 
7689c9de7dSDavid van Moolenbroek /*
7789c9de7dSDavid van Moolenbroek  * Main program of any file server task.
7889c9de7dSDavid van Moolenbroek  */
7989c9de7dSDavid van Moolenbroek void
fsdriver_task(struct fsdriver * fdp)8089c9de7dSDavid van Moolenbroek fsdriver_task(struct fsdriver * fdp)
8189c9de7dSDavid van Moolenbroek {
8289c9de7dSDavid van Moolenbroek 	message mess;
8389c9de7dSDavid van Moolenbroek 	int r, ipc_status;
8489c9de7dSDavid van Moolenbroek 
8589c9de7dSDavid van Moolenbroek 	fsdriver_running = TRUE;
8689c9de7dSDavid van Moolenbroek 
8789c9de7dSDavid van Moolenbroek 	while (fsdriver_running || fsdriver_mounted) {
8889c9de7dSDavid van Moolenbroek 		if ((r = sef_receive_status(ANY, &mess, &ipc_status)) != OK) {
8989c9de7dSDavid van Moolenbroek 			if (r == EINTR)
9089c9de7dSDavid van Moolenbroek 				continue;	/* sef_cancel() was called */
9189c9de7dSDavid van Moolenbroek 
9289c9de7dSDavid van Moolenbroek 			panic("fsdriver: sef_receive_status failed: %d", r);
9389c9de7dSDavid van Moolenbroek 		}
9489c9de7dSDavid van Moolenbroek 
9589c9de7dSDavid van Moolenbroek 		fsdriver_process(fdp, &mess, ipc_status, FALSE /*asyn_reply*/);
9689c9de7dSDavid van Moolenbroek 	}
9789c9de7dSDavid van Moolenbroek }
98