3 #include <minix/sysutil.h>
6 /* SEF Live update variables. */
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
;
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
;
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
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
);
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
);
40 EXTERN
char* sef_debug_header(void);
41 static int sef_lu_debug_cycle
= 0;
43 /* Information about SELF. */
44 EXTERN endpoint_t sef_self_endpoint
;
46 /*===========================================================================*
47 * do_sef_lu_before_receive *
48 *===========================================================================*/
49 void do_sef_lu_before_receive(void)
51 /* Handle SEF Live update before receive events. */
54 assert(sef_lu_state
!= SEF_LU_STATE_NULL
);
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
);
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.
70 switch(sef_lu_state
) {
71 case SEF_LU_STATE_WORK_FREE
:
74 case SEF_LU_STATE_UNREACHABLE
:
75 r
= sef_cb_lu_prepare_never_ready(sef_lu_state
);
77 case SEF_LU_STATE_PREPARE_CRASH
:
78 r
= sef_cb_lu_prepare_crash(sef_lu_state
);
80 case SEF_LU_STATE_EVAL
:
81 r
= sef_cb_lu_prepare_eval(sef_lu_state
);
84 r
= sef_lu_cbs
.sef_cb_lu_prepare(sef_lu_state
);
87 if(r
== OK
|| r
!= ENOTREADY
) {
92 /*===========================================================================*
94 *===========================================================================*/
95 int do_sef_lu_request(message
*m_ptr
)
97 /* Handle a SEF Live update request. */
98 int r
, state
, flags
, is_valid_state
;
99 cp_grant_id_t rs_state_data_gid
;
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
;
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);
112 /* Check if we are already busy. */
113 if(sef_lu_state
!= SEF_LU_STATE_NULL
) {
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
);
126 sef_lu_ready(EINVAL
);
131 /* Handle additional state data (if any). */
132 r
= sef_lu_handle_state_data(m_ptr
->m_source
, state
, rs_state_data_gid
);
138 /* Set the new live update state. */
139 sef_lu_state_change(state
, flags
);
142 /* Return OK not to let anybody else intercept the request. */
146 /*===========================================================================*
148 *===========================================================================*/
149 static void sef_lu_ready(int result
)
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)" : ""));
162 /* If result is OK, let the callback code cleanup and save
163 * any state that must be carried over to the new version.
166 r
= sef_llvm_state_cleanup();
168 r
= sef_lu_cbs
.sef_cb_lu_state_save(sef_lu_state
, sef_lu_flags
);
171 /* Abort update in case of error. */
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.
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
);
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. */
195 /* Something went wrong. Update was aborted and we didn't get updated.
196 * Restore things back to normal and continue executing.
198 sef_lu_state_change(SEF_LU_STATE_NULL
, 0);
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
232 /*===========================================================================*
233 * sef_lu_state_change *
234 *===========================================================================*/
235 static void sef_lu_state_change(int state
, int flags
)
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);
245 panic("%s:%d: SYS_STATE_CLEAR_IPC_FILTERS failed\n", __func__
, __LINE__
);
247 if(old_state
!= sef_lu_state
) {
248 sef_lu_cbs
.sef_cb_lu_state_changed(old_state
, sef_lu_state
);
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
)
259 struct rs_state_data rs_state_data
;
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
;
266 r
= sys_safecopyfrom(src_e
, state_data_gid
, 0,
267 (vir_bytes
) &rs_state_data
, sizeof(rs_state_data
));
271 if(rs_state_data
.size
!= sizeof(rs_state_data
)) {
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
) {
279 r
= sys_safecopyfrom(src_e
, rs_state_data
.eval_gid
, 0,
280 (vir_bytes
) sef_lu_state_eval
, rs_state_data
.eval_len
);
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. */
292 /* SEF_LU_STATE_EVAL requires a valid eval expression. */
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
;
301 if(rs_state_data
.ipcf_els_size
% ipc_filter_size
) {
305 for(i
=0;i
<num_ipc_filters
;i
++) {
307 r
= sys_safecopyfrom(src_e
, rs_state_data
.ipcf_els_gid
, i
*ipc_filter_size
,
308 (vir_bytes
) ipc_filter
, ipc_filter_size
);
313 sef_lu_debug_begin();
314 sef_lu_dprint("%s, Installing ipc filter:\n", sef_debug_header());
316 while(num_elements
< IPCF_MAX_ELEMENTS
&& ipc_filter
[num_elements
].flags
) {
318 sef_lu_dprint("el[%d]=(flags=%c%c%c%c, m_source=%d, m_type=%d)",
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
);
332 if(num_elements
== 0) {
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
));
343 sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS
, 0, 0);
350 /*===========================================================================*
351 * sef_setcb_lu_prepare *
352 *===========================================================================*/
353 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb
)
356 sef_lu_cbs
.sef_cb_lu_prepare
= cb
;
359 /*===========================================================================*
360 * sef_setcb_lu_state_isvalid *
361 *===========================================================================*/
362 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb
)
365 sef_lu_cbs
.sef_cb_lu_state_isvalid
= cb
;
368 /*===========================================================================*
369 * sef_setcb_lu_state_changed *
370 *===========================================================================*/
371 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb
)
374 sef_lu_cbs
.sef_cb_lu_state_changed
= cb
;
377 /*===========================================================================*
378 * sef_setcb_lu_state_dump *
379 *===========================================================================*/
380 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb
)
383 sef_lu_cbs
.sef_cb_lu_state_dump
= cb
;
386 /*===========================================================================*
387 * sef_setcb_lu_state_save *
388 *===========================================================================*/
389 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb
)
392 sef_lu_cbs
.sef_cb_lu_state_save
= cb
;
395 /*===========================================================================*
396 * sef_setcb_lu_response *
397 *===========================================================================*/
398 void sef_setcb_lu_response(sef_cb_lu_response_t cb
)
401 sef_lu_cbs
.sef_cb_lu_response
= cb
;
404 /*===========================================================================*
405 * sef_cb_lu_prepare_null *
406 *===========================================================================*/
407 int sef_cb_lu_prepare_null(int UNUSED(state
))
412 /*===========================================================================*
413 * sef_cb_lu_state_isvalid_null *
414 *===========================================================================*/
415 int sef_cb_lu_state_isvalid_null(int UNUSED(state
), int UNUSED(flags
))
420 /*===========================================================================*
421 * sef_cb_lu_state_changed_null *
422 *===========================================================================*/
423 void sef_cb_lu_state_changed_null(int UNUSED(old_state
),
428 /*===========================================================================*
429 * sef_cb_lu_state_dump_null *
430 *===========================================================================*/
431 void sef_cb_lu_state_dump_null(int UNUSED(state
))
433 sef_lu_dprint("NULL\n");
436 /*===========================================================================*
437 * sef_cb_lu_state_save_null *
438 *===========================================================================*/
439 int sef_cb_lu_state_save_null(int UNUSED(result
), int UNUSED(flags
))
444 /*===========================================================================*
445 * sef_cb_lu_response_null *
446 *===========================================================================*/
447 int sef_cb_lu_response_null(message
* UNUSED(m_ptr
))
452 /*===========================================================================*
453 * sef_cb_lu_prepare_always_ready *
454 *===========================================================================*/
455 int sef_cb_lu_prepare_always_ready(int UNUSED(state
))
460 /*===========================================================================*
461 * sef_cb_lu_prepare_never_ready *
462 *===========================================================================*/
463 int sef_cb_lu_prepare_never_ready(int UNUSED(state
))
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
);
475 /*===========================================================================*
476 * sef_cb_lu_prepare_crash *
477 *===========================================================================*/
478 int sef_cb_lu_prepare_crash(int UNUSED(state
))
480 panic("Simulating a crash at update prepare time...\n");
485 /*===========================================================================*
486 * sef_cb_lu_prepare_eval *
487 *===========================================================================*/
488 int sef_cb_lu_prepare_eval(int UNUSED(state
))
491 int ret
= sef_llvm_eval_bool(sef_lu_state_eval
, &result
);
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
);
501 return ret
== ENOTREADY
? EINTR
: ret
;
503 return result
? OK
: ENOTREADY
;
506 /*===========================================================================*
507 * sef_cb_lu_state_isvalid_standard *
508 *===========================================================================*/
509 int sef_cb_lu_state_isvalid_standard(int state
, int UNUSED(flags
))
511 return SEF_LU_STATE_IS_STANDARD(state
);
514 /*===========================================================================*
515 * sef_cb_lu_state_isvalid_workfree *
516 *===========================================================================*/
517 int sef_cb_lu_state_isvalid_workfree(int state
, int UNUSED(flags
))
519 return (state
== SEF_LU_STATE_WORK_FREE
);
522 /*===========================================================================*
523 * sef_cb_lu_state_isvalid_workfree_self *
524 *===========================================================================*/
525 int sef_cb_lu_state_isvalid_workfree_self(int state
, int flags
)
527 return (state
== SEF_LU_STATE_WORK_FREE
) && (flags
& (SEF_LU_SELF
|SEF_LU_ASR
));
530 /*===========================================================================*
531 * sef_cb_lu_state_isvalid_generic *
532 *===========================================================================*/
533 int sef_cb_lu_state_isvalid_generic(int state
, int flags
)
535 return (state
== SEF_LU_STATE_EVAL
) || sef_cb_lu_state_isvalid_workfree(state
, flags
);
538 /*===========================================================================*
539 * sef_cb_lu_state_dump_eval *
540 *===========================================================================*/
541 void sef_cb_lu_state_dump_eval(int state
)
543 if(state
== SEF_LU_STATE_EVAL
) {
544 sef_llvm_dump_eval(sef_lu_state_eval
);
547 return sef_cb_lu_state_dump_null(state
);
551 /*===========================================================================*
552 * sef_cb_lu_response_rs_reply *
553 *===========================================================================*/
554 int sef_cb_lu_response_rs_reply(message
*m_ptr
)
558 /* Inform RS that we're ready with the given result. */
559 r
= ipc_sendrec(RS_PROC_NR
, m_ptr
);
564 return m_ptr
->m_type
== RS_LU_PREPARE
? EINTR
: m_ptr
->m_type
;