RS crash recovery support.

This commit is contained in:
Cristiano Giuffrida 2010-07-06 22:05:21 +00:00
parent e920c1e1df
commit 1f8dbed029
21 changed files with 429 additions and 200 deletions

View file

@ -487,7 +487,7 @@
# define GET_IRQACTIDS 16 /* get the IRQ masks */
# define GET_PRIV 17 /* get privilege structure */
# define GET_HZ 18 /* get HZ value */
# define GET_WHOAMI 19 /* get own name and endpoint */
# define GET_WHOAMI 19 /* get own name, endpoint, and privileges */
# define GET_RANDOMNESS_BIN 20 /* get one randomness bin */
# define GET_IDLETSC 21 /* get cumulative idle time stamp counter */
# define GET_AOUTHEADER 22 /* get a.out headers from the boot image */
@ -500,6 +500,7 @@
/* GET_WHOAMI fields. */
#define GIWHO_EP m3_i1
#define GIWHO_NAME m3_ca1
#define GIWHO_PRIVFLAGS m3_i2
/* Field names for SYS_TIMES. */
#define T_ENDPT m4_l1 /* process to request time info for */
@ -529,6 +530,7 @@
*/
#define SYS_PRIV_ADD_IRQ 7 /* Add IRQ */
#define SYS_PRIV_QUERY_MEM 8 /* Verify memory privilege. */
#define SYS_PRIV_UPDATE_SYS 9 /* Update a sys privilege structure. */
/* Field names for SYS_SETGRANT */
#define SG_ADDR m2_p1 /* address */

View file

@ -168,14 +168,17 @@
#define PROC_FULLVM 0x100 /* VM sets and manages full pagetable */
/* Bits for s_flags in the privilege structure. */
#define PREEMPTIBLE 0x02 /* kernel tasks are not preemptible */
#define BILLABLE 0x04 /* some processes are not billable */
#define DYN_PRIV_ID 0x08 /* privilege id assigned dynamically */
#define PREEMPTIBLE 0x002 /* kernel tasks are not preemptible */
#define BILLABLE 0x004 /* some processes are not billable */
#define DYN_PRIV_ID 0x008 /* privilege id assigned dynamically */
#define SYS_PROC 0x10 /* system processes have own priv structure */
#define CHECK_IO_PORT 0x20 /* check if I/O request is allowed */
#define CHECK_IRQ 0x40 /* check if IRQ can be used */
#define CHECK_MEM 0x80 /* check if (VM) mem map request is allowed */
#define SYS_PROC 0x010 /* system processes have own priv structure */
#define CHECK_IO_PORT 0x020 /* check if I/O request is allowed */
#define CHECK_IRQ 0x040 /* check if IRQ can be used */
#define CHECK_MEM 0x080 /* check if (VM) mem map request is allowed */
#define ROOT_SYS_PROC 0x100 /* this is a root system process instance */
#define LU_SYS_PROC 0x200 /* this is a live updated sys proc instance */
#define RST_SYS_PROC 0x400 /* this is a restarted sys proc instance */
/* Bits for device driver flags managed by RS and VFS. */
#define DRV_FORCED 0x01 /* driver is mapped even if not alive yet */

View file

@ -29,6 +29,7 @@ _PROTOTYPE( void sef_exit, (int status) );
/* Type definitions. */
typedef struct {
cp_grant_id_t rproctab_gid;
endpoint_t endpoint;
endpoint_t old_endpoint;
} sef_init_info_t;

View file

@ -197,7 +197,8 @@ _PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off,
#define sys_getaoutheader(dst,nr) sys_getinfo(GET_AOUTHEADER, dst, 0,0,nr)
_PROTOTYPE(int sys_getinfo, (int request, void *val_ptr, int val_len,
void *val_ptr2, int val_len2) );
_PROTOTYPE(int sys_whoami, (endpoint_t *ep, char *name, int namelen));
_PROTOTYPE(int sys_whoami, (endpoint_t *ep, char *name, int namelen,
int *priv_flags));
/* Signal control. */
_PROTOTYPE(int sys_kill, (endpoint_t proc_ep, int sig) );

View file

@ -162,40 +162,87 @@ schedulerstr(struct proc *scheduler)
return "KERNEL";
}
PRIVATE void
print_proc_name(struct proc *pp)
{
char *name = pp->p_name;
endpoint_t ep = pp->p_endpoint;
if(name) {
printf("%s(%d)", name, ep);
}
else {
printf("%d", ep);
}
}
PRIVATE void
print_endpoint(endpoint_t ep)
{
int proc_nr;
struct proc *pp = NULL;
switch(ep) {
case ANY:
printf("ANY");
break;
case SELF:
printf("SELF");
break;
case NONE:
printf("NONE");
break;
default:
if(!isokendpt(ep, &proc_nr)) {
printf("??? %d\n", ep);
}
else {
pp = proc_addr(proc_nr);
if(isemptyp(pp)) {
printf("??? empty slot %d\n", proc_nr);
}
else {
print_proc_name(pp);
}
}
break;
}
}
PRIVATE void
print_sigmgr(struct proc *pp)
{
endpoint_t sig_mgr, bak_sig_mgr;
sig_mgr = priv(pp)->s_sig_mgr;
bak_sig_mgr = priv(pp)->s_bak_sig_mgr;
printf("sigmgr ");
print_endpoint(sig_mgr);
if(bak_sig_mgr != NONE) {
printf(" / ");
print_endpoint(bak_sig_mgr);
}
}
PUBLIC void print_proc(struct proc *pp)
{
struct proc *depproc = NULL;
endpoint_t dep;
printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cr3 0x%lx rts %s misc %s sched %s",
printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cr3 0x%lx rts %s misc %s sched %s ",
proc_nr(pp), pp->p_name, pp->p_endpoint,
pp->p_priority, pp->p_user_time,
pp->p_sys_time, pp->p_cycles.hi, pp->p_cycles.lo, pp->p_seg.p_cr3,
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
schedulerstr(pp->p_scheduler));
print_sigmgr(pp);
dep = P_BLOCKEDON(pp);
if(dep != NONE) {
printf(" blocked on: ");
if(dep == ANY) {
printf(" ANY\n");
} else {
int procno;
if(!isokendpt(dep, &procno)) {
printf(" ??? %d\n", dep);
} else {
depproc = proc_addr(procno);
if(isemptyp(depproc)) {
printf(" empty slot %d???\n", procno);
depproc = NULL;
} else {
printf(" %s\n", depproc->p_name);
}
}
}
} else {
printf("\n");
print_endpoint(dep);
}
printf("\n");
}
PRIVATE void print_proc_depends(struct proc *pp, const int level)

View file

@ -58,6 +58,8 @@ PUBLIC int main(void)
sp->s_proc_nr = NONE; /* initialize as free */
sp->s_id = (sys_id_t) i; /* priv structure index */
ppriv_addr[i] = sp; /* priv ptr from number */
sp->s_sig_mgr = NONE; /* clear signal managers */
sp->s_bak_sig_mgr = NONE;
}
/* Set up proc table entries for processes in boot image. The stacks of the
@ -116,6 +118,7 @@ PUBLIC int main(void)
ipc_to_m = RSYS_M; /* allowed targets */
kcalls = RSYS_KC; /* allowed kernel calls */
priv(rp)->s_sig_mgr = RSYS_SM; /* signal manager */
priv(rp)->s_bak_sig_mgr = NONE; /* backup signal manager */
}
/* Priviliges for ordinary process. */
else {
@ -123,12 +126,7 @@ PUBLIC int main(void)
}
/* Fill in target mask. */
for (j=0; j < NR_SYS_PROCS; j++) {
if (ipc_to_m & (1 << j))
set_sendto_bit(rp, j);
else
unset_sendto_bit(rp, j);
}
fill_sendto_mask(rp, ipc_to_m);
/* Fill in kernel call mask. */
for(j = 0; j < SYS_CALL_MASK_SIZE; j++) {

View file

@ -44,6 +44,7 @@ struct priv {
bitchunk_t s_k_call_mask[SYS_CALL_MASK_SIZE];
endpoint_t s_sig_mgr; /* signal manager for system signals */
endpoint_t s_bak_sig_mgr; /* backup signal manager for system signals */
sys_map_t s_notify_pending; /* bit map with pending notifications */
irq_id_t s_int_pending; /* pending hardware interrupts */
sigset_t s_sig_pending; /* pending signals */
@ -130,7 +131,7 @@ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
* and there is another runnable process
*/
#define TSK_F (SYS_PROC) /* other kernel tasks */
#define RSYS_F (SYS_PROC | PREEMPTIBLE) /* root system proc */
#define RSYS_F (SYS_PROC | PREEMPTIBLE | ROOT_SYS_PROC) /* root sys proc */
#define DEF_SYS_F (RSYS_F | DYN_PRIV_ID) /* default sys proc */
/* allowed traps */
@ -152,7 +153,7 @@ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
#define DEF_SYS_KC RSYS_KC /* default sys proc */
/* signal manager */
#define RSYS_SM ROOT_SYS_PROC_NR /* root system proc */
#define RSYS_SM SELF /* root system proc */
#define DEF_SYS_SM ROOT_SYS_PROC_NR /* default sys proc */
/* scheduler */

View file

@ -65,6 +65,7 @@ _PROTOTYPE( char *env_get, (const char *key));
_PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type) );
_PROTOTYPE( void set_sendto_bit, (const struct proc *rc, int id) );
_PROTOTYPE( void unset_sendto_bit, (const struct proc *rc, int id) );
_PROTOTYPE( void fill_sendto_mask, (const struct proc *rc, int mask) );
_PROTOTYPE( void send_sig, (endpoint_t proc_nr, int sig_nr) );
_PROTOTYPE( void cause_sig, (proc_nr_t proc_nr, int sig_nr) );
_PROTOTYPE( void sig_delay_done, (struct proc *rp) );

View file

@ -14,6 +14,7 @@
* get_priv: assign privilege structure to user or system process
* set_sendto_bit: allow a process to send messages to a new target
* unset_sendto_bit: disallow a process from sending messages to a target
* fill_sendto_mask: fill the target mask of a given process
* send_sig: send a signal directly to a system process
* cause_sig: take action to cause a signal to occur via a signal mgr
* sig_delay_done: tell PM that a process is not sending
@ -333,19 +334,35 @@ PUBLIC void unset_sendto_bit(const struct proc *rp, int id)
unset_sys_bit(priv_addr(id)->s_ipc_to, priv_id(rp));
}
/*===========================================================================*
* fill_sendto_mask *
*===========================================================================*/
PUBLIC void fill_sendto_mask(const struct proc *rp, int mask)
{
int i;
for (i=0; i < NR_SYS_PROCS; i++) {
if (mask & (1 << i))
set_sendto_bit(rp, i);
else
unset_sendto_bit(rp, i);
}
}
/*===========================================================================*
* send_sig *
*===========================================================================*/
PUBLIC void send_sig(endpoint_t proc_nr, int sig_nr)
PUBLIC void send_sig(endpoint_t ep, int sig_nr)
{
/* Notify a system process about a signal. This is straightforward. Simply
* set the signal that is to be delivered in the pending signals map and
* send a notification with source SYSTEM.
*/
register struct proc *rp;
int proc_nr;
if(!isokprocn(proc_nr) || isemptyn(proc_nr))
panic("send_sig to empty process: %d", proc_nr);
if(!isokendpt(ep, &proc_nr) || isemptyn(proc_nr))
panic("send_sig to empty process: %d", ep);
rp = proc_addr(proc_nr);
(void) sigaddset(&priv(rp)->s_sig_pending, sig_nr);
@ -372,19 +389,32 @@ int sig_nr; /* signal to be sent */
* only called when a user process causes a CPU exception and from the kernel
* process level, which runs to completion.
*/
register struct proc *rp;
register struct proc *rp, *sig_mgr_rp;
endpoint_t sig_mgr;
int sig_mgr_proc_nr;
/* Lookup signal manager. */
rp = proc_addr(proc_nr);
sig_mgr = priv(rp)->s_sig_mgr;
if(sig_mgr == SELF) sig_mgr = rp->p_endpoint;
/* If the target is the signal manager of itself, send the signal directly. */
if(rp->p_endpoint == sig_mgr) {
if(SIGS_IS_LETHAL(sig_nr)) {
/* If the signal is lethal, see if a backup signal manager exists. */
sig_mgr = priv(rp)->s_bak_sig_mgr;
if(sig_mgr != NONE && isokendpt(sig_mgr, &sig_mgr_proc_nr)) {
priv(rp)->s_sig_mgr = sig_mgr;
priv(rp)->s_bak_sig_mgr = NONE;
sig_mgr_rp = proc_addr(sig_mgr_proc_nr);
RTS_UNSET(sig_mgr_rp, RTS_NO_PRIV);
cause_sig(proc_nr, sig_nr); /* try again with the new sig mgr. */
return;
}
/* We are out of luck. Time to panic. */
proc_stacktrace(rp);
panic("cause_sig: signal manager gets lethal signal %d for itself",
sig_nr);
panic("cause_sig: sig manager %d gets lethal signal %d for itself",
rp->p_endpoint, sig_nr);
}
(void) sigaddset(&priv(rp)->s_sig_pending, sig_nr);
send_sig(rp->p_endpoint, SIGKSIGSM);

View file

@ -96,6 +96,7 @@ PUBLIC int do_getinfo(struct proc * caller, message * m_ptr)
len = MIN(sizeof(m_ptr->GIWHO_NAME), sizeof(caller->p_name))-1;
strncpy(m_ptr->GIWHO_NAME, caller->p_name, len);
m_ptr->GIWHO_NAME[len] = '\0';
m_ptr->GIWHO_PRIVFLAGS = priv(caller)->s_flags;
return OK;
}
case GET_MONPARAMS: {

View file

@ -15,6 +15,10 @@
#if USE_PRIVCTL
#define PRIV_DEBUG 0
FORWARD _PROTOTYPE(int update_priv, (struct proc *rp, struct priv *priv));
/*===========================================================================*
* do_privctl *
*===========================================================================*/
@ -107,13 +111,15 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
priv(rp)->s_flags= DEF_SYS_F; /* privilege flags */
priv(rp)->s_trap_mask= DEF_SYS_T; /* allowed traps */
ipc_to_m = DEF_SYS_M; /* allowed targets */
fill_sendto_mask(rp, ipc_to_m);
kcalls = DEF_SYS_KC; /* allowed kernel calls */
for(i = 0; i < SYS_CALL_MASK_SIZE; i++) {
priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
}
/* Set the default signal manager. */
/* Set the default signal managers. */
priv(rp)->s_sig_mgr = DEF_SYS_SM;
priv(rp)->s_bak_sig_mgr = NONE;
/* Set defaults for resources: no I/O resources, no memory resources,
* no IRQs, no grant table
@ -127,76 +133,9 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
/* Override defaults if the caller has supplied a privilege structure. */
if (m_ptr->CTL_ARG_PTR)
{
/* Copy s_flags and signal manager. */
priv(rp)->s_flags = priv.s_flags;
priv(rp)->s_sig_mgr = priv.s_sig_mgr;
/* Copy IRQs */
if(priv.s_flags & CHECK_IRQ) {
if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
return EINVAL;
priv(rp)->s_nr_irq= priv.s_nr_irq;
for (i= 0; i<priv.s_nr_irq; i++)
{
priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
#if 0
printf("do_privctl: adding IRQ %d for %d\n",
priv(rp)->s_irq_tab[i], rp->p_endpoint);
#endif
}
}
/* Copy I/O ranges */
if(priv.s_flags & CHECK_IO_PORT) {
if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
return EINVAL;
priv(rp)->s_nr_io_range= priv.s_nr_io_range;
for (i= 0; i<priv.s_nr_io_range; i++)
{
priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
#if 0
printf("do_privctl: adding I/O range [%x..%x] for %d\n",
priv(rp)->s_io_tab[i].ior_base,
priv(rp)->s_io_tab[i].ior_limit,
rp->p_endpoint);
#endif
}
}
/* Copy memory ranges */
if(priv.s_flags & CHECK_MEM) {
if (priv.s_nr_mem_range < 0 || priv.s_nr_mem_range > NR_MEM_RANGE)
return EINVAL;
priv(rp)->s_nr_mem_range= priv.s_nr_mem_range;
for (i= 0; i<priv.s_nr_mem_range; i++)
{
priv(rp)->s_mem_tab[i]= priv.s_mem_tab[i];
#if 0
printf("do_privctl: adding mem range [%x..%x] for %d\n",
priv(rp)->s_mem_tab[i].mr_base,
priv(rp)->s_mem_tab[i].mr_limit,
rp->p_endpoint);
#endif
}
}
/* Copy trap mask. */
priv(rp)->s_trap_mask = priv.s_trap_mask;
/* Copy target mask. */
memcpy(&ipc_to_m, &priv.s_ipc_to, sizeof(ipc_to_m));
/* Copy kernel call mask. */
memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
sizeof(priv(rp)->s_k_call_mask));
}
/* Fill in target mask. */
for (i=0; i < NR_SYS_PROCS; i++) {
if (ipc_to_m & (1 << i))
set_sendto_bit(rp, i);
else
unset_sendto_bit(rp, i);
if((r = update_priv(rp, &priv)) != OK) {
return r;
}
}
return(OK);
@ -316,11 +255,105 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
}
return EPERM;
}
case SYS_PRIV_UPDATE_SYS:
/* Update the privilege structure of a system process. */
if(!m_ptr->CTL_ARG_PTR) return EINVAL;
/* Copy privilege structure from caller */
if((r=data_copy(caller->p_endpoint, (vir_bytes) m_ptr->CTL_ARG_PTR,
KERNEL, (vir_bytes) &priv, sizeof(priv))) != OK)
return r;
/* Override settings in existing privilege structure. */
if((r = update_priv(rp, &priv)) != OK) {
return r;
}
return(OK);
default:
printf("do_privctl: bad request %d\n", m_ptr->CTL_REQUEST);
return EINVAL;
}
}
/*===========================================================================*
* update_priv *
*===========================================================================*/
PRIVATE int update_priv(struct proc *rp, struct priv *priv)
{
/* Update the privilege structure of a given process. */
int ipc_to_m, i;
/* Copy s_flags and signal managers. */
priv(rp)->s_flags = priv->s_flags;
priv(rp)->s_sig_mgr = priv->s_sig_mgr;
priv(rp)->s_bak_sig_mgr = priv->s_bak_sig_mgr;
/* Copy IRQs. */
if(priv->s_flags & CHECK_IRQ) {
if (priv->s_nr_irq < 0 || priv->s_nr_irq > NR_IRQ)
return EINVAL;
priv(rp)->s_nr_irq= priv->s_nr_irq;
for (i= 0; i<priv->s_nr_irq; i++)
{
priv(rp)->s_irq_tab[i]= priv->s_irq_tab[i];
#if PRIV_DEBUG
printf("do_privctl: adding IRQ %d for %d\n",
priv(rp)->s_irq_tab[i], rp->p_endpoint);
#endif
}
}
/* Copy I/O ranges. */
if(priv->s_flags & CHECK_IO_PORT) {
if (priv->s_nr_io_range < 0 || priv->s_nr_io_range > NR_IO_RANGE)
return EINVAL;
priv(rp)->s_nr_io_range= priv->s_nr_io_range;
for (i= 0; i<priv->s_nr_io_range; i++)
{
priv(rp)->s_io_tab[i]= priv->s_io_tab[i];
#if PRIV_DEBUG
printf("do_privctl: adding I/O range [%x..%x] for %d\n",
priv(rp)->s_io_tab[i].ior_base,
priv(rp)->s_io_tab[i].ior_limit,
rp->p_endpoint);
#endif
}
}
/* Copy memory ranges. */
if(priv->s_flags & CHECK_MEM) {
if (priv->s_nr_mem_range < 0 || priv->s_nr_mem_range > NR_MEM_RANGE)
return EINVAL;
priv(rp)->s_nr_mem_range= priv->s_nr_mem_range;
for (i= 0; i<priv->s_nr_mem_range; i++)
{
priv(rp)->s_mem_tab[i]= priv->s_mem_tab[i];
#if PRIV_DEBUG
printf("do_privctl: adding mem range [%x..%x] for %d\n",
priv(rp)->s_mem_tab[i].mr_base,
priv(rp)->s_mem_tab[i].mr_limit,
rp->p_endpoint);
#endif
}
}
/* Copy trap mask. */
priv(rp)->s_trap_mask = priv->s_trap_mask;
/* Copy target mask. */
memcpy(&ipc_to_m, &priv->s_ipc_to, sizeof(ipc_to_m));
fill_sendto_mask(rp, ipc_to_m);
/* Copy kernel call mask. */
memcpy(priv(rp)->s_k_call_mask, priv->s_k_call_mask,
sizeof(priv(rp)->s_k_call_mask));
return OK;
}
#endif /* USE_PRIVCTL */

View file

@ -17,10 +17,11 @@ PUBLIC void panic(const char *fmt, ...)
*/
endpoint_t me = NONE;
char name[20];
int priv_flags;
void (*suicide)(void);
va_list args;
if(sys_whoami(&me, name, sizeof(name)) == OK && me != NONE)
if(sys_whoami(&me, name, sizeof(name), &priv_flags) == OK && me != NONE)
printf("%s(%d): panic: ", name, me);
else
printf("(sys_whoami failed): panic: ");

View file

@ -7,6 +7,7 @@
#define SEF_SELF_NAME_MAXLEN 20
PUBLIC char sef_self_name[SEF_SELF_NAME_MAXLEN];
PUBLIC endpoint_t sef_self_endpoint;
PUBLIC int sef_self_priv_flags;
/* Debug. */
#define SEF_DEBUG_HEADER_MAXLEN 32
@ -19,7 +20,7 @@ FORWARD _PROTOTYPE( void sef_debug_refresh_params, (void) );
PUBLIC _PROTOTYPE( char* sef_debug_header, (void) );
/* SEF Init prototypes. */
EXTERN _PROTOTYPE( int do_sef_rs_init, (void) );
EXTERN _PROTOTYPE( int do_sef_rs_init, (endpoint_t old_endpoint) );
EXTERN _PROTOTYPE( int do_sef_init_request, (message *m_ptr) );
/* SEF Ping prototypes. */
@ -39,20 +40,34 @@ PUBLIC void sef_startup()
{
/* SEF startup interface for system services. */
int r, status;
endpoint_t old_endpoint;
/* Get information about self. */
r = sys_whoami(&sef_self_endpoint, sef_self_name, SEF_SELF_NAME_MAXLEN);
r = sys_whoami(&sef_self_endpoint, sef_self_name, SEF_SELF_NAME_MAXLEN,
&sef_self_priv_flags);
if ( r != OK) {
sef_self_endpoint = SELF;
sprintf(sef_self_name, "%s", "Unknown");
}
old_endpoint = NONE;
/* RS may wake up with the wrong endpoint, perfom the update in that case. */
if((sef_self_priv_flags & ROOT_SYS_PROC) && sef_self_endpoint != RS_PROC_NR) {
r = vm_update(RS_PROC_NR, sef_self_endpoint);
if(r != OK) {
panic("unable to update RS from instance %d to %d",
RS_PROC_NR, sef_self_endpoint);
}
old_endpoint = sef_self_endpoint;
sef_self_endpoint = RS_PROC_NR;
}
#if INTERCEPT_SEF_INIT_REQUESTS
/* Intercept SEF Init requests. */
if(sef_self_endpoint == RS_PROC_NR) {
if(sef_self_priv_flags & ROOT_SYS_PROC) {
/* RS initialization is special. */
if((r = do_sef_rs_init()) != OK) {
panic("unable to complete init: %d", r);
if((r = do_sef_rs_init(old_endpoint)) != OK) {
panic("RS unable to complete init: %d (%s)", r, strerror(-r));
}
}
else {

View file

@ -1,5 +1,6 @@
#include "syslib.h"
#include <assert.h>
#include <unistd.h>
#include <minix/sysutil.h>
/* SEF Init callbacks. */
@ -14,19 +15,79 @@ PRIVATE struct sef_cbs {
};
/* SEF Init prototypes for sef_startup(). */
PUBLIC _PROTOTYPE( int do_sef_rs_init, (void) );
PUBLIC _PROTOTYPE( int do_sef_rs_init, (endpoint_t old_endpoint) );
PUBLIC _PROTOTYPE( int do_sef_init_request, (message *m_ptr) );
/* Debug. */
EXTERN _PROTOTYPE( char* sef_debug_header, (void) );
/* Information about SELF. */
EXTERN endpoint_t sef_self_endpoint;
EXTERN endpoint_t sef_self_priv_flags;
/*===========================================================================*
* process_init *
*===========================================================================*/
PRIVATE int process_init(int type, sef_init_info_t *info)
{
/* Process initialization. */
int r;
/* Debug. */
#if SEF_INIT_DEBUG
sef_init_debug_begin();
sef_init_dprint("%s. Got a SEF Init request of type: %d. About to init.\n",
sef_debug_header(), type);
sef_init_debug_end();
#endif
/* Let the callback code handle the specific initialization type. */
switch(type) {
case SEF_INIT_FRESH:
r = sef_cbs.sef_cb_init_fresh(type, info);
break;
case SEF_INIT_LU:
r = sef_cbs.sef_cb_init_lu(type, info);
break;
case SEF_INIT_RESTART:
r = sef_cbs.sef_cb_init_restart(type, info);
break;
default:
/* Not a valid SEF init type. */
r = EINVAL;
break;
}
return r;
}
/*===========================================================================*
* do_sef_rs_init *
*===========================================================================*/
PUBLIC int do_sef_rs_init()
PUBLIC int do_sef_rs_init(endpoint_t old_endpoint)
{
/* Special SEF Init for RS. */
return sef_cbs.sef_cb_init_fresh(SEF_INIT_FRESH, NULL);
int r;
int type;
sef_init_info_t info;
/* Get init parameters from SEF. */
type = SEF_INIT_FRESH;
if(sef_self_priv_flags & LU_SYS_PROC) {
type = SEF_INIT_LU;
}
else if(sef_self_priv_flags & RST_SYS_PROC) {
type = SEF_INIT_RESTART;
}
info.rproctab_gid = -1;
info.endpoint = sef_self_endpoint;
info.old_endpoint = old_endpoint;
/* Peform initialization. */
r = process_init(type, &info);
return r;
}
/*===========================================================================*
@ -39,34 +100,14 @@ PUBLIC int do_sef_init_request(message *m_ptr)
int type;
sef_init_info_t info;
/* Debug. */
#if SEF_INIT_DEBUG
sef_init_debug_begin();
sef_init_dprint("%s. Got a SEF Init request of type: %d. About to init.\n",
sef_debug_header(), m_ptr->RS_INIT_TYPE);
sef_init_debug_end();
#endif
/* Let the callback code handle the request. */
/* Get init parameters from message. */
type = m_ptr->RS_INIT_TYPE;
info.rproctab_gid = m_ptr->RS_INIT_RPROCTAB_GID;
info.endpoint = sef_self_endpoint;
info.old_endpoint = m_ptr->RS_INIT_OLD_ENDPOINT;
switch(type) {
case SEF_INIT_FRESH:
r = sef_cbs.sef_cb_init_fresh(type, &info);
break;
case SEF_INIT_LU:
r = sef_cbs.sef_cb_init_lu(type, &info);
break;
case SEF_INIT_RESTART:
r = sef_cbs.sef_cb_init_restart(type, &info);
break;
default:
/* Not a valid SEF init type. */
r = EINVAL;
break;
}
/* Peform initialization. */
r = process_init(type, &info);
/* Report back to RS. */
m_ptr->RS_INIT_RESULT = r;

View file

@ -28,7 +28,8 @@ int len2; /* length or process nr */
/*===========================================================================*
* sys_whoami *
*===========================================================================*/
PUBLIC int sys_whoami(endpoint_t *who_ep, char *who_name, int len)
PUBLIC int sys_whoami(endpoint_t *who_ep, char *who_name, int len,
int *priv_flags)
{
message m;
int r;
@ -47,6 +48,7 @@ PUBLIC int sys_whoami(endpoint_t *who_ep, char *who_name, int len)
strncpy(who_name, m.GIWHO_NAME, lenmin);
who_name[lenmin] = '\0';
*who_ep = m.GIWHO_EP;
*priv_flags = m.GIWHO_PRIVFLAGS;
return OK;
}

View file

@ -206,10 +206,8 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
/* Initialize the inet server. */
int r;
int timerand, fd;
endpoint_t tasknr;
u8_t randbits[32];
struct timeval tv;
char my_name[32];
#if DEBUG
printf("Starting inet...\n");
@ -258,10 +256,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
init_rand256(randbits);
/* Our new identity as a server. */
r = sys_whoami(&tasknr, my_name, sizeof(my_name));
if (r != OK)
ip_panic(("inet: sys_whoami failed for 'inet': %d", r));
this_proc= tasknr;
this_proc= info->endpoint;
#ifdef BUF_CONSISTENCY_CHECK
inet_buf_debug= (getenv("inetbufdebug") &&

View file

@ -93,5 +93,9 @@
#define SRV_DF (DRV_FORCED) /* system services */
#define DSRV_DF (SRV_DF) /* dynamic system services */
/* Reply flags. */
#define RS_DONTREPLY 0
#define RS_REPLY 1
#endif /* RS_CONST_H */

View file

@ -138,7 +138,8 @@ PUBLIC int main(void)
PRIVATE void sef_local_startup()
{
/* Register init callbacks. */
sef_setcb_init_fresh(sef_cb_init_fresh); /* RS can only start fresh. */
sef_setcb_init_fresh(sef_cb_init_fresh);
sef_setcb_init_restart(sef_cb_init_fail);
/* Register signal callbacks. */
sef_setcb_signal_handler(sef_cb_signal_handler);
@ -262,6 +263,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
sizeof(rp->r_priv.s_ipc_to)); /* targets */
rp->r_priv.s_sig_mgr = boot_image_priv->sig_mgr; /* sig mgr */
rp->r_priv.s_bak_sig_mgr = NONE; /* backup sig mgr */
/* Initialize kernel call mask bitmap from unordered set. */
fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS,

View file

@ -100,9 +100,9 @@ struct rproc *rp;
return EPERM;
}
/* Only allow RS_EDIT for RS. */
/* Disallow RS_UPDATE for RS. */
if(rpub->endpoint == RS_PROC_NR) {
if(call != RS_EDIT) return EPERM;
if(call == RS_UPDATE) return EPERM;
}
/* Disallow the call if another call is in progress for the service. */
@ -273,7 +273,7 @@ PUBLIC void update_period(message *m_ptr)
*/
if(has_update_timed_out) {
printf("RS: update failed: maximum prepare time reached\n");
end_update(EINTR);
end_update(EINTR, RS_DONTREPLY);
/* Prepare cancel request. */
m.m_type = RS_LU_PREPARE;
@ -285,7 +285,7 @@ PUBLIC void update_period(message *m_ptr)
/*===========================================================================*
* end_update *
*===========================================================================*/
PUBLIC void end_update(int result)
PUBLIC void end_update(int result, int reply_flag)
{
/* End the update process. There are two possibilities:
* 1) the update succeeded. In that case, cleanup the old version and mark the
@ -321,10 +321,19 @@ PUBLIC void end_update(int result)
/* Send a late reply if necessary. */
late_reply(old_rp, result);
/* Cleanup the version that has to die out and mark the other
* version as no longer updating.
/* Mark the version that has to survive as no longer updating and
* reply when asked to.
*/
surviving_rp->r_flags &= ~RS_UPDATING;
if(reply_flag == RS_REPLY) {
message m;
if(rs_verbose)
printf("RS: %s being replied to\n", srv_to_string(surviving_rp));
m.m_type = result;
reply(surviving_rp->r_pub->endpoint, &m);
}
/* Cleanup the version that has to die out. */
get_service_instances(exiting_rp, &rps, &nr_rps);
for(i=0;i<nr_rps;i++) {
cleanup_service(rps[i]);
@ -371,6 +380,11 @@ struct rproc *rp;
printf("RS: %s %skilled at %s:%d\n", srv_to_string(rp),
rp->r_flags & RS_EXITING ? "lethally " : "", file, line);
/* RS should simply exit() directly. */
if(rpub->endpoint == RS_PROC_NR) {
exit(0);
}
return sys_kill(rpub->endpoint, SIGKILL);
}
@ -552,12 +566,17 @@ struct rproc *rp;
/*===========================================================================*
* clone_service *
*===========================================================================*/
PUBLIC int clone_service(rp)
PUBLIC int clone_service(rp, instance_flag)
struct rproc *rp;
int instance_flag;
{
/* Clone the given system service instance. */
struct rproc *replica_rp;
struct rprocpub *replica_rpub;
struct rproc **rp_link;
struct rproc **replica_link;
struct rproc *rs_rp;
int rs_flags;
int r;
if(rs_verbose)
@ -568,14 +587,25 @@ struct rproc *rp;
return r;
}
/* Clone is a live updated or restarted service instance? */
if(instance_flag == LU_SYS_PROC) {
rp_link = &rp->r_new_rp;
replica_link = &replica_rp->r_old_rp;
}
else {
rp_link = &rp->r_next_rp;
replica_link = &replica_rp->r_prev_rp;
}
replica_rp->r_priv.s_flags |= instance_flag;
/* Link the two slots. */
rp->r_next_rp = replica_rp;
replica_rp->r_prev_rp = rp;
*rp_link = replica_rp;
*replica_link = rp;
/* Create a new replica of the service. */
r = create_service(replica_rp);
if(r != OK) {
rp->r_next_rp = NULL;
*rp_link = NULL;
return r;
}
@ -584,11 +614,32 @@ struct rproc *rp;
if(replica_rpub->vm_call_mask[0]) {
r = vm_set_priv(replica_rpub->endpoint, &replica_rpub->vm_call_mask[0]);
if (r != OK) {
rp->r_next_rp = NULL;
*rp_link = NULL;
return kill_service(replica_rp, "vm_set_priv call failed", r);
}
}
/* If this instance is for restarting RS, set up a backup signal manager. */
rs_flags = (ROOT_SYS_PROC | RST_SYS_PROC);
if((replica_rp->r_priv.s_flags & rs_flags) == rs_flags) {
rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
if(rs_verbose)
printf("RS: %s gets a backup signal manager\n", srv_to_string(rs_rp));
/* Update privilege structures. */
rs_rp->r_priv.s_bak_sig_mgr = replica_rpub->endpoint;
replica_rp->r_priv.s_sig_mgr = SELF;
r = sys_privctl(RS_PROC_NR, SYS_PRIV_UPDATE_SYS, &rs_rp->r_priv);
if(r == OK) {
r = sys_privctl(replica_rpub->endpoint, SYS_PRIV_UPDATE_SYS,
&replica_rp->r_priv);
}
if(r != OK) {
*rp_link = NULL;
return kill_service(replica_rp, "sys_privctl call failed", r);
}
}
return OK;
}
@ -756,6 +807,7 @@ struct rproc *rp;
PUBLIC void stop_service(struct rproc *rp,int how)
{
struct rprocpub *rpub;
int signo;
rpub = rp->r_pub;
@ -767,8 +819,10 @@ PUBLIC void stop_service(struct rproc *rp,int how)
if(rs_verbose)
printf("RS: %s signaled with SIGTERM\n", srv_to_string(rp));
signo = rpub->endpoint != RS_PROC_NR ? SIGTERM : SIGHUP; /* SIGHUP for RS. */
rp->r_flags |= how; /* what to on exit? */
sys_kill(rpub->endpoint, SIGTERM); /* first try friendly */
sys_kill(rpub->endpoint, signo); /* first try friendly */
getuptime(&rp->r_stop_tm); /* record current time */
}
@ -874,16 +928,13 @@ PUBLIC void terminate_service(struct rproc *rp)
/* If updating, rollback. */
if(rp->r_flags & RS_UPDATING) {
message m;
struct rproc *old_rp, *new_rp;
printf("RS: update failed: state transfer failed. Rolling back...\n");
new_rp = rp;
old_rp = new_rp->r_old_rp;
new_rp->r_flags &= ~RS_INITIALIZING;
update_service(&new_rp, &old_rp); /* can't fail */
m.m_type = ERESTART;
reply(old_rp->r_pub->endpoint, &m);
end_update(ERESTART);
end_update(ERESTART, RS_REPLY);
return;
}
}
@ -916,7 +967,7 @@ PUBLIC void terminate_service(struct rproc *rp)
* that just exited will continue executing.
*/
if(rp->r_flags & RS_UPDATING) {
end_update(ERESTART);
end_update(ERESTART, RS_DONTREPLY);
}
/* Determine what to do. If this is the first unexpected
@ -1012,7 +1063,7 @@ PUBLIC void restart_service(struct rproc *rp)
/* Restart directly. We need a replica if not already available. */
if(rp->r_next_rp == NULL) {
/* Create the replica. */
r = clone_service(rp);
r = clone_service(rp, RST_SYS_PROC);
if(r != OK) {
kill_service(rp, "unable to clone service", r);
return;
@ -1061,6 +1112,9 @@ struct rproc *rp;
rpub->dev_style = def_rpub->dev_style;
rpub->dev_style2 = def_rpub->dev_style2;
/* Service type flags. */
rp->r_priv.s_flags |= rp->r_priv.s_flags & ROOT_SYS_PROC;
/* Period. */
if(!rp->r_period && def_rp->r_period) {
rp->r_period = def_rp->r_period;
@ -1327,6 +1381,7 @@ endpoint_t source;
rp->r_priv.s_flags = DSRV_F; /* privilege flags */
rp->r_priv.s_trap_mask = DSRV_T; /* allowed traps */
rp->r_priv.s_sig_mgr = DSRV_SM; /* signal manager */
rp->r_priv.s_bak_sig_mgr = NONE; /* backup signal manager */
/* Initialize control labels. */
if(rs_start->rss_nr_control > 0) {
@ -1522,6 +1577,9 @@ struct rproc **clone_rpp;
/* Force dynamic privilege id. */
clone_rp->r_priv.s_flags |= DYN_PRIV_ID;
/* Clear instance flags. */
clone_rp->r_priv.s_flags &= ~(LU_SYS_PROC | RST_SYS_PROC);
*clone_rpp = clone_rp;
return OK;
}

View file

@ -51,7 +51,7 @@ _PROTOTYPE( int crash_service_debug, (char *file, int line, struct rproc *rp) );
_PROTOTYPE( void cleanup_service_debug, (char *file, int line,
struct rproc *rp) );
_PROTOTYPE( int create_service, (struct rproc *rp) );
_PROTOTYPE( int clone_service, (struct rproc *rp) );
_PROTOTYPE( int clone_service, (struct rproc *rp, int instance_flag) );
_PROTOTYPE( int publish_service, (struct rproc *rp) );
_PROTOTYPE( int unpublish_service, (struct rproc *rp) );
_PROTOTYPE( int run_service, (struct rproc *rp, int init_type) );
@ -85,7 +85,7 @@ _PROTOTYPE( void add_forward_ipc, (struct rproc *rp, struct priv *privp) );
_PROTOTYPE( void add_backward_ipc, (struct rproc *rp, struct priv *privp) );
_PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
_PROTOTYPE( void update_period, (message *m_ptr) );
_PROTOTYPE( void end_update, (int result) );
_PROTOTYPE( void end_update, (int result, int reply_flag) );
/* utility.c */
_PROTOTYPE( int init_service, (struct rproc *rp, int type));

View file

@ -219,7 +219,7 @@ PUBLIC int do_clone(message *m_ptr)
/* Clone the service as requested. */
rpub->sys_flags |= SF_USE_REPL;
if ((r = clone_service(rp)) != OK) {
if ((r = clone_service(rp, RST_SYS_PROC)) != OK) {
rpub->sys_flags &= ~SF_USE_REPL;
return r;
}
@ -280,7 +280,7 @@ PUBLIC int do_edit(message *m_ptr)
cleanup_service(rp->r_next_rp);
rp->r_next_rp = NULL;
}
if ((r = clone_service(rp)) != OK) {
if ((r = clone_service(rp, RST_SYS_PROC)) != OK) {
printf("RS: warning: unable to clone %s\n", srv_to_string(rp));
}
}
@ -408,7 +408,7 @@ PUBLIC int do_init_ready(message *m_ptr)
*/
if(rp->r_flags & RS_UPDATING) {
printf("RS: update succeeded\n");
end_update(OK);
end_update(OK, RS_DONTREPLY);
}
/* If the service has completed initialization after a crash
@ -424,7 +424,7 @@ PUBLIC int do_init_ready(message *m_ptr)
/* If we must keep a replica of this system service, create it now. */
if(rpub->sys_flags & SF_USE_REPL) {
if ((r = clone_service(rp)) != OK) {
if ((r = clone_service(rp, RST_SYS_PROC)) != OK) {
printf("RS: warning: unable to clone %s\n", srv_to_string(rp));
}
}
@ -508,25 +508,15 @@ PUBLIC int do_update(message *m_ptr)
* by the given binary.
*/
if(do_self_update) {
struct rproc *r_next_rp;
if(rs_verbose)
printf("RS: %s performs self update\n", srv_to_string(rp));
/* Save information about existing replica (if any). */
r_next_rp = rp->r_next_rp;
rp->r_next_rp = NULL;
/* Clone the system service and use the replica as the new version. */
s = clone_service(rp);
s = clone_service(rp, LU_SYS_PROC);
if(s != OK) {
printf("RS: do_update: unable to clone service: %d\n", s);
return s;
}
new_rp = rp->r_next_rp;
new_rp->r_prev_rp = NULL;
/* Restore information about existing replica (if any). */
rp->r_next_rp = r_next_rp;
}
else {
if(rs_verbose)
@ -549,7 +539,12 @@ PUBLIC int do_update(message *m_ptr)
/* Let the new version inherit defaults from the old one. */
inherit_service_defaults(rp, new_rp);
/* Link the two versions. */
rp->r_new_rp = new_rp;
new_rp->r_old_rp = rp;
/* Create new version of the service but don't let it run. */
new_rp->r_priv.s_flags |= LU_SYS_PROC;
s = create_service(new_rp);
if(s != OK) {
printf("RS: do_update: unable to create a new service: %d\n", s);
@ -557,9 +552,7 @@ PUBLIC int do_update(message *m_ptr)
}
}
/* Link old version to new version and mark both as updating. */
rp->r_new_rp = new_rp;
new_rp->r_old_rp = rp;
/* Mark both versions as updating. */
rp->r_flags |= RS_UPDATING;
rp->r_new_rp->r_flags |= RS_UPDATING;
rupdate.flags |= RS_UPDATING;
@ -614,10 +607,10 @@ PUBLIC int do_upd_ready(message *m_ptr)
* be replied to and continue executing.
*/
if(result != OK) {
end_update(result);
end_update(result, RS_REPLY);
printf("RS: update failed: %s\n", lu_strerror(result));
return OK;
return EDONTREPLY;
}
/* Perform the update. */
@ -625,21 +618,21 @@ PUBLIC int do_upd_ready(message *m_ptr)
new_rp = rp->r_new_rp;
r = update_service(&old_rp, &new_rp);
if(r != OK) {
end_update(r);
end_update(r, RS_REPLY);
printf("RS: update failed: error %d\n", r);
return r;
return EDONTREPLY;
}
/* Let the new version run. */
r = run_service(new_rp, SEF_INIT_LU);
if(r != OK) {
update_service(&new_rp, &old_rp); /* rollback, can't fail. */
end_update(r);
end_update(r, RS_REPLY);
printf("RS: update failed: error %d\n", r);
return r;
return EDONTREPLY;
}
return(EDONTREPLY);
return EDONTREPLY;
}
/*===========================================================================*
@ -688,8 +681,8 @@ message *m_ptr;
*/
else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
&& rp->r_pid > 0) {
crash_service(rp); /* simulate crash */
rp->r_stop_tm = 0;
crash_service(rp); /* simulate crash */
}
/* There seems to be no special conditions. If the service has a