RS: support for endpoint-changing driver restarts

This commit is contained in:
David van Moolenbroek 2011-12-05 10:51:30 +01:00
parent 01015cc0e2
commit ba19c83fd6
6 changed files with 65 additions and 11 deletions

View file

@ -33,6 +33,7 @@
#define RS_INITIALIZING 0x040 /* set when init is in progress */ #define RS_INITIALIZING 0x040 /* set when init is in progress */
#define RS_UPDATING 0x080 /* set when update is in progress */ #define RS_UPDATING 0x080 /* set when update is in progress */
#define RS_ACTIVE 0x100 /* set for the active instance of a service */ #define RS_ACTIVE 0x100 /* set for the active instance of a service */
#define RS_REINCARNATE 0x200 /* after exit, restart with a new endpoint */
/* Sys flag values. */ /* Sys flag values. */
#define SF_CORE_SRV 0x001 /* set for core system services */ #define SF_CORE_SRV 0x001 /* set for core system services */

View file

@ -23,16 +23,16 @@ static int load_aout(struct exec_info *execi);
static int load_elf(struct exec_info *execi); static int load_elf(struct exec_info *execi);
/* Array of loaders for different object formats */ /* Array of loaders for different object formats */
struct exec_loaders { static struct exec_loaders {
int (*load_object)(struct exec_info *); int (*load_object)(struct exec_info *);
} static const exec_loaders[] = { } const exec_loaders[] = {
{ load_aout }, { load_aout },
{ load_elf }, { load_elf },
{ NULL } { NULL }
}; };
int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv, int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv,
char **Xenvp) char **UNUSED(Xenvp))
{ {
char * const *ap; char * const *ap;
char * const *ep; char * const *ep;

View file

@ -161,7 +161,7 @@ PRIVATE void sef_local_startup()
/*===========================================================================* /*===========================================================================*
* sef_cb_init_fresh * * sef_cb_init_fresh *
*===========================================================================*/ *===========================================================================*/
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
{ {
/* Initialize the reincarnation server. */ /* Initialize the reincarnation server. */
struct boot_image *ip; struct boot_image *ip;

View file

@ -423,8 +423,9 @@ struct rproc *rp;
srv_kill(rp->r_pid, SIGKILL); srv_kill(rp->r_pid, SIGKILL);
} }
/* Free slot */ /* Free slot, unless we're about to reuse it */
free_slot(rp); if (!(rp->r_flags & RS_REINCARNATE))
free_slot(rp);
} }
/*===========================================================================* /*===========================================================================*
@ -941,6 +942,40 @@ PUBLIC void activate_service(struct rproc *rp, struct rproc *ex_rp)
} }
} }
/*===========================================================================*
* reincarnate_service *
*===========================================================================*/
PUBLIC void reincarnate_service(struct rproc *rp)
{
/* Restart a service as if it were never started before. */
struct rprocpub *rpub;
int i;
rpub = rp->r_pub;
rp->r_flags &= RS_IN_USE;
rp->r_pid = -1;
rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL;
/* Restore original IRQ and I/O range tables in the priv struct. This is the
* only part of the privilege structure that can be modified by processes
* other than RS itself.
*/
rp->r_priv.s_nr_irq = rp->r_nr_irq;
for (i = 0; i < rp->r_nr_irq; i++)
rp->r_priv.s_irq_tab[i] = rp->r_irq_tab[i];
rp->r_priv.s_nr_io_range = rp->r_nr_io_range;
for (i = 0; i < rp->r_nr_io_range; i++)
rp->r_priv.s_io_tab[i] = rp->r_io_tab[i];
rp->r_old_rp = NULL;
rp->r_new_rp = NULL;
rp->r_prev_rp = NULL;
rp->r_next_rp = NULL;
start_service(rp);
}
/*===========================================================================* /*===========================================================================*
* terminate_service * * terminate_service *
*===========================================================================*/ *===========================================================================*/
@ -959,9 +994,10 @@ PUBLIC void terminate_service(struct rproc *rp)
/* Deal with failures during initialization. */ /* Deal with failures during initialization. */
if(rp->r_flags & RS_INITIALIZING) { if(rp->r_flags & RS_INITIALIZING) {
printf("RS: service '%s' exited during initialization\n", rpub->label); if(rs_verbose)
printf("RS: service '%s' exited during initialization\n",
rpub->label);
rp->r_flags |= RS_EXITING; /* don't restart. */ rp->r_flags |= RS_EXITING; /* don't restart. */
sys_sysctl_stacktrace(rp->r_pub->endpoint);
/* If updating, rollback. */ /* If updating, rollback. */
if(rp->r_flags & RS_UPDATING) { if(rp->r_flags & RS_UPDATING) {
@ -995,6 +1031,14 @@ PUBLIC void terminate_service(struct rproc *rp)
for(i=0;i<nr_rps;i++) { for(i=0;i<nr_rps;i++) {
cleanup_service(rps[i]); cleanup_service(rps[i]);
} }
/* If the service is reincarnating, its slot has not been cleaned up.
* Check for this flag now, and attempt to start the service again.
* If this fails, start_service() itself will perform cleanup.
*/
if (rp->r_flags & RS_REINCARNATE) {
reincarnate_service(rp);
}
} }
else if(rp->r_flags & RS_REFRESHING) { else if(rp->r_flags & RS_REFRESHING) {
/* Restart service. */ /* Restart service. */
@ -1335,9 +1379,9 @@ endpoint_t source;
printf("RS: edit_slot: too many IRQs requested\n"); printf("RS: edit_slot: too many IRQs requested\n");
return EINVAL; return EINVAL;
} }
rp->r_priv.s_nr_irq= rs_start->rss_nr_irq; rp->r_nr_irq= rp->r_priv.s_nr_irq= rs_start->rss_nr_irq;
for (i= 0; i<rp->r_priv.s_nr_irq; i++) { for (i= 0; i<rp->r_priv.s_nr_irq; i++) {
rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i]; rp->r_irq_tab[i]= rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i];
if(rs_verbose) if(rs_verbose)
printf("RS: edit_slot: IRQ %d\n", rp->r_priv.s_irq_tab[i]); printf("RS: edit_slot: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
} }
@ -1353,11 +1397,12 @@ endpoint_t source;
printf("RS: edit_slot: too many I/O ranges requested\n"); printf("RS: edit_slot: too many I/O ranges requested\n");
return EINVAL; return EINVAL;
} }
rp->r_priv.s_nr_io_range= rs_start->rss_nr_io; rp->r_nr_io_range= rp->r_priv.s_nr_io_range= rs_start->rss_nr_io;
for (i= 0; i<rp->r_priv.s_nr_io_range; i++) { for (i= 0; i<rp->r_priv.s_nr_io_range; i++) {
rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base; rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base;
rp->r_priv.s_io_tab[i].ior_limit= rp->r_priv.s_io_tab[i].ior_limit=
rs_start->rss_io[i].base+rs_start->rss_io[i].len-1; rs_start->rss_io[i].base+rs_start->rss_io[i].len-1;
rp->r_io_tab[i] = rp->r_priv.s_io_tab[i];
if(rs_verbose) if(rs_verbose)
printf("RS: edit_slot: I/O [%x..%x]\n", printf("RS: edit_slot: I/O [%x..%x]\n",
rp->r_priv.s_io_tab[i].ior_base, rp->r_priv.s_io_tab[i].ior_base,

View file

@ -426,6 +426,8 @@ PUBLIC int do_init_ready(message *m_ptr)
if(rs_verbose) if(rs_verbose)
printf("RS: %s initialization error: %s\n", srv_to_string(rp), printf("RS: %s initialization error: %s\n", srv_to_string(rp),
init_strerror(result)); init_strerror(result));
if (result == ERESTART)
rp->r_flags |= RS_REINCARNATE;
crash_service(rp); /* simulate crash */ crash_service(rp); /* simulate crash */
return EDONTREPLY; return EDONTREPLY;
} }

View file

@ -67,6 +67,12 @@ struct rproc {
int r_quantum; int r_quantum;
int r_cpu; int r_cpu;
/* Backup values from the privilege structure. */
struct io_range r_io_tab[NR_IO_RANGE];
int r_nr_io_range;
int r_irq_tab[NR_IRQ];
int r_nr_irq;
char r_ipc_list[MAX_IPC_LIST]; char r_ipc_list[MAX_IPC_LIST];
int r_nr_control; int r_nr_control;
char r_control[RS_NR_CONTROL][RS_MAX_LABEL_LEN]; char r_control[RS_NR_CONTROL][RS_MAX_LABEL_LEN];