]> Zhao Yanbai Git Server - minix.git/commitdiff
Switch to stateful restart. 08/3108/1
authorCristiano Giuffrida <giuffrida@cs.vu.nl>
Sat, 1 Mar 2014 22:52:17 +0000 (23:52 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 17 Sep 2015 13:26:22 +0000 (13:26 +0000)
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

minix/drivers/tty/tty/tty.c
minix/fs/isofs/main.c
minix/fs/mfs/main.c
minix/fs/pfs/pfs.c
minix/lib/libsys/sef.c
minix/lib/libvtreefs/vtreefs.c
minix/servers/ds/main.c
minix/servers/pm/main.c
minix/servers/vfs/main.c
minix/servers/vm/main.c

index 841035acd74427530f4be1d904dc44b0cf258332..edfc3ad74eb461f65d685365f7ee80b52f67714c 100644 (file)
@@ -296,7 +296,6 @@ static void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fresh);
 
   /* No live update support for now. */
 
index 2dd3267b6ab8258a1cc90b7a7b1240192db25d79..f301ac51e4f368d4322e7a2668653cf3582439c6 100644 (file)
@@ -44,7 +44,6 @@ static void sef_local_startup(void)
 {
        /* Register init callbacks. */
        sef_setcb_init_fresh(sef_cb_init_fresh);
-       sef_setcb_init_restart(sef_cb_init_fail);
 
        /* No live update support for now. */
 
index da34ba9e2892002f2eb7de33b9e4bb0b6768fe27..d6cda6ae4a29bca7c34f0b6d45d5faed73fe7de5 100644 (file)
@@ -32,7 +32,6 @@ static void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
index 050edd1532f652a8b2cbeecb45fce918ea95a146..b9d751e33096799a549f4727a465b84976b82106 100644 (file)
@@ -408,7 +408,6 @@ pfs_startup(void)
 
        /* Register initialization callbacks. */
        sef_setcb_init_fresh(pfs_init);
-       sef_setcb_init_restart(sef_cb_init_fail);
 
        /* No live update support for now. */
 
index 9d385f9ca8997e98eb7698a45eaad01eb7a51948..b575804d8c91fb123b80d284c298ae324d61d3e9 100644 (file)
@@ -21,6 +21,7 @@ int sef_self_receiving;
 /* Extern variables. */
 EXTERN int sef_lu_state;
 EXTERN int __sef_st_before_receive_enabled;
+EXTERN __attribute__((weak)) int __vm_init_fresh;
 
 /* 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);
       }
   }
-  else if(sef_self_endpoint == VM_PROC_NR) {
-       /* VM handles initialization by RS later */
+  else if(sef_self_endpoint == VM_PROC_NR && __vm_init_fresh) {
+      /* VM handles fresh initialization by RS later */
   } else {
       message m;
 
index dc5fbe80a7310e22d317abdd6020ff2cf1ae3090..36064439c8dbc069da4f4e926a045f6c447ea8ad 100644 (file)
@@ -53,7 +53,6 @@ sef_local_startup(void)
 {
 
        sef_setcb_init_fresh(init_server);
-       sef_setcb_init_restart(init_server);
 
        sef_setcb_signal_handler(got_signal);
 
index 594732897a05c42b41d83c4548cc3271de26aa1b..b61f2c8b6ac59e13d6be26ffe26e13685e7c4e90 100644 (file)
@@ -94,7 +94,6 @@ static void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* Register state transfer callbacks. */
   sef_llvm_ds_st_init();
index 3e5004baf7724a8c604af0460a9bae5dc59111f0..82bc1b9513422ae8cb8d2f92e3c62449c437bce4 100644 (file)
@@ -114,7 +114,6 @@ static void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
index 6b7eb8a68a59144753bb660d44dea846aa273ba5..354565ce317d707341c15d6e8c203602446ef722 100644 (file)
@@ -290,7 +290,6 @@ static void sef_local_startup()
 {
   /* Register init callbacks. */
   sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fail);
 
   /* No live update support for now. */
 
index 6f314fcc14ec27f6004d39b775d84556f055b334..29ead3174c9dc091a0de054ef6b8a9ef32c7fa30 100644 (file)
@@ -60,13 +60,34 @@ struct {
                        ((c) - VM_RQ_BASE) : -1)
 
 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. */
+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);
 
 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                                         *
  *===========================================================================*/
@@ -76,15 +97,15 @@ int main(void)
   int result, who_e, rcv_sts;
   int caller_slot;
 
-  /* Initialize system so that all processes are runnable */
-  init_vm();
-
-  /* Register init callbacks. */
-  sef_setcb_init_restart(sef_cb_init_fail);
-  sef_setcb_signal_handler(sef_cb_signal_handler);
+  /* Initialize system so that all processes are runnable the first time. */
+  if (is_first_time()) {
+       init_vm();
+       __vm_init_fresh=1;
+  }
 
-  /* Let SEF perform startup. */
-  sef_startup();
+  /* SEF local startup. */
+  sef_local_startup();
+  __vm_init_fresh=0;
 
   SANITYCHECK(SCL_TOP);
 
@@ -127,7 +148,9 @@ int main(void)
                /* Calls that use the transid */
                result = do_procctl(&msg, transid);
        } 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) {
                if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) {
                        printf("VM: process %d faked VM_PAGEFAULT "
@@ -171,13 +194,26 @@ int main(void)
   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;
-       static struct rprocpub rprocpub[NR_BOOT_PROCS];
 
        /* 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) {
                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: */
-       m->m_rs_init.result = OK;
-       ipc_sendrec(RS_PROC_NR, m);
-
-       return(SUSPEND);
+       return(OK);
 }
 
 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                             *
  *===========================================================================*/