]> Zhao Yanbai Git Server - minix.git/commitdiff
RS: support for endpoint-changing driver restarts
authorDavid van Moolenbroek <david@minix3.org>
Mon, 5 Dec 2011 09:51:30 +0000 (10:51 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Mon, 5 Dec 2011 15:28:07 +0000 (16:28 +0100)
servers/rs/const.h
servers/rs/exec.c
servers/rs/main.c
servers/rs/manager.c
servers/rs/request.c
servers/rs/type.h

index 9b0be8e26ebe67a76b7b338d66b40ea9a26ffbd1..87733ef6e2a506f010f5a3dc09acf26e5e091014 100644 (file)
@@ -33,6 +33,7 @@
 #define RS_INITIALIZING 0x040    /* set when init 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_REINCARNATE  0x200    /* after exit, restart with a new endpoint */
 
 /* Sys flag values. */
 #define SF_CORE_SRV     0x001    /* set for core system services */
index 57a24ced63de6ed54f95f502f5c2df66559e7312..1e5556b54335361dc5739704a7a667e2df9ce756 100644 (file)
@@ -23,16 +23,16 @@ static int load_aout(struct exec_info *execi);
 static int load_elf(struct exec_info *execi);
 
 /* Array of loaders for different object formats */
-struct exec_loaders {
+static struct exec_loaders {
        int (*load_object)(struct exec_info *);
-} static const exec_loaders[] = {
+} const exec_loaders[] = {
        { load_aout },
        { load_elf },
        { NULL }
 };
 
 int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv,
-       char **Xenvp)
+       char **UNUSED(Xenvp))
 {
        char * const *ap;
        char * const *ep;
index fa1d55b02719e36d30c0b4b4c249036eed9ed628..34b376b22e833a37f8031d6f360d9673e00ca6a7 100644 (file)
@@ -161,7 +161,7 @@ PRIVATE void sef_local_startup()
 /*===========================================================================*
  *                         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. */
   struct boot_image *ip;
index c5eba016e6c7681068d1b3c01f469b385a5c7f45..d9dd58075e4b6f0b4fd52f5845609e260fa5af72 100644 (file)
@@ -423,8 +423,9 @@ struct rproc *rp;
       srv_kill(rp->r_pid, SIGKILL);
   }
 
-  /* Free slot */
-  free_slot(rp);
+  /* Free slot, unless we're about to reuse it */
+  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                              *
  *===========================================================================*/
@@ -959,9 +994,10 @@ PUBLIC void terminate_service(struct rproc *rp)
 
   /* Deal with failures during initialization. */
   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. */
-      sys_sysctl_stacktrace(rp->r_pub->endpoint);
 
       /* If updating, rollback. */
       if(rp->r_flags & RS_UPDATING) {
@@ -995,6 +1031,14 @@ PUBLIC void terminate_service(struct rproc *rp)
       for(i=0;i<nr_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) {
       /* Restart service. */
@@ -1335,9 +1379,9 @@ endpoint_t source;
       printf("RS: edit_slot: too many IRQs requested\n");
       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++) {
-      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)
           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");
       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++) {
       rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base;
       rp->r_priv.s_io_tab[i].ior_limit=
           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)
           printf("RS: edit_slot: I/O [%x..%x]\n",
               rp->r_priv.s_io_tab[i].ior_base,
index eccf60ed5566cb1693406408bf694ec6ee7be7a2..f664f357d92fe565f4e6c594d543e6d20c71d961 100755 (executable)
@@ -426,6 +426,8 @@ PUBLIC int do_init_ready(message *m_ptr)
       if(rs_verbose)
           printf("RS: %s initialization error: %s\n", srv_to_string(rp),
               init_strerror(result));
+      if (result == ERESTART)
+          rp->r_flags |= RS_REINCARNATE;
       crash_service(rp); /* simulate crash */
       return EDONTREPLY;
   }
index 378f26198f1c2cf7ec4a384f71f0daf9e58c9df3..17e92d1d2cc0faf736af8ad1327f875b5e8d2d8e 100644 (file)
@@ -67,6 +67,12 @@ struct rproc {
   int r_quantum;
   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];
   int r_nr_control;
   char r_control[RS_NR_CONTROL][RS_MAX_LABEL_LEN];