xref: /minix/minix/fs/ext2/main.c (revision 433d6423)
1 #include "fs.h"
2 #include <assert.h>
3 #include <minix/callnr.h>
4 #include <signal.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <minix/dmap.h>
9 #include <minix/endpoint.h>
10 #include <minix/vfsif.h>
11 #include <minix/optset.h>
12 #include "buf.h"
13 #include "inode.h"
14 
15 /* Declare some local functions. */
16 static void get_work(message *m_in);
17 static void reply(endpoint_t who, message *m_out);
18 
19 /* SEF functions and variables. */
20 static void sef_local_startup(void);
21 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
22 static void sef_cb_signal_handler(int signo);
23 
24 EXTERN int env_argc;
25 EXTERN char **env_argv;
26 
27 static struct optset optset_table[] = {
28   { "sb",		OPT_INT,    &opt.block_with_super,	0	},
29   { "orlov",		OPT_BOOL,   &opt.use_orlov,		TRUE    },
30   { "oldalloc",		OPT_BOOL,   &opt.use_orlov,		FALSE   },
31   { "mfsalloc",		OPT_BOOL,   &opt.mfsalloc,		TRUE    },
32   { "reserved",		OPT_BOOL,   &opt.use_reserved_blocks,	TRUE    },
33   { "prealloc",		OPT_BOOL,   &opt.use_prealloc, 		TRUE	},
34   { "noprealloc",	OPT_BOOL,   &opt.use_prealloc, 		FALSE	},
35   { NULL,		0,	    NULL,			0								}
36 };
37 
38 /*===========================================================================*
39  *				main                                         *
40  *===========================================================================*/
41 int main(int argc, char *argv[])
42 {
43 /* This is the main routine of this service. The main loop consists of
44  * three major activities: getting new work, processing the work, and
45  * sending the reply. The loop never terminates, unless a panic occurs.
46  */
47   int error = OK, ind, transid;
48   unsigned short test_endian = 1;
49 
50   /* SEF local startup. */
51   env_setargs(argc, argv);
52   sef_local_startup();
53 
54   le_CPU = (*(unsigned char *) &test_endian == 0 ? 0 : 1);
55 
56   /* Server isn't tested on big endian CPU */
57   ASSERT(le_CPU == 1);
58 
59   while(!unmountdone || !exitsignaled) {
60 	endpoint_t src;
61 
62 	/* Wait for request message. */
63 	get_work(&fs_m_in);
64 
65 	transid = TRNS_GET_ID(fs_m_in.m_type);
66 	fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type);
67 	if (fs_m_in.m_type == 0) {
68 		assert(!IS_VFS_FS_TRANSID(transid));
69 		fs_m_in.m_type = transid;       /* Backwards compat. */
70 		transid = 0;
71 	} else
72 		assert(IS_VFS_FS_TRANSID(transid));
73 
74 	src = fs_m_in.m_source;
75 	caller_uid = INVAL_UID;	/* To trap errors */
76 	caller_gid = INVAL_GID;
77 	req_nr = fs_m_in.m_type;
78 
79 	if (req_nr < FS_BASE) {
80 		fs_m_in.m_type += FS_BASE;
81 		req_nr = fs_m_in.m_type;
82 	}
83 	ind = req_nr - FS_BASE;
84 
85 	if (ind < 0 || ind >= NREQS) {
86 		printf("mfs: bad request %d\n", req_nr);
87 		printf("ind = %d\n", ind);
88 		error = EINVAL;
89 	} else {
90 		error = (*fs_call_vec[ind])();
91 	}
92 
93 	fs_m_out.m_type = error;
94 	if (IS_VFS_FS_TRANSID(transid)) {
95 		/* If a transaction ID was set, reset it */
96 		fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid);
97 	}
98 	reply(src, &fs_m_out);
99 
100 	if (error == OK)
101 		read_ahead(); /* do block read ahead */
102   }
103 
104   return 0;
105 }
106 
107 /*===========================================================================*
108  *			       sef_local_startup			     *
109  *===========================================================================*/
110 static void sef_local_startup()
111 {
112   /* Register init callbacks. */
113   sef_setcb_init_fresh(sef_cb_init_fresh);
114   sef_setcb_init_restart(sef_cb_init_fail);
115 
116   /* No live update support for now. */
117 
118   /* Register signal callbacks. */
119   sef_setcb_signal_handler(sef_cb_signal_handler);
120 
121   /* Let SEF perform startup. */
122   sef_startup();
123 }
124 
125 /*===========================================================================*
126  *		            sef_cb_init_fresh                                *
127  *===========================================================================*/
128 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
129 {
130 /* Initialize the Minix file server. */
131   int i;
132 
133   /* Defaults */
134   opt.use_orlov = TRUE;
135   opt.mfsalloc = FALSE;
136   opt.use_reserved_blocks = FALSE;
137   opt.block_with_super = 0;
138   opt.use_prealloc = FALSE;
139 
140   /* If we have been given an options string, parse options from there. */
141   for (i = 1; i < env_argc - 1; i++)
142 	if (!strcmp(env_argv[i], "-o"))
143 		optset_parse(optset_table, env_argv[++i]);
144 
145   lmfs_may_use_vmcache(1);
146 
147   /* Init inode table */
148   for (i = 0; i < NR_INODES; ++i) {
149 	inode[i].i_count = 0;
150 	cch[i] = 0;
151   }
152 
153   init_inode_cache();
154 
155   /* just a small number before we find out the block size at mount time */
156   lmfs_buf_pool(10);
157 
158   return(OK);
159 }
160 
161 /*===========================================================================*
162  *		           sef_cb_signal_handler                             *
163  *===========================================================================*/
164 static void sef_cb_signal_handler(int signo)
165 {
166   /* Only check for termination signal, ignore anything else. */
167   if (signo != SIGTERM) return;
168 
169   exitsignaled = 1;
170   (void) fs_sync();
171 
172   /* If unmounting has already been performed, exit immediately.
173    * We might not get another message.
174    */
175   if (unmountdone) exit(0);
176 }
177 
178 /*===========================================================================*
179  *				get_work				     *
180  *===========================================================================*/
181 static void get_work(m_in)
182 message *m_in;				/* pointer to message */
183 {
184   int r, srcok = 0;
185   endpoint_t src;
186 
187   do {
188 	if ((r = sef_receive(ANY, m_in)) != OK) 	/* wait for message */
189 		panic("sef_receive failed: %d", r);
190 	src = m_in->m_source;
191 
192 	if(src == VFS_PROC_NR) {
193 		if(unmountdone)
194 			printf("ext2: unmounted: unexpected message from FS\n");
195 		else
196 			srcok = 1;		/* Normal FS request. */
197 
198 	} else
199 		printf("ext2: unexpected source %d\n", src);
200   } while(!srcok);
201 
202    assert((src == VFS_PROC_NR && !unmountdone));
203 }
204 
205 
206 /*===========================================================================*
207  *				reply					     *
208  *===========================================================================*/
209 static void reply(
210   endpoint_t who,
211   message *m_out                       	/* report result */
212 )
213 {
214   if (OK != ipc_send(who, m_out))    /* send the message */
215 	printf("ext2(%d) was unable to send reply\n", sef_self());
216 }
217