RS crash recovery support.
This commit is contained in:
parent
e920c1e1df
commit
1f8dbed029
21 changed files with 429 additions and 200 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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: ");
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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") &&
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue