]> Zhao Yanbai Git Server - minix.git/commitdiff
kernel: Handle IPC properly at live update time. 83/3083/2
authorCristiano Giuffrida <giuffrida@cs.vu.nl>
Tue, 11 Mar 2014 17:06:45 +0000 (18:06 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 16 Sep 2015 11:02:53 +0000 (11:02 +0000)
Change-Id: I2dfc6c6cf4d2bfe198e159d3e4b7c50d0bb499c8

minix/kernel/priv.h
minix/kernel/proc.c
minix/kernel/system/do_privctl.c
minix/kernel/system/do_update.c

index 4efd9e8778a5d87d73081f456ac2d8939d12b210..4303ac4976a47aafbd6feb86b82055ff882ef927 100644 (file)
@@ -30,6 +30,7 @@ struct priv {
   size_t s_asynsize;           /* number of elements in table. 0 when not in
                                 * use
                                 */
+  endpoint_t s_asynendpoint;    /* the endpoint the asyn table belongs to. */
 
   short s_trap_mask;           /* allowed system call traps */
   sys_map_t s_ipc_to;          /* allowed destination processes */
index 1629b3ca697d9d55dd5985b342234c4e43d16dee..bc8458f4c146e5ba886ca3bc890320ab9a32fbf4 100644 (file)
@@ -1153,6 +1153,7 @@ int try_deliver_senda(struct proc *caller_ptr,
   /* Clear table */
   privp->s_asyntab = -1;
   privp->s_asynsize = 0;
+  privp->s_asynendpoint = caller_ptr->p_endpoint;
 
   if (size == 0) return(OK);  /* Nothing to do, just return */
 
@@ -1346,6 +1347,7 @@ static int try_one(endpoint_t receive_e, struct proc *src_ptr,
   unset_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
 
   if (size == 0) return(EAGAIN);
+  if (privp->s_asynendpoint != src_ptr->p_endpoint) return EAGAIN;
   if (!may_asynsend_to(src_ptr, proc_nr(dst_ptr))) return (ECALLDENIED);
 
   caller_ptr = src_ptr;        /* Needed for A_ macros later on */
index 188cea93913e9cd708f11009741d95fee5fd2821..1dd19423e84d2ae11942e636504e1a46a43fb923 100644 (file)
@@ -126,6 +126,7 @@ int do_privctl(struct proc * caller, message * m_ptr)
        reset_kernel_timer(&priv(rp)->s_alarm_timer);   /* - alarm */
        priv(rp)->s_asyntab= -1;                        /* - asynsends */
        priv(rp)->s_asynsize= 0;
+       priv(rp)->s_asynendpoint = rp->p_endpoint;
        priv(rp)->s_diag_sig = FALSE;           /* no request for diag sigs */
 
        /* Set defaults for privilege bitmaps. */
index 14792c92eecde6b6c2b748b38bb9874877ed85ac..089037b88f460c2a695fb090ad8993b89b502a5e 100644 (file)
 static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp);
 static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp);
 static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp);
+static void abort_proc_ipc_send(struct proc *rp);
 static void adjust_proc_slot(struct proc *rp, struct proc *from_rp);
 static void adjust_priv_slot(struct priv *privp, struct priv
        *from_privp);
+static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp);
 static void swap_proc_slot_pointer(struct proc **rpp, struct proc
        *src_rp, struct proc *dst_rp);
 
@@ -38,7 +40,7 @@ int do_update(struct proc * caller, message * m_ptr)
  * slots.
  */
   endpoint_t src_e, dst_e;
-  int src_p, dst_p;
+  int src_p, dst_p, flags;
   struct proc *src_rp, *dst_rp;
   struct priv *src_privp, *dst_privp;
   struct proc orig_src_proc;
@@ -48,6 +50,7 @@ int do_update(struct proc * caller, message * m_ptr)
   int i, r;
 
   /* Lookup slots for source and destination process. */
+  flags = m_ptr->SYS_UPD_FLAGS;
   src_e = m_ptr->SYS_UPD_SRC_ENDPT;
   if(!isokendpt(src_e, &src_p)) {
       return EINVAL;
@@ -112,6 +115,15 @@ int do_update(struct proc * caller, message * m_ptr)
   orig_dst_proc = *dst_rp;
   orig_dst_priv = *(priv(dst_rp));
 
+  /* Adjust asyn tables. */
+  adjust_asyn_table(priv(src_rp), priv(dst_rp));
+  adjust_asyn_table(priv(dst_rp), priv(src_rp));
+
+  /* Abort any pending send() on rollback. */
+  if(flags & SYS_UPD_ROLLBACK) {
+      abort_proc_ipc_send(src_rp);
+  }
+
   /* Swap slots. */
   *src_rp = orig_dst_proc;
   *src_privp = orig_dst_priv;
@@ -195,6 +207,27 @@ int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp)
   return OK;
 }
 
+/*===========================================================================*
+ *                         abort_proc_ipc_send                              *
+ *===========================================================================*/
+void abort_proc_ipc_send(struct proc *rp)
+{
+  if(RTS_ISSET(rp, RTS_SENDING)) {
+      struct proc **xpp;
+      RTS_UNSET(rp, RTS_SENDING);
+      rp->p_misc_flags &= ~MF_SENDING_FROM_KERNEL;
+      xpp = &(proc_addr(_ENDPOINT_P(rp->p_sendto_e))->p_caller_q);
+      while (*xpp) {
+          if(*xpp == rp) {
+              *xpp = rp->p_q_link;
+              rp->p_q_link = NULL;
+              break;
+          }
+          xpp = &(*xpp)->p_q_link;
+      }
+  }
+}
+
 /*===========================================================================*
  *                          adjust_proc_slot                                *
  *===========================================================================*/
@@ -205,6 +238,7 @@ static void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
   rp->p_nr = from_rp->p_nr;
   rp->p_priv = from_rp->p_priv;
   priv(rp)->s_proc_nr = from_rp->p_nr;
+
   rp->p_caller_q = from_rp->p_caller_q;
 
   /* preserve scheduling */
@@ -216,6 +250,27 @@ static void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
 #endif
 }
 
+/*===========================================================================*
+ *                          adjust_asyn_table                               *
+ *===========================================================================*/
+static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp)
+{
+  /* Transfer the asyn table if source's table belongs to the destination. */
+  endpoint_t src_e = proc_addr(src_privp->s_proc_nr)->p_endpoint;
+  endpoint_t dst_e = proc_addr(dst_privp->s_proc_nr)->p_endpoint;
+
+  if(src_privp->s_asynsize > 0 && dst_privp->s_asynsize > 0 && src_privp->s_asynendpoint == dst_e) {
+      if(data_copy(src_e, src_privp->s_asyntab, dst_e, dst_privp->s_asyntab,
+         src_privp->s_asynsize*sizeof(asynmsg_t)) != OK) {
+         printf("Warning: unable to transfer asyn table from ep %d to ep %d\n",
+             src_e, dst_e);
+      }
+      else {
+          dst_privp->s_asynsize = src_privp->s_asynsize;
+      }
+  }
+}
+
 /*===========================================================================*
  *                          adjust_priv_slot                                *
  *===========================================================================*/