160 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* VTreeFS - vtreefs.c - by Alen Stojanov and David van Moolenbroek */
 | 
						|
 | 
						|
#include "inc.h"
 | 
						|
 | 
						|
static int get_work(void);
 | 
						|
static void send_reply(int err, int transid);
 | 
						|
static void got_signal(int signal);
 | 
						|
 | 
						|
static unsigned int inodes;
 | 
						|
static struct inode_stat *root_stat;
 | 
						|
static index_t root_entries;
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				init_server				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static int init_server(int UNUSED(type), sef_init_info_t *UNUSED(info))
 | 
						|
{
 | 
						|
	/* Initialize internal state, and register with VFS.
 | 
						|
	 */
 | 
						|
 | 
						|
	/* Initialize the virtual tree. */
 | 
						|
	init_inodes(inodes, root_stat, root_entries);
 | 
						|
 | 
						|
	/* Do not yet allow any requests except REQ_READSUPER. */
 | 
						|
	fs_mounted = FALSE;
 | 
						|
 | 
						|
	return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				sef_local_startup			     *
 | 
						|
 *===========================================================================*/
 | 
						|
static void sef_local_startup(void)
 | 
						|
{
 | 
						|
	sef_setcb_init_fresh(init_server);
 | 
						|
	sef_setcb_init_restart(init_server);
 | 
						|
 | 
						|
	sef_setcb_signal_handler(got_signal);
 | 
						|
 | 
						|
	/* No support for live update yet. */
 | 
						|
 | 
						|
	sef_startup();
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				start_vtreefs				     *
 | 
						|
 *===========================================================================*/
 | 
						|
void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes,
 | 
						|
		struct inode_stat *stat, index_t nr_indexed_entries)
 | 
						|
{
 | 
						|
	/* This is the main routine of this service. The main loop consists of
 | 
						|
	 * three major activities: getting new work, processing the work, and
 | 
						|
	 * sending the reply. The loop exits when the process is signaled to
 | 
						|
	 * exit; due to limitations of SEF, it can not return to the caller.
 | 
						|
	 */
 | 
						|
	int call_nr, err, transid;
 | 
						|
 | 
						|
	/* Use global variables to work around the inability to pass parameters
 | 
						|
	 * through SEF to the initialization function..
 | 
						|
	 */
 | 
						|
	vtreefs_hooks = hooks;
 | 
						|
	inodes = nr_inodes;
 | 
						|
	root_stat = stat;
 | 
						|
	root_entries = nr_indexed_entries;
 | 
						|
 | 
						|
	sef_local_startup();
 | 
						|
 | 
						|
	for (;;) {
 | 
						|
		get_work();
 | 
						|
 | 
						|
		transid = TRNS_GET_ID(fs_m_in.m_type);
 | 
						|
		fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type);
 | 
						|
		if (fs_m_in.m_type == 0) {
 | 
						|
			assert(!IS_VFS_FS_TRANSID(transid));
 | 
						|
			fs_m_in.m_type = transid;	/* Backwards compat. */
 | 
						|
			transid = 0;
 | 
						|
		} else
 | 
						|
			assert(IS_VFS_FS_TRANSID(transid));
 | 
						|
 | 
						|
		call_nr = fs_m_in.m_type;
 | 
						|
 | 
						|
		if (fs_m_in.m_source != VFS_PROC_NR) {
 | 
						|
			if (vtreefs_hooks->message_hook != NULL) {
 | 
						|
				/* If the request is not among the recognized
 | 
						|
				 * requests, call the message hook.
 | 
						|
				 */
 | 
						|
				vtreefs_hooks->message_hook(&fs_m_in);
 | 
						|
			}
 | 
						|
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		if (fs_mounted || call_nr == REQ_READSUPER) {
 | 
						|
			call_nr -= VFS_BASE;
 | 
						|
 | 
						|
			if (call_nr >= 0 && call_nr < NREQS) {
 | 
						|
				err = (*fs_call_vec[call_nr])();
 | 
						|
			} else {
 | 
						|
				err = ENOSYS;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else err = EINVAL;
 | 
						|
 | 
						|
		send_reply(err, transid);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				get_work				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static int get_work(void)
 | 
						|
{
 | 
						|
	/* Retrieve work. Return the call number.
 | 
						|
	 */
 | 
						|
	int r;
 | 
						|
 | 
						|
	if ((r = sef_receive(ANY, &fs_m_in)) != OK)
 | 
						|
		panic(__FILE__, "receive failed", r);
 | 
						|
 | 
						|
	return fs_m_in.m_type;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				send_reply				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static void send_reply(int err, int transid)
 | 
						|
{
 | 
						|
	/* Send a reply to the caller.
 | 
						|
	 */
 | 
						|
	int r;
 | 
						|
 | 
						|
	fs_m_out.m_type = err;
 | 
						|
	if (IS_VFS_FS_TRANSID(transid)) {
 | 
						|
		fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid);
 | 
						|
	}
 | 
						|
 | 
						|
	if ((r = send(fs_m_in.m_source, &fs_m_out)) != OK)
 | 
						|
		panic(__FILE__, "unable to send reply", r);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				got_signal				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static void got_signal(int signal)
 | 
						|
{
 | 
						|
	/* We received a signal. If it is a termination signal, and the file
 | 
						|
	 * system has already been unmounted, clean up and exit.
 | 
						|
	 */
 | 
						|
 | 
						|
	if (signal != SIGTERM)
 | 
						|
		return;
 | 
						|
 | 
						|
	if (fs_mounted)
 | 
						|
		return;
 | 
						|
 | 
						|
	cleanup_inodes();
 | 
						|
 | 
						|
	exit(0);
 | 
						|
}
 |