Switch to stateful restart.
The following services have been updated to support stateful restarts: - Drivers: tty - Filesystems: isofs, mfs, pfs, libvtreefs-based file servers - System servers: tty, ds, pm, vfs, vm Change-Id: Ie84baa3ba1774047b3ae519808fe4116928edabb
This commit is contained in:
parent
2b641b28b1
commit
0e78c0166c
10 changed files with 192 additions and 28 deletions
|
@ -296,7 +296,6 @@ static void sef_local_startup()
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_restart(sef_cb_init_fresh);
|
|
||||||
|
|
||||||
/* No live update support for now. */
|
/* No live update support for now. */
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,6 @@ static void sef_local_startup(void)
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_restart(sef_cb_init_fail);
|
|
||||||
|
|
||||||
/* No live update support for now. */
|
/* No live update support for now. */
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ static void sef_local_startup()
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_restart(sef_cb_init_fail);
|
|
||||||
|
|
||||||
/* No live update support for now. */
|
/* No live update support for now. */
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,6 @@ pfs_startup(void)
|
||||||
|
|
||||||
/* Register initialization callbacks. */
|
/* Register initialization callbacks. */
|
||||||
sef_setcb_init_fresh(pfs_init);
|
sef_setcb_init_fresh(pfs_init);
|
||||||
sef_setcb_init_restart(sef_cb_init_fail);
|
|
||||||
|
|
||||||
/* No live update support for now. */
|
/* No live update support for now. */
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ int sef_self_receiving;
|
||||||
/* Extern variables. */
|
/* Extern variables. */
|
||||||
EXTERN int sef_lu_state;
|
EXTERN int sef_lu_state;
|
||||||
EXTERN int __sef_st_before_receive_enabled;
|
EXTERN int __sef_st_before_receive_enabled;
|
||||||
|
EXTERN __attribute__((weak)) int __vm_init_fresh;
|
||||||
|
|
||||||
/* Debug. */
|
/* Debug. */
|
||||||
#if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG
|
#if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG
|
||||||
|
@ -109,8 +110,8 @@ void sef_startup()
|
||||||
panic("RS unable to complete init: %d", r);
|
panic("RS unable to complete init: %d", r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(sef_self_endpoint == VM_PROC_NR) {
|
else if(sef_self_endpoint == VM_PROC_NR && __vm_init_fresh) {
|
||||||
/* VM handles initialization by RS later */
|
/* VM handles fresh initialization by RS later */
|
||||||
} else {
|
} else {
|
||||||
message m;
|
message m;
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@ sef_local_startup(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
sef_setcb_init_fresh(init_server);
|
sef_setcb_init_fresh(init_server);
|
||||||
sef_setcb_init_restart(init_server);
|
|
||||||
|
|
||||||
sef_setcb_signal_handler(got_signal);
|
sef_setcb_signal_handler(got_signal);
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,6 @@ static void sef_local_startup()
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_restart(sef_cb_init_fail);
|
|
||||||
|
|
||||||
/* Register state transfer callbacks. */
|
/* Register state transfer callbacks. */
|
||||||
sef_llvm_ds_st_init();
|
sef_llvm_ds_st_init();
|
||||||
|
|
|
@ -114,7 +114,6 @@ static void sef_local_startup()
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_restart(sef_cb_init_fail);
|
|
||||||
|
|
||||||
/* No live update support for now. */
|
/* No live update support for now. */
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,6 @@ static void sef_local_startup()
|
||||||
{
|
{
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_restart(sef_cb_init_fail);
|
|
||||||
|
|
||||||
/* No live update support for now. */
|
/* No live update support for now. */
|
||||||
|
|
||||||
|
|
|
@ -60,13 +60,34 @@ struct {
|
||||||
((c) - VM_RQ_BASE) : -1)
|
((c) - VM_RQ_BASE) : -1)
|
||||||
|
|
||||||
static int map_service(struct rprocpub *rpub);
|
static int map_service(struct rprocpub *rpub);
|
||||||
static int do_rs_init(message *m);
|
|
||||||
|
static struct rprocpub rprocpub[NR_SYS_PROCS];
|
||||||
|
int __vm_init_fresh;
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
/* SEF functions and variables. */
|
||||||
|
static void sef_local_startup(void);
|
||||||
|
static int sef_cb_init_lu_restart(int type, sef_init_info_t *info);
|
||||||
|
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
||||||
static void sef_cb_signal_handler(int signo);
|
static void sef_cb_signal_handler(int signo);
|
||||||
|
|
||||||
void init_vm(void);
|
void init_vm(void);
|
||||||
|
|
||||||
|
int do_sef_init_request(message *);
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* is_first_time *
|
||||||
|
*===========================================================================*/
|
||||||
|
static int is_first_time(void)
|
||||||
|
{
|
||||||
|
struct proc rs_proc;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((r = sys_getproc(&rs_proc, RS_PROC_NR)) != OK)
|
||||||
|
panic("VM: couldn't get RS process data: %d", r);
|
||||||
|
|
||||||
|
return RTS_ISSET(&rs_proc, RTS_BOOTINHIBIT);
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* main *
|
* main *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -76,15 +97,15 @@ int main(void)
|
||||||
int result, who_e, rcv_sts;
|
int result, who_e, rcv_sts;
|
||||||
int caller_slot;
|
int caller_slot;
|
||||||
|
|
||||||
/* Initialize system so that all processes are runnable */
|
/* Initialize system so that all processes are runnable the first time. */
|
||||||
init_vm();
|
if (is_first_time()) {
|
||||||
|
init_vm();
|
||||||
|
__vm_init_fresh=1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Register init callbacks. */
|
/* SEF local startup. */
|
||||||
sef_setcb_init_restart(sef_cb_init_fail);
|
sef_local_startup();
|
||||||
sef_setcb_signal_handler(sef_cb_signal_handler);
|
__vm_init_fresh=0;
|
||||||
|
|
||||||
/* Let SEF perform startup. */
|
|
||||||
sef_startup();
|
|
||||||
|
|
||||||
SANITYCHECK(SCL_TOP);
|
SANITYCHECK(SCL_TOP);
|
||||||
|
|
||||||
|
@ -127,7 +148,9 @@ int main(void)
|
||||||
/* Calls that use the transid */
|
/* Calls that use the transid */
|
||||||
result = do_procctl(&msg, transid);
|
result = do_procctl(&msg, transid);
|
||||||
} else if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) {
|
} else if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) {
|
||||||
result = do_rs_init(&msg);
|
result = do_sef_init_request(&msg);
|
||||||
|
if(result != OK) panic("do_sef_init_request failed!\n");
|
||||||
|
result = SUSPEND; /* do not reply to RS */
|
||||||
} else if (msg.m_type == VM_PAGEFAULT) {
|
} else if (msg.m_type == VM_PAGEFAULT) {
|
||||||
if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) {
|
if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) {
|
||||||
printf("VM: process %d faked VM_PAGEFAULT "
|
printf("VM: process %d faked VM_PAGEFAULT "
|
||||||
|
@ -171,13 +194,26 @@ int main(void)
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_rs_init(message *m)
|
static void sef_local_startup(void)
|
||||||
|
{
|
||||||
|
/* Register init callbacks. */
|
||||||
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
|
sef_setcb_init_lu(sef_cb_init_lu_restart);
|
||||||
|
sef_setcb_init_restart(sef_cb_init_lu_restart);
|
||||||
|
|
||||||
|
/* Register signal callbacks. */
|
||||||
|
sef_setcb_signal_handler(sef_cb_signal_handler);
|
||||||
|
|
||||||
|
/* Let SEF perform startup. */
|
||||||
|
sef_startup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
{
|
{
|
||||||
int s, i;
|
int s, i;
|
||||||
static struct rprocpub rprocpub[NR_BOOT_PROCS];
|
|
||||||
|
|
||||||
/* Map all the services in the boot image. */
|
/* Map all the services in the boot image. */
|
||||||
if((s = sys_safecopyfrom(RS_PROC_NR, m->m_rs_init.rproctab_gid, 0,
|
if((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
|
||||||
(vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
|
(vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
|
||||||
panic("vm: sys_safecopyfrom (rs) failed: %d", s);
|
panic("vm: sys_safecopyfrom (rs) failed: %d", s);
|
||||||
}
|
}
|
||||||
|
@ -190,11 +226,7 @@ static int do_rs_init(message *m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RS expects this response that it then again wants to reply to: */
|
return(OK);
|
||||||
m->m_rs_init.result = OK;
|
|
||||||
ipc_sendrec(RS_PROC_NR, m);
|
|
||||||
|
|
||||||
return(SUSPEND);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vmproc *init_proc(endpoint_t ep_nr)
|
static struct vmproc *init_proc(endpoint_t ep_nr)
|
||||||
|
@ -528,6 +560,145 @@ void init_vm(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* sef_cb_init_vm_multi_lu *
|
||||||
|
*===========================================================================*/
|
||||||
|
static int sef_cb_init_vm_multi_lu(int type, sef_init_info_t *info)
|
||||||
|
{
|
||||||
|
message m;
|
||||||
|
int i, r;
|
||||||
|
ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS];
|
||||||
|
int num_elements;
|
||||||
|
|
||||||
|
if(type != SEF_INIT_LU || !(info->flags & SEF_LU_MULTI)) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is a multi-component update, we need to perform the update
|
||||||
|
* for services that need to be updated. In addition, make sure VM
|
||||||
|
* can only receive messages from RS, tasks, and other services being
|
||||||
|
* updated until RS specifically sends a special update cancel message.
|
||||||
|
* This is necessary to limit the number of VM state changes to support
|
||||||
|
* rollback. Allow only safe message types for safe updates.
|
||||||
|
*/
|
||||||
|
memset(ipc_filter, 0, sizeof(ipc_filter));
|
||||||
|
num_elements = 0;
|
||||||
|
ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
|
||||||
|
ipc_filter[num_elements++].m_source = RS_PROC_NR;
|
||||||
|
if(info->flags & SEF_LU_UNSAFE) {
|
||||||
|
ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
|
||||||
|
ipc_filter[num_elements++].m_source = ANY_TSK;
|
||||||
|
}
|
||||||
|
if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
|
||||||
|
(vir_bytes) rprocpub, NR_SYS_PROCS*sizeof(struct rprocpub))) != OK) {
|
||||||
|
panic("sys_safecopyfrom failed: %d", r);
|
||||||
|
}
|
||||||
|
m.m_source = VM_PROC_NR;
|
||||||
|
for(i=0;i < NR_SYS_PROCS;i++) {
|
||||||
|
if(rprocpub[i].in_use && rprocpub[i].old_endpoint != NONE) {
|
||||||
|
if(num_elements <= IPCF_MAX_ELEMENTS-3) {
|
||||||
|
ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
|
||||||
|
ipc_filter[num_elements].m_source = rprocpub[i].old_endpoint;
|
||||||
|
if(!(info->flags & SEF_LU_UNSAFE)) {
|
||||||
|
ipc_filter[num_elements].flags |= IPCF_MATCH_M_TYPE;
|
||||||
|
ipc_filter[num_elements].m_type = VM_BRK;
|
||||||
|
}
|
||||||
|
num_elements++;
|
||||||
|
ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
|
||||||
|
ipc_filter[num_elements].m_source = rprocpub[i].new_endpoint;
|
||||||
|
if(!(info->flags & SEF_LU_UNSAFE)) {
|
||||||
|
ipc_filter[num_elements].flags |= IPCF_MATCH_M_TYPE;
|
||||||
|
ipc_filter[num_elements].m_type = VM_BRK;
|
||||||
|
}
|
||||||
|
num_elements++;
|
||||||
|
/* Make sure we can talk to any RS instance. */
|
||||||
|
if(rprocpub[i].old_endpoint == RS_PROC_NR) {
|
||||||
|
ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
|
||||||
|
ipc_filter[num_elements++].m_source = rprocpub[i].new_endpoint;
|
||||||
|
}
|
||||||
|
else if(rprocpub[i].new_endpoint == RS_PROC_NR) {
|
||||||
|
ipc_filter[num_elements].flags = IPCF_MATCH_M_SOURCE;
|
||||||
|
ipc_filter[num_elements++].m_source = rprocpub[i].old_endpoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("sef_cb_init_vm_multi_lu: skipping ipc filter elements for %d and %d\n",
|
||||||
|
rprocpub[i].old_endpoint, rprocpub[i].new_endpoint);
|
||||||
|
}
|
||||||
|
if(rprocpub[i].sys_flags & SF_VM_UPDATE) {
|
||||||
|
m.m_lsys_vm_update.src = rprocpub[i].new_endpoint;
|
||||||
|
m.m_lsys_vm_update.dst = rprocpub[i].old_endpoint;
|
||||||
|
m.m_lsys_vm_update.flags = rprocpub[i].sys_flags;
|
||||||
|
r = do_rs_update(&m);
|
||||||
|
if(r != OK && r != SUSPEND) {
|
||||||
|
printf("sef_cb_init_vm_multi_lu: do_rs_update failed: %d", r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sys_statectl(SYS_STATE_ADD_IPC_WL_FILTER, ipc_filter, num_elements*sizeof(ipc_filter_el_t));
|
||||||
|
if(r != OK) {
|
||||||
|
printf("sef_cb_init_vm_multi_lu: sys_statectl failed: %d", r);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* sef_cb_init_lu_restart *
|
||||||
|
*===========================================================================*/
|
||||||
|
static int sef_cb_init_lu_restart(int type, sef_init_info_t *info)
|
||||||
|
{
|
||||||
|
/* Restart the vm server. */
|
||||||
|
int r;
|
||||||
|
endpoint_t old_e;
|
||||||
|
int old_p;
|
||||||
|
struct vmproc *old_vmp, *new_vmp;
|
||||||
|
|
||||||
|
/* Perform default state transfer first. Assume VM doesn't brk(). */
|
||||||
|
if(type == SEF_INIT_LU) {
|
||||||
|
sef_setcb_init_restart(SEF_CB_INIT_RESTART_DEFAULT);
|
||||||
|
r = SEF_CB_INIT_LU_DEFAULT(type, info);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = SEF_CB_INIT_RESTART_DEFAULT(type, info);
|
||||||
|
}
|
||||||
|
if(r != OK) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lookup slots for old process. */
|
||||||
|
old_e = info->old_endpoint;
|
||||||
|
if(vm_isokendpt(old_e, &old_p) != OK) {
|
||||||
|
printf("sef_cb_init_lu_restart: bad old endpoint %d\n", old_e);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
old_vmp = &vmproc[old_p];
|
||||||
|
new_vmp = &vmproc[VM_PROC_NR];
|
||||||
|
|
||||||
|
/* Swap proc slots and dynamic data. */
|
||||||
|
if((r = swap_proc_slot(old_vmp, new_vmp)) != OK) {
|
||||||
|
printf("sef_cb_init_lu_restart: swap_proc_slot failed\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if((r = swap_proc_dyn_data(old_vmp, new_vmp, 0)) != OK) {
|
||||||
|
printf("sef_cb_init_lu_restart: swap_proc_dyn_data failed\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rebind page tables. */
|
||||||
|
pt_bind(&new_vmp->vm_pt, new_vmp);
|
||||||
|
pt_bind(&old_vmp->vm_pt, old_vmp);
|
||||||
|
pt_clearmapcache();
|
||||||
|
|
||||||
|
/* Adjust process references. */
|
||||||
|
adjust_proc_refs();
|
||||||
|
|
||||||
|
/* Handle multi-component live update when necessary. */
|
||||||
|
return sef_cb_init_vm_multi_lu(type, info);
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* sef_cb_signal_handler *
|
* sef_cb_signal_handler *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
Loading…
Reference in a new issue