* Also change _orig to _intr for clarity
 * Cleaned up {IPC,KER}VEC
 * Renamed _minix_kernel_info_struct to get_minix_kerninfo
 * Merged _senda.S into _ipc.S
 * Moved into separate files get_minix_kerninfo and _do_kernel_call
 * Adapted do_kernel_call to follow same _ convention as ipc functions
 * Drop patches in libc/net/send.c and libc/include/namespace.h
Change-Id: If4ea21ecb65435170d7d87de6c826328e84c18d0
		
	
			
		
			
				
	
	
		
			155 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* This file contains the SFFS initialization code and message loop.
 | 
						|
 *
 | 
						|
 * The entry points into this file are:
 | 
						|
 *   sffs_init		initialization
 | 
						|
 *   sffs_signal	signal handler
 | 
						|
 *   sffs_loop		main message loop
 | 
						|
 *
 | 
						|
 * Created:
 | 
						|
 *   April 2009 (D.C. van Moolenbroek)
 | 
						|
 */
 | 
						|
 | 
						|
#include "inc.h"
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				sffs_init				     *
 | 
						|
 *===========================================================================*/
 | 
						|
int sffs_init(char *name, const struct sffs_table *table,
 | 
						|
  struct sffs_params *params)
 | 
						|
{
 | 
						|
/* Initialize this file server. Called at startup time.
 | 
						|
 */
 | 
						|
  int i;
 | 
						|
 | 
						|
  /* Make sure that the given path prefix doesn't end with a slash. */
 | 
						|
  i = strlen(params->p_prefix);
 | 
						|
  while (i > 0 && params->p_prefix[i - 1] == '/') i--;
 | 
						|
  params->p_prefix[i] = 0;
 | 
						|
 | 
						|
  state.s_mounted = FALSE;
 | 
						|
  state.s_signaled = FALSE;
 | 
						|
 | 
						|
  sffs_name = name;
 | 
						|
  sffs_table = table;
 | 
						|
  sffs_params = params;
 | 
						|
 | 
						|
  return OK;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				sffs_signal				     *
 | 
						|
 *===========================================================================*/
 | 
						|
void sffs_signal(int signo)
 | 
						|
{
 | 
						|
 | 
						|
  /* Only check for termination signal, ignore anything else. */
 | 
						|
  if (signo != SIGTERM) return;
 | 
						|
 | 
						|
  /* We can now terminate if we have also been unmounted. */
 | 
						|
  state.s_signaled = TRUE;
 | 
						|
 | 
						|
  if (state.s_mounted) {
 | 
						|
	dprintf(("%s: got SIGTERM, still mounted\n", sffs_name));
 | 
						|
  } else {
 | 
						|
	dprintf(("%s: got SIGTERM, shutting down\n", sffs_name));
 | 
						|
 | 
						|
	/* Break out of the main loop, giving the main program the chance to
 | 
						|
	 * perform further cleanup. This causes sef_receive() to return with
 | 
						|
	 * an EINTR error code.
 | 
						|
	 */
 | 
						|
	sef_cancel();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				get_work				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static int get_work(who_e)
 | 
						|
endpoint_t *who_e;
 | 
						|
{
 | 
						|
/* Receive a request message from VFS. Return TRUE if a new message is ready
 | 
						|
 * to be processed, or FALSE if sef_stop() was called from the signal handler.
 | 
						|
 */
 | 
						|
  int r;
 | 
						|
 | 
						|
  if ((r = sef_receive(ANY, &m_in)) != OK) {
 | 
						|
	if (r != EINTR)
 | 
						|
		panic("receive failed: %d", r);
 | 
						|
 | 
						|
	return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  *who_e = m_in.m_source;
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				send_reply				     *
 | 
						|
 *===========================================================================*/
 | 
						|
static void send_reply(err, transid)
 | 
						|
int err;				/* resulting error code */
 | 
						|
int transid;
 | 
						|
{
 | 
						|
/* Send a reply message to the requesting party, with the given error code.
 | 
						|
 */
 | 
						|
  int r;
 | 
						|
 | 
						|
  m_out.m_type = err;
 | 
						|
  if (IS_VFS_FS_TRANSID(transid)) {
 | 
						|
	/* If a transaction ID was set, reset it */
 | 
						|
	m_out.m_type = TRNS_ADD_ID(m_out.m_type, transid);
 | 
						|
  }
 | 
						|
  if ((r = ipc_send(m_in.m_source, &m_out)) != OK)
 | 
						|
	printf("%s: ipc_send failed (%d)\n", sffs_name, r);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				sffs_loop				     *
 | 
						|
 *===========================================================================*/
 | 
						|
void sffs_loop(void)
 | 
						|
{
 | 
						|
/* The main function of this file server. After initializing, loop, receiving
 | 
						|
 * one request from VFS at a time, processing it, and sending a reply back to
 | 
						|
 * VFS. Termination occurs when we both have been unmounted and have received
 | 
						|
 * a termination signal.
 | 
						|
 */
 | 
						|
  endpoint_t who_e;
 | 
						|
  int call_nr, err, transid;
 | 
						|
 | 
						|
  while (state.s_mounted || !state.s_signaled) {
 | 
						|
	if (!get_work(&who_e))
 | 
						|
		continue;	/* Recheck running conditions */
 | 
						|
 | 
						|
	transid = TRNS_GET_ID(m_in.m_type);
 | 
						|
	m_in.m_type = TRNS_DEL_ID(m_in.m_type);
 | 
						|
	if (m_in.m_type == 0) {
 | 
						|
		assert(!IS_VFS_FS_TRANSID(transid));
 | 
						|
		m_in.m_type = transid;		/* Backwards compat. */
 | 
						|
		transid = 0;
 | 
						|
	} else
 | 
						|
		assert(IS_VFS_FS_TRANSID(transid));
 | 
						|
 | 
						|
	call_nr = m_in.m_type;
 | 
						|
	if (who_e != VFS_PROC_NR) {
 | 
						|
		continue;
 | 
						|
	}
 | 
						|
 | 
						|
	if (state.s_mounted || call_nr == REQ_READSUPER) {
 | 
						|
		call_nr -= FS_BASE;
 | 
						|
 | 
						|
		dprintf(("%s: call %d\n", sffs_name, call_nr));
 | 
						|
 | 
						|
		if (call_nr >= 0 && call_nr < NREQS) {
 | 
						|
			err = (*call_vec[call_nr])();
 | 
						|
		} else {
 | 
						|
			err = ENOSYS;
 | 
						|
		}
 | 
						|
 | 
						|
		dprintf(("%s: call %d result %d\n", sffs_name, call_nr, err));
 | 
						|
	}
 | 
						|
	else err = EINVAL;
 | 
						|
 | 
						|
	send_reply(err, transid);
 | 
						|
  }
 | 
						|
}
 |