xref: /minix/minix/lib/libsys/sef_liveupdate.c (revision 0a6a1f1d)
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       assert(r == OK);
245   }
246   if(old_state != sef_lu_state) {
247       sef_lu_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
248   }
249 }
250 
251 /*===========================================================================*
252  *                         sef_lu_handle_state_data             	     *
253  *===========================================================================*/
254 int sef_lu_handle_state_data(endpoint_t src_e,
255     int state, cp_grant_id_t state_data_gid)
256 {
257     int r;
258     struct rs_state_data rs_state_data;
259 
260     if(state_data_gid == GRANT_INVALID) {
261         /* SEF_LU_STATE_EVAL requires an eval expression. */
262         return state == SEF_LU_STATE_EVAL ? EINVAL : OK;
263     }
264 
265     r = sys_safecopyfrom(src_e, state_data_gid, 0,
266         (vir_bytes) &rs_state_data, sizeof(rs_state_data));
267     if(r != OK) {
268         return r;
269     }
270     if(rs_state_data.size != sizeof(rs_state_data)) {
271         return E2BIG;
272     }
273     if(state == SEF_LU_STATE_EVAL) {
274         if(rs_state_data.eval_addr && rs_state_data.eval_len) {
275             if(rs_state_data.eval_len >= SEF_LU_STATE_EVAL_MAX_LEN) {
276                 return E2BIG;
277             }
278             r = sys_safecopyfrom(src_e, rs_state_data.eval_gid, 0,
279                 (vir_bytes) sef_lu_state_eval, rs_state_data.eval_len);
280             if(r != OK) {
281                 return r;
282             }
283             sef_lu_state_eval[rs_state_data.eval_len] = '\0';
284             r = sef_cb_lu_prepare_eval(SEF_LU_STATE_EVAL);
285             if(r != OK && r != ENOTREADY) {
286                 /* State expression could not be evaluated correctly. */
287                 return EINVAL;
288             }
289         }
290         else {
291             /* SEF_LU_STATE_EVAL requires a valid eval expression. */
292             return EINVAL;
293         }
294     }
295     if(rs_state_data.ipcf_els && rs_state_data.ipcf_els_size) {
296         ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS];
297         size_t ipc_filter_size = sizeof(ipc_filter);
298         int num_ipc_filters = rs_state_data.ipcf_els_size / ipc_filter_size;
299         int i;
300         if(rs_state_data.ipcf_els_size % ipc_filter_size) {
301             return E2BIG;
302         }
303         r = OK;
304         for(i=0;i<num_ipc_filters;i++) {
305             int num_elements=0;
306             r = sys_safecopyfrom(src_e, rs_state_data.ipcf_els_gid, i*ipc_filter_size,
307                 (vir_bytes) ipc_filter, ipc_filter_size);
308             if(r != OK) {
309                 break;
310             }
311 #if SEF_LU_DEBUG
312             sef_lu_debug_begin();
313             sef_lu_dprint("%s, Installing ipc filter:\n", sef_debug_header());
314 #endif
315             while(num_elements < IPCF_MAX_ELEMENTS && ipc_filter[num_elements].flags) {
316 #if SEF_LU_DEBUG
317                 sef_lu_dprint("el[%d]=(flags=%c%c%c%c, m_source=%d, m_type=%d)",
318                   num_elements,
319                   (ipc_filter[num_elements].flags & IPCF_MATCH_M_SOURCE) ? 'S' : '-',
320                   (ipc_filter[num_elements].flags & IPCF_MATCH_M_TYPE) ? 'T' : '-',
321                   (ipc_filter[num_elements].flags & IPCF_EL_BLACKLIST) ? 'B' : '-',
322                   (ipc_filter[num_elements].flags & IPCF_EL_WHITELIST) ? 'W' : '-',
323                   ipc_filter[num_elements].m_source, ipc_filter[num_elements].m_type);
324                 sef_lu_dprint("\n");
325 #endif
326                 num_elements++;
327             }
328 #if SEF_LU_DEBUG
329             sef_lu_debug_end();
330 #endif
331             if(num_elements == 0) {
332                 r = EINVAL;
333                 break;
334             }
335             r = sys_statectl(ipc_filter[0].flags & IPCF_EL_BLACKLIST ? SYS_STATE_ADD_IPC_BL_FILTER : SYS_STATE_ADD_IPC_WL_FILTER,
336                 ipc_filter, num_elements*sizeof(ipc_filter_el_t));
337             if(r != OK) {
338                 break;
339             }
340         }
341         if(r != OK) {
342             sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
343             return r;
344         }
345     }
346     return OK;
347 }
348 
349 /*===========================================================================*
350  *                            sef_setcb_lu_prepare                           *
351  *===========================================================================*/
352 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb)
353 {
354   assert(cb != NULL);
355   sef_lu_cbs.sef_cb_lu_prepare = cb;
356 }
357 
358 /*===========================================================================*
359  *                         sef_setcb_lu_state_isvalid                        *
360  *===========================================================================*/
361 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb)
362 {
363   assert(cb != NULL);
364   sef_lu_cbs.sef_cb_lu_state_isvalid = cb;
365 }
366 
367 /*===========================================================================*
368  *                         sef_setcb_lu_state_changed                        *
369  *===========================================================================*/
370 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb)
371 {
372   assert(cb != NULL);
373   sef_lu_cbs.sef_cb_lu_state_changed = cb;
374 }
375 
376 /*===========================================================================*
377  *                          sef_setcb_lu_state_dump                          *
378  *===========================================================================*/
379 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb)
380 {
381   assert(cb != NULL);
382   sef_lu_cbs.sef_cb_lu_state_dump = cb;
383 }
384 
385 /*===========================================================================*
386  *                          sef_setcb_lu_state_save                           *
387  *===========================================================================*/
388 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb)
389 {
390   assert(cb != NULL);
391   sef_lu_cbs.sef_cb_lu_state_save = cb;
392 }
393 
394 /*===========================================================================*
395  *                          sef_setcb_lu_response                            *
396  *===========================================================================*/
397 void sef_setcb_lu_response(sef_cb_lu_response_t cb)
398 {
399   assert(cb != NULL);
400   sef_lu_cbs.sef_cb_lu_response = cb;
401 }
402 
403 /*===========================================================================*
404  *      	            sef_cb_lu_prepare_null 	 	             *
405  *===========================================================================*/
406 int sef_cb_lu_prepare_null(int UNUSED(state))
407 {
408   return ENOTREADY;
409 }
410 
411 /*===========================================================================*
412  *      	         sef_cb_lu_state_isvalid_null		             *
413  *===========================================================================*/
414 int sef_cb_lu_state_isvalid_null(int UNUSED(state), int UNUSED(flags))
415 {
416   return FALSE;
417 }
418 
419 /*===========================================================================*
420  *                       sef_cb_lu_state_changed_null        		     *
421  *===========================================================================*/
422 void sef_cb_lu_state_changed_null(int UNUSED(old_state),
423    int UNUSED(state))
424 {
425 }
426 
427 /*===========================================================================*
428  *                       sef_cb_lu_state_dump_null        		     *
429  *===========================================================================*/
430 void sef_cb_lu_state_dump_null(int UNUSED(state))
431 {
432   sef_lu_dprint("NULL\n");
433 }
434 
435 /*===========================================================================*
436  *                       sef_cb_lu_state_save_null        		     *
437  *===========================================================================*/
438 int sef_cb_lu_state_save_null(int UNUSED(result), int UNUSED(flags))
439 {
440   return OK;
441 }
442 
443 /*===========================================================================*
444  *                       sef_cb_lu_response_null        		     *
445  *===========================================================================*/
446 int sef_cb_lu_response_null(message * UNUSED(m_ptr))
447 {
448   return ENOSYS;
449 }
450 
451 /*===========================================================================*
452  *      	       sef_cb_lu_prepare_always_ready	                     *
453  *===========================================================================*/
454 int sef_cb_lu_prepare_always_ready(int UNUSED(state))
455 {
456   return OK;
457 }
458 
459 /*===========================================================================*
460  *      	       sef_cb_lu_prepare_never_ready	                     *
461  *===========================================================================*/
462 int sef_cb_lu_prepare_never_ready(int UNUSED(state))
463 {
464 #if SEF_LU_DEBUG
465   sef_lu_debug_begin();
466   sef_lu_dprint("%s, cycle=%d. Simulating a service never ready to update...\n",
467       sef_debug_header(), sef_lu_debug_cycle);
468   sef_lu_debug_end();
469 #endif
470 
471   return ENOTREADY;
472 }
473 
474 /*===========================================================================*
475  *      	         sef_cb_lu_prepare_crash	                     *
476  *===========================================================================*/
477 int sef_cb_lu_prepare_crash(int UNUSED(state))
478 {
479   panic("Simulating a crash at update prepare time...\n");
480 
481   return OK;
482 }
483 
484 /*===========================================================================*
485  *      	         sef_cb_lu_prepare_eval 	                     *
486  *===========================================================================*/
487 int sef_cb_lu_prepare_eval(int UNUSED(state))
488 {
489   char result = 0;
490   int ret = sef_llvm_eval_bool(sef_lu_state_eval, &result);
491 
492 #if SEF_LU_DEBUG
493   sef_lu_debug_begin();
494   sef_lu_dprint("%s, cycle=%d. Evaluated state expression '%s' with error code %d and result %d\n",
495       sef_debug_header(), sef_lu_debug_cycle, sef_lu_state_eval, ret, result);
496   sef_lu_debug_end();
497 #endif
498 
499   if(ret < 0) {
500       return ret == ENOTREADY ? EINTR : ret;
501   }
502   return result ? OK : ENOTREADY;
503 }
504 
505 /*===========================================================================*
506  *      	      sef_cb_lu_state_isvalid_standard                       *
507  *===========================================================================*/
508 int sef_cb_lu_state_isvalid_standard(int state, int UNUSED(flags))
509 {
510   return SEF_LU_STATE_IS_STANDARD(state);
511 }
512 
513 /*===========================================================================*
514  *      	      sef_cb_lu_state_isvalid_workfree                       *
515  *===========================================================================*/
516 int sef_cb_lu_state_isvalid_workfree(int state, int UNUSED(flags))
517 {
518   return (state == SEF_LU_STATE_WORK_FREE);
519 }
520 
521 /*===========================================================================*
522  *      	    sef_cb_lu_state_isvalid_workfree_self                    *
523  *===========================================================================*/
524 int sef_cb_lu_state_isvalid_workfree_self(int state, int flags)
525 {
526   return (state == SEF_LU_STATE_WORK_FREE) && (flags & (SEF_LU_SELF|SEF_LU_ASR));
527 }
528 
529 /*===========================================================================*
530  *      	       sef_cb_lu_state_isvalid_generic                       *
531  *===========================================================================*/
532 int sef_cb_lu_state_isvalid_generic(int state, int flags)
533 {
534   return (state == SEF_LU_STATE_EVAL) || sef_cb_lu_state_isvalid_workfree(state, flags);
535 }
536 
537 /*===========================================================================*
538  *                       sef_cb_lu_state_dump_eval        		     *
539  *===========================================================================*/
540 void sef_cb_lu_state_dump_eval(int state)
541 {
542   if(state == SEF_LU_STATE_EVAL) {
543       sef_llvm_dump_eval(sef_lu_state_eval);
544   }
545   else {
546       return sef_cb_lu_state_dump_null(state);
547   }
548 }
549 
550 /*===========================================================================*
551  *                       sef_cb_lu_response_rs_reply        		     *
552  *===========================================================================*/
553 int sef_cb_lu_response_rs_reply(message *m_ptr)
554 {
555   int r;
556 
557   /* Inform RS that we're ready with the given result. */
558   r = ipc_sendrec(RS_PROC_NR, m_ptr);
559   if ( r != OK) {
560       return r;
561   }
562 
563   return m_ptr->m_type == RS_LU_PREPARE ? EINTR : m_ptr->m_type;
564 }
565 
566