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