RS: support for endpoint-changing driver restarts
This commit is contained in:
parent
01015cc0e2
commit
ba19c83fd6
6 changed files with 65 additions and 11 deletions
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
Loading…
Reference in a new issue