xref: /minix/minix/lib/libsys/sef_liveupdate.c (revision 08cbf5a0)
1 #include "syslib.h"
2 #include <assert.h>
3 #include <minix/sysutil.h>
4 #include <minix/rs.h>
5 
6 /* SEF Live update variables. */
7 int sef_lu_state;
8 int __sef_st_before_receive_enabled;
9 char sef_lu_state_eval[SEF_LU_STATE_EVAL_MAX_LEN];
10 static int sef_lu_flags;
11 
12 /* SEF Live update callbacks. */
13 static struct sef_lu_cbs {
14     sef_cb_lu_prepare_t                 sef_cb_lu_prepare;
15     sef_cb_lu_state_isvalid_t           sef_cb_lu_state_isvalid;
16     sef_cb_lu_state_changed_t           sef_cb_lu_state_changed;
17     sef_cb_lu_state_dump_t              sef_cb_lu_state_dump;
18     sef_cb_lu_state_save_t              sef_cb_lu_state_save;
19     sef_cb_lu_response_t                sef_cb_lu_response;
20 } sef_lu_cbs = {
21     SEF_CB_LU_PREPARE_DEFAULT,
22     SEF_CB_LU_STATE_ISVALID_DEFAULT,
23     SEF_CB_LU_STATE_CHANGED_DEFAULT,
24     SEF_CB_LU_STATE_DUMP_DEFAULT,
25     SEF_CB_LU_STATE_SAVE_DEFAULT,
26     SEF_CB_LU_RESPONSE_DEFAULT
27 };
28 
29 /* SEF Live update prototypes for sef_receive(). */
30 void do_sef_lu_before_receive(void);
31 int do_sef_lu_request(message *m_ptr);
32 
33 /* SEF Live update helpers. */
34 static void sef_lu_ready(int result);
35 static void sef_lu_state_change(int state, int flags);
36 int sef_lu_handle_state_data(endpoint_t src_e, int state,
37     cp_grant_id_t state_data_gid);
38 
39 /* Debug. */
40 EXTERN char* sef_debug_header(void);
41 static int sef_lu_debug_cycle = 0;
42 
43 /* Information about SELF. */
44 EXTERN endpoint_t sef_self_endpoint;
45 
46 /*===========================================================================*
47  *                         do_sef_lu_before_receive             	     *
48  *===========================================================================*/
49 void do_sef_lu_before_receive(void)
50 {
51 /* Handle SEF Live update before receive events. */
52   int r;
53 
54   assert(sef_lu_state != SEF_LU_STATE_NULL);
55 
56   /* Debug. */
57 #if SEF_LU_DEBUG
58   sef_lu_debug_cycle++;
59   sef_lu_debug_begin();
60   sef_lu_dprint("%s, cycle=%d. Dumping state variables:\n",
61       sef_debug_header(), sef_lu_debug_cycle);
62   sef_lu_cbs.sef_cb_lu_state_dump(sef_lu_state);
63   sef_lu_debug_end();
64 #endif
65 
66   /* Check the state. For SEF_LU_STATE_WORK_FREE/SEF_LU_STATE_UNREACHABLE,
67    * we are always/never ready. For SEF_LU_STATE_EVAL, evaluate the expression.
68    * For other states, let the callback code handle the event.
69    */
70   switch(sef_lu_state) {
71       case SEF_LU_STATE_WORK_FREE:
72           r = OK;
73       break;
74       case SEF_LU_STATE_UNREACHABLE:
75           r = sef_cb_lu_prepare_never_ready(sef_lu_state);
76       break;
77       case SEF_LU_STATE_PREPARE_CRASH:
78           r = sef_cb_lu_prepare_crash(sef_lu_state);
79       break;
80       case SEF_LU_STATE_EVAL:
81           r = sef_cb_lu_prepare_eval(sef_lu_state);
82       break;
83       default:
84           r = sef_lu_cbs.sef_cb_lu_prepare(sef_lu_state);
85       break;
86   }
87   if(r == OK || r != ENOTREADY) {
88        sef_lu_ready(r);
89   }
90 }
91 
92 /*===========================================================================*
93  *                               do_sef_lu_request              	     *
94  *===========================================================================*/
95 int do_sef_lu_request(message *m_ptr)
96 {
97 /* Handle a SEF Live update request. */
98   int r, state, flags, is_valid_state;
99   cp_grant_id_t rs_state_data_gid;
100 
101   sef_lu_debug_cycle = 0;
102   state = m_ptr->m_rs_update.state;
103   flags = m_ptr->m_rs_update.flags;
104   rs_state_data_gid = m_ptr->m_rs_update.state_data_gid;
105 
106   /* Deal with prepare cancel requests first, where no reply is requested. */
107   if(state == SEF_LU_STATE_NULL) {
108       sef_lu_state_change(SEF_LU_STATE_NULL, 0);
109       return OK;
110   }
111 
112   /* Check if we are already busy. */
113   if(sef_lu_state != SEF_LU_STATE_NULL) {
114       sef_lu_ready(EBUSY);
115       return OK;
116   }
117 
118   /* Otherwise only accept live update requests with a valid state. */
119   is_valid_state = SEF_LU_ALWAYS_ALLOW_DEBUG_STATES && SEF_LU_STATE_IS_DEBUG(state);
120   is_valid_state = is_valid_state || sef_lu_cbs.sef_cb_lu_state_isvalid(state, flags);
121   if(!is_valid_state) {
122       if(sef_lu_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_DEFAULT) {
123           sef_lu_ready(ENOSYS);
124       }
125       else {
126           sef_lu_ready(EINVAL);
127       }
128       return OK;
129   }
130 
131   /* Handle additional state data (if any). */
132   r = sef_lu_handle_state_data(m_ptr->m_source, state, rs_state_data_gid);
133   if(r != OK) {
134       sef_lu_ready(r);
135       return OK;
136   }
137 
138   /* Set the new live update state. */
139   sef_lu_state_change(state, flags);
140 
141 
142   /* Return OK not to let anybody else intercept the request. */
143   return(OK);
144 }
145 
146 /*===========================================================================*
147  *				  sef_lu_ready				     *
148  *===========================================================================*/
149 static void sef_lu_ready(int result)
150 {
151   message m;
152   int r=EINVAL;
153 
154 #if SEF_LU_DEBUG
155   sef_lu_debug_begin();
156   sef_lu_dprint("%s, cycle=%d. Ready to update with result: %d%s\n",
157       sef_debug_header(), sef_lu_debug_cycle,
158       result, (result == OK ? "(OK)" : ""));
159   sef_lu_debug_end();
160 #endif
161 
162   /* If result is OK, let the callback code cleanup and save
163    * any state that must be carried over to the new version.
164    */
165   if(result == OK) {
166       r = sef_llvm_state_cleanup();
167       if(r == OK) {
168           r = sef_lu_cbs.sef_cb_lu_state_save(sef_lu_state, sef_lu_flags);
169       }
170       if(r != OK) {
171           /* Abort update in case of error. */
172           result = r;
173       }
174   }
175 
176   /* Let the callback code produce a live update response and block.
177    * We should get beyond this point only if either result is an error or
178    * something else goes wrong in the callback code.
179    */
180   m.m_source = sef_self_endpoint;
181   m.m_type = RS_LU_PREPARE;
182   m.m_rs_update.state = sef_lu_state;
183   m.m_rs_update.result = result;
184   r = sef_lu_cbs.sef_cb_lu_response(&m);
185 
186 #if SEF_LU_DEBUG
187   sef_lu_debug_begin();
188   sef_lu_dprint("%s, cycle=%d. The %s aborted the update with result %d!\n",
189       sef_debug_header(), sef_lu_debug_cycle,
190       (result == OK ? "server" : "client"),
191       (result == OK ? r : result)); /* EINTR if update was canceled. */
192   sef_lu_debug_end();
193 #endif
194 
195   /* Something went wrong. Update was aborted and we didn't get updated.
196    * Restore things back to normal and continue executing.
197    */
198   sef_lu_state_change(SEF_LU_STATE_NULL, 0);
199 
200   /* Transfer of asynsend tables during live update is messy at best. The
201    * general idea is that the asynsend table is preserved during live update,
202    * so that messages never get lost. That means that 1) the new instance
203    * takes over the table from the old instance upon live update, and 2) the
204    * old instance takes over the table on rollback. Case 1 is not atomic:
205    * the new instance starts with no asynsend table, and after swapping slots,
206    * the old instance's table will no longer be looked at by the kernel. The
207    * new instance copies over the table from the old instance, and then calls
208    * senda_reload() to tell the kernel about the new location of the otherwise
209    * preserved table. Case 2 is different: the old instance cannot copy the
210    * table from the new instance, and so the kernel does that part, based on
211    * the table provided through the new instance's senda_reload(). However, if
212    * the new instance never got to the senda_reload() call, then the kernel
213    * also would not have been able to deliver any messages, and so the old
214    * instance's table can still be used as is. Now the problem. Because case 1
215    * is not atomic, there is a small window during which other processes may
216    * attempt to receive a message, based on the fact that their s_asyn_pending
217    * mask in the kernel has a bit set for the process being updated. Failing
218    * to find a matching message in the yet-missing table of the new process,
219    * the kernel will unset the s_asyn_pending bit. Now, normally the bit would
220    * be set again through the new instance's senda_reload() call. However, if
221    * the new instance rolls back instead, the old instance will have a message
222    * for the other process, but its s_asyn_pending bit will not be set. Thus,
223    * the message will never be delivered unless we call senda_reload() here.
224    * XXX TODO: the story is even more complicated, because based on the above
225    * story, copying back the table should never be necessary and never happen.
226    * My logs show it does happen for at least RS, which may indicate RS sends
227    * asynchronous messages in its initialization code.. -dcvmoole
228    */
229   senda_reload();
230 }
231 
232 /*===========================================================================*
233  *                           sef_lu_state_change                	     *
234  *===========================================================================*/
235 static void sef_lu_state_change(int state, int flags)
236 {
237   int r, old_state;
238 
239   old_state = sef_lu_state;
240   sef_lu_state = state;
241   sef_lu_flags = flags;
242   if(sef_lu_state == SEF_LU_STATE_NULL) {
243       r = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
244       if(r != OK)
245           panic("%s:%d: SYS_STATE_CLEAR_IPC_FILTERS failed\n", __func__, __LINE__);
246   }
247   if(old_state != sef_lu_state) {
248       sef_lu_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
249   }
250 }
251 
252 /*===========================================================================*
253  *                         sef_lu_handle_state_data             	     *
254  *===========================================================================*/
255 int sef_lu_handle_state_data(endpoint_t src_e,
256     int state, cp_grant_id_t state_data_gid)
257 {
258     int r;
259     struct rs_state_data rs_state_data;
260 
261     if(state_data_gid == GRANT_INVALID) {
262         /* SEF_LU_STATE_EVAL requires an eval expression. */
263         return state == SEF_LU_STATE_EVAL ? EINVAL : OK;
264     }
265 
266     r = sys_safecopyfrom(src_e, state_data_gid, 0,
267         (vir_bytes) &rs_state_data, sizeof(rs_state_data));
268     if(r != OK) {
269         return r;
270     }
271     if(rs_state_data.size != sizeof(rs_state_data)) {
272         return E2BIG;
273     }
274     if(state == SEF_LU_STATE_EVAL) {
275         if(rs_state_data.eval_addr && rs_state_data.eval_len) {
276             if(rs_state_data.eval_len >= SEF_LU_STATE_EVAL_MAX_LEN) {
277                 return E2BIG;
278             }
279             r = sys_safecopyfrom(src_e, rs_state_data.eval_gid, 0,
280                 (vir_bytes) sef_lu_state_eval, rs_state_data.eval_len);
281             if(r != OK) {
282                 return r;
283             }
284             sef_lu_state_eval[rs_state_data.eval_len] = '\0';
285             r = sef_cb_lu_prepare_eval(SEF_LU_STATE_EVAL);
286             if(r != OK && r != ENOTREADY) {
287                 /* State expression could not be evaluated correctly. */
288                 return EINVAL;
289             }
290         }
291         else {
292             /* SEF_LU_STATE_EVAL requires a valid eval expression. */
293             return EINVAL;
294         }
295     }
296     if(rs_state_data.ipcf_els && rs_state_data.ipcf_els_size) {
297         ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS];
298         size_t ipc_filter_size = sizeof(ipc_filter);
299         int num_ipc_filters = rs_state_data.ipcf_els_size / ipc_filter_size;
300         int i;
301         if(rs_state_data.ipcf_els_size % ipc_filter_size) {
302             return E2BIG;
303         }
304         r = OK;
305         for(i=0;i<num_ipc_filters;i++) {
306             int num_elements=0;
307             r = sys_safecopyfrom(src_e, rs_state_data.ipcf_els_gid, i*ipc_filter_size,
308                 (vir_bytes) ipc_filter, ipc_filter_size);
309             if(r != OK) {
310                 break;
311             }
312 #if SEF_LU_DEBUG
313             sef_lu_debug_begin();
314             sef_lu_dprint("%s, Installing ipc filter:\n", sef_debug_header());
315 #endif
316             while(num_elements < IPCF_MAX_ELEMENTS && ipc_filter[num_elements].flags) {
317 #if SEF_LU_DEBUG
318                 sef_lu_dprint("el[%d]=(flags=%c%c%c%c, m_source=%d, m_type=%d)",
319                   num_elements,
320                   (ipc_filter[num_elements].flags & IPCF_MATCH_M_SOURCE) ? 'S' : '-',
321                   (ipc_filter[num_elements].flags & IPCF_MATCH_M_TYPE) ? 'T' : '-',
322                   (ipc_filter[num_elements].flags & IPCF_EL_BLACKLIST) ? 'B' : '-',
323                   (ipc_filter[num_elements].flags & IPCF_EL_WHITELIST) ? 'W' : '-',
324                   ipc_filter[num_elements].m_source, ipc_filter[num_elements].m_type);
325                 sef_lu_dprint("\n");
326 #endif
327                 num_elements++;
328             }
329 #if SEF_LU_DEBUG
330             sef_lu_debug_end();
331 #endif
332             if(num_elements == 0) {
333                 r = EINVAL;
334                 break;
335             }
336             r = sys_statectl(ipc_filter[0].flags & IPCF_EL_BLACKLIST ? SYS_STATE_ADD_IPC_BL_FILTER : SYS_STATE_ADD_IPC_WL_FILTER,
337                 ipc_filter, num_elements*sizeof(ipc_filter_el_t));
338             if(r != OK) {
339                 break;
340             }
341         }
342         if(r != OK) {
343             sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
344             return r;
345         }
346     }
347     return OK;
348 }
349 
350 /*===========================================================================*
351  *                            sef_setcb_lu_prepare                           *
352  *===========================================================================*/
353 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb)
354 {
355   assert(cb != NULL);
356   sef_lu_cbs.sef_cb_lu_prepare = cb;
357 }
358 
359 /*===========================================================================*
360  *                         sef_setcb_lu_state_isvalid                        *
361  *===========================================================================*/
362 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb)
363 {
364   assert(cb != NULL);
365   sef_lu_cbs.sef_cb_lu_state_isvalid = cb;
366 }
367 
368 /*===========================================================================*
369  *                         sef_setcb_lu_state_changed                        *
370  *===========================================================================*/
371 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb)
372 {
373   assert(cb != NULL);
374   sef_lu_cbs.sef_cb_lu_state_changed = cb;
375 }
376 
377 /*===========================================================================*
378  *                          sef_setcb_lu_state_dump                          *
379  *===========================================================================*/
380 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb)
381 {
382   assert(cb != NULL);
383   sef_lu_cbs.sef_cb_lu_state_dump = cb;
384 }
385 
386 /*===========================================================================*
387  *                          sef_setcb_lu_state_save                           *
388  *===========================================================================*/
389 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb)
390 {
391   assert(cb != NULL);
392   sef_lu_cbs.sef_cb_lu_state_save = cb;
393 }
394 
395 /*===========================================================================*
396  *                          sef_setcb_lu_response                            *
397  *===========================================================================*/
398 void sef_setcb_lu_response(sef_cb_lu_response_t cb)
399 {
400   assert(cb != NULL);
401   sef_lu_cbs.sef_cb_lu_response = cb;
402 }
403 
404 /*===========================================================================*
405  *      	            sef_cb_lu_prepare_null 	 	             *
406  *===========================================================================*/
407 int sef_cb_lu_prepare_null(int UNUSED(state))
408 {
409   return ENOTREADY;
410 }
411 
412 /*===========================================================================*
413  *      	         sef_cb_lu_state_isvalid_null		             *
414  *===========================================================================*/
415 int sef_cb_lu_state_isvalid_null(int UNUSED(state), int UNUSED(flags))
416 {
417   return FALSE;
418 }
419 
420 /*===========================================================================*
421  *                       sef_cb_lu_state_changed_null        		     *
422  *===========================================================================*/
423 void sef_cb_lu_state_changed_null(int UNUSED(old_state),
424    int UNUSED(state))
425 {
426 }
427 
428 /*===========================================================================*
429  *                       sef_cb_lu_state_dump_null        		     *
430  *===========================================================================*/
431 void sef_cb_lu_state_dump_null(int UNUSED(state))
432 {
433   sef_lu_dprint("NULL\n");
434 }
435 
436 /*===========================================================================*
437  *                       sef_cb_lu_state_save_null        		     *
438  *===========================================================================*/
439 int sef_cb_lu_state_save_null(int UNUSED(result), int UNUSED(flags))
440 {
441   return OK;
442 }
443 
444 /*===========================================================================*
445  *                       sef_cb_lu_response_null        		     *
446  *===========================================================================*/
447 int sef_cb_lu_response_null(message * UNUSED(m_ptr))
448 {
449   return ENOSYS;
450 }
451 
452 /*===========================================================================*
453  *      	       sef_cb_lu_prepare_always_ready	                     *
454  *===========================================================================*/
455 int sef_cb_lu_prepare_always_ready(int UNUSED(state))
456 {
457   return OK;
458 }
459 
460 /*===========================================================================*
461  *      	       sef_cb_lu_prepare_never_ready	                     *
462  *===========================================================================*/
463 int sef_cb_lu_prepare_never_ready(int UNUSED(state))
464 {
465 #if SEF_LU_DEBUG
466   sef_lu_debug_begin();
467   sef_lu_dprint("%s, cycle=%d. Simulating a service never ready to update...\n",
468       sef_debug_header(), sef_lu_debug_cycle);
469   sef_lu_debug_end();
470 #endif
471 
472   return ENOTREADY;
473 }
474 
475 /*===========================================================================*
476  *      	         sef_cb_lu_prepare_crash	                     *
477  *===========================================================================*/
478 int sef_cb_lu_prepare_crash(int UNUSED(state))
479 {
480   panic("Simulating a crash at update prepare time...\n");
481 
482   return OK;
483 }
484 
485 /*===========================================================================*
486  *      	         sef_cb_lu_prepare_eval 	                     *
487  *===========================================================================*/
488 int sef_cb_lu_prepare_eval(int UNUSED(state))
489 {
490   char result = 0;
491   int ret = sef_llvm_eval_bool(sef_lu_state_eval, &result);
492 
493 #if SEF_LU_DEBUG
494   sef_lu_debug_begin();
495   sef_lu_dprint("%s, cycle=%d. Evaluated state expression '%s' with error code %d and result %d\n",
496       sef_debug_header(), sef_lu_debug_cycle, sef_lu_state_eval, ret, result);
497   sef_lu_debug_end();
498 #endif
499 
500   if(ret < 0) {
501       return ret == ENOTREADY ? EINTR : ret;
502   }
503   return result ? OK : ENOTREADY;
504 }
505 
506 /*===========================================================================*
507  *      	      sef_cb_lu_state_isvalid_standard                       *
508  *===========================================================================*/
509 int sef_cb_lu_state_isvalid_standard(int state, int UNUSED(flags))
510 {
511   return SEF_LU_STATE_IS_STANDARD(state);
512 }
513 
514 /*===========================================================================*
515  *      	      sef_cb_lu_state_isvalid_workfree                       *
516  *===========================================================================*/
517 int sef_cb_lu_state_isvalid_workfree(int state, int UNUSED(flags))
518 {
519   return (state == SEF_LU_STATE_WORK_FREE);
520 }
521 
522 /*===========================================================================*
523  *      	    sef_cb_lu_state_isvalid_workfree_self                    *
524  *===========================================================================*/
525 int sef_cb_lu_state_isvalid_workfree_self(int state, int flags)
526 {
527   return (state == SEF_LU_STATE_WORK_FREE) && (flags & (SEF_LU_SELF|SEF_LU_ASR));
528 }
529 
530 /*===========================================================================*
531  *      	       sef_cb_lu_state_isvalid_generic                       *
532  *===========================================================================*/
533 int sef_cb_lu_state_isvalid_generic(int state, int flags)
534 {
535   return (state == SEF_LU_STATE_EVAL) || sef_cb_lu_state_isvalid_workfree(state, flags);
536 }
537 
538 /*===========================================================================*
539  *                       sef_cb_lu_state_dump_eval        		     *
540  *===========================================================================*/
541 void sef_cb_lu_state_dump_eval(int state)
542 {
543   if(state == SEF_LU_STATE_EVAL) {
544       sef_llvm_dump_eval(sef_lu_state_eval);
545   }
546   else {
547       return sef_cb_lu_state_dump_null(state);
548   }
549 }
550 
551 /*===========================================================================*
552  *                       sef_cb_lu_response_rs_reply        		     *
553  *===========================================================================*/
554 int sef_cb_lu_response_rs_reply(message *m_ptr)
555 {
556   int r;
557 
558   /* Inform RS that we're ready with the given result. */
559   r = ipc_sendrec(RS_PROC_NR, m_ptr);
560   if ( r != OK) {
561       return r;
562   }
563 
564   return m_ptr->m_type == RS_LU_PREPARE ? EINTR : m_ptr->m_type;
565 }
566 
567