xref: /minix/minix/lib/libvtreefs/vtreefs.c (revision 7f5f010b)
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