xref: /minix/minix/lib/libfsdriver/fsdriver.c (revision 83133719)
1 
2 #include "fsdriver.h"
3 
4 /* Library-local variables. */
5 ino_t fsdriver_root;
6 int fsdriver_mounted = FALSE;
7 
8 static int fsdriver_running;
9 
10 /*
11  * Process an incoming VFS request, and send a reply.  If the message is not
12  * a file system request from VFS, pass it on to the generic message handler.
13  * Multithreaded file systems should indicate that the reply is to be sent to
14  * VFS asynchronously.
15  */
16 void
17 fsdriver_process(const struct fsdriver * __restrict fdp,
18 	const message * __restrict m_ptr, int ipc_status, int asyn_reply)
19 {
20 	message m_out;
21 	unsigned int call_nr;
22 	int r, transid;
23 
24 	/* Is this a file system request at all? */
25 	if (is_ipc_notify(ipc_status) || m_ptr->m_source != VFS_PROC_NR) {
26 		if (fdp->fdr_other != NULL)
27 			fdp->fdr_other(m_ptr, ipc_status);
28 
29 		return; /* do not send a reply */
30 	}
31 
32 	/* Call the appropriate function. */
33 	transid = TRNS_GET_ID(m_ptr->m_type);
34 	call_nr = TRNS_DEL_ID(m_ptr->m_type);
35 
36 	memset(&m_out, 0, sizeof(m_out));
37 
38 	if (fsdriver_mounted || call_nr == REQ_READSUPER) {
39 		call_nr -= FS_BASE;	/* unsigned; wrapping is intended */
40 
41 		if (call_nr < NREQS && fsdriver_callvec[call_nr] != NULL)
42 			r = (fsdriver_callvec[call_nr])(fdp, m_ptr, &m_out);
43 		else
44 			r = ENOSYS;
45 	} else
46 		r = EINVAL;
47 
48 	/* Send a reply. */
49 	m_out.m_type = TRNS_ADD_ID(r, transid);
50 
51 	if (asyn_reply)
52 		r = asynsend(m_ptr->m_source, &m_out);
53 	else
54 		r = ipc_send(m_ptr->m_source, &m_out);
55 
56 	if (r != OK)
57 		printf("fsdriver: sending reply failed (%d)\n", r);
58 
59 	if (fdp->fdr_postcall != NULL)
60 		fdp->fdr_postcall();
61 }
62 
63 /*
64  * Terminate the file server as soon as the file system has been unmounted.
65  */
66 void
67 fsdriver_terminate(void)
68 {
69 
70 	fsdriver_running = FALSE;
71 
72 	sef_cancel();
73 }
74 
75 /*
76  * Main program of any file server task.
77  */
78 void
79 fsdriver_task(struct fsdriver * fdp)
80 {
81 	message mess;
82 	int r, ipc_status;
83 
84 	fsdriver_running = TRUE;
85 
86 	while (fsdriver_running || fsdriver_mounted) {
87 		if ((r = sef_receive_status(ANY, &mess, &ipc_status)) != OK) {
88 			if (r == EINTR)
89 				continue;	/* sef_cancel() was called */
90 
91 			panic("fsdriver: sef_receive_status failed: %d", r);
92 		}
93 
94 		fsdriver_process(fdp, &mess, ipc_status, FALSE /*asyn_reply*/);
95 	}
96 }
97