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