1 2 #include "inc.h" 3 4 /*===========================================================================* 5 * rupdate_clear_upds * 6 *===========================================================================*/ 7 void rupdate_clear_upds() 8 { 9 /* Clear the update chain and the global update descriptor. */ 10 struct rprocupd *prev_rpupd, *rpupd; 11 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 12 if(prev_rpupd) { 13 rupdate_upd_clear(prev_rpupd); 14 } 15 ); 16 rupdate_upd_clear(rupdate.last_rpupd); 17 RUPDATE_CLEAR(); 18 } 19 20 /*===========================================================================* 21 * rupdate_add_upd * 22 *===========================================================================*/ 23 void rupdate_add_upd(struct rprocupd* rpupd) 24 { 25 /* Add an update descriptor to the update chain. */ 26 struct rprocupd* prev_rpupd; 27 int lu_flags; 28 29 rpupd->prev_rpupd = rupdate.last_rpupd; 30 if(rupdate.num_rpupds == 0) { 31 rupdate.first_rpupd = rpupd; 32 rupdate.curr_rpupd = rpupd; 33 } 34 else { 35 rupdate.last_rpupd->next_rpupd = rpupd; 36 } 37 rupdate.last_rpupd = rpupd; 38 rupdate.num_rpupds++; 39 40 /* Propagate relevant flags from the new descriptor. */ 41 lu_flags = rpupd->lu_flags & (SEF_LU_INCLUDES_VM|SEF_LU_INCLUDES_RS|SEF_LU_UNSAFE|SEF_LU_MULTI); 42 if(lu_flags) { 43 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 44 rpupd->lu_flags |= lu_flags; 45 rpupd->init_flags |= lu_flags; 46 ); 47 } 48 49 /* Set VM/RS update descriptor pointers. */ 50 if(!rupdate.vm_rpupd && (lu_flags & SEF_LU_INCLUDES_VM)) { 51 rupdate.vm_rpupd = rupdate.last_rpupd; 52 } 53 else if(!rupdate.rs_rpupd && (lu_flags & SEF_LU_INCLUDES_RS)) { 54 rupdate.rs_rpupd = rupdate.last_rpupd; 55 } 56 } 57 58 /*===========================================================================* 59 * rupdate_set_new_upd_flags * 60 *===========================================================================*/ 61 void rupdate_set_new_upd_flags(struct rprocupd* rpupd) 62 { 63 /* Set multi-component update flags. */ 64 if(rupdate.num_rpupds > 0) { 65 rpupd->lu_flags |= SEF_LU_MULTI; 66 rpupd->init_flags |= SEF_LU_MULTI; 67 } 68 69 /* Propagate relevant flags from last service under update (if any). */ 70 if(rupdate.last_rpupd) { 71 int lu_flags = rupdate.last_rpupd->lu_flags & (SEF_LU_INCLUDES_VM|SEF_LU_INCLUDES_RS|SEF_LU_UNSAFE); 72 rpupd->lu_flags |= lu_flags; 73 rpupd->init_flags |= lu_flags; 74 } 75 76 if(UPD_IS_PREPARING_ONLY(rpupd)) { 77 return; 78 } 79 80 /* Set VM/RS update flags. */ 81 if(rpupd->rp->r_pub->endpoint == VM_PROC_NR) { 82 rpupd->lu_flags |= SEF_LU_INCLUDES_VM; 83 rpupd->init_flags |= SEF_LU_INCLUDES_VM; 84 } 85 else if(rpupd->rp->r_pub->endpoint == RS_PROC_NR) { 86 rpupd->lu_flags |= SEF_LU_INCLUDES_RS; 87 rpupd->init_flags |= SEF_LU_INCLUDES_RS; 88 } 89 } 90 91 /*===========================================================================* 92 * rupdate_upd_init * 93 *===========================================================================*/ 94 void rupdate_upd_init(struct rprocupd* rpupd, struct rproc *rp) 95 { 96 /* Initialize an update descriptor for a given service. */ 97 memset(rpupd, 0, sizeof(*(rpupd))); 98 rpupd->prepare_state_data_gid = GRANT_INVALID; 99 rpupd->prepare_state_data.ipcf_els_gid = GRANT_INVALID; 100 rpupd->prepare_state_data.eval_gid = GRANT_INVALID; 101 rpupd->state_endpoint = NONE; 102 rpupd->rp = rp; 103 } 104 105 /*===========================================================================* 106 * rupdate_upd_clear * 107 *===========================================================================*/ 108 void rupdate_upd_clear(struct rprocupd* rpupd) 109 { 110 /* Clear an update descriptor. */ 111 if(rpupd->rp->r_new_rp) { 112 cleanup_service(rpupd->rp->r_new_rp); 113 } 114 if(rpupd->prepare_state_data_gid != GRANT_INVALID) { 115 cpf_revoke(rpupd->prepare_state_data_gid); 116 } 117 if(rpupd->prepare_state_data.size > 0) { 118 if(rpupd->prepare_state_data.ipcf_els_gid != GRANT_INVALID) { 119 cpf_revoke(rpupd->prepare_state_data.ipcf_els_gid); 120 } 121 if(rpupd->prepare_state_data.eval_gid != GRANT_INVALID) { 122 cpf_revoke(rpupd->prepare_state_data.eval_gid); 123 } 124 if(rpupd->prepare_state_data.ipcf_els) { 125 free(rpupd->prepare_state_data.ipcf_els); 126 } 127 if(rpupd->prepare_state_data.eval_addr) { 128 free(rpupd->prepare_state_data.eval_addr); 129 } 130 } 131 rupdate_upd_init(rpupd,NULL); 132 } 133 134 /*===========================================================================* 135 * rupdate_upd_move * 136 *===========================================================================*/ 137 void rupdate_upd_move(struct rproc* src_rp, struct rproc* dst_rp) 138 { 139 /* Move an update descriptor from one service instance to another. */ 140 dst_rp->r_upd = src_rp->r_upd; 141 dst_rp->r_upd.rp = dst_rp; 142 if(src_rp->r_new_rp) { 143 assert(!dst_rp->r_new_rp); 144 dst_rp->r_new_rp = src_rp->r_new_rp; 145 dst_rp->r_new_rp->r_old_rp = dst_rp; 146 } 147 if(dst_rp->r_upd.prev_rpupd) dst_rp->r_upd.prev_rpupd->next_rpupd = &dst_rp->r_upd; 148 if(dst_rp->r_upd.next_rpupd) dst_rp->r_upd.next_rpupd->prev_rpupd = &dst_rp->r_upd; 149 if(rupdate.first_rpupd == &src_rp->r_upd) rupdate.first_rpupd = &dst_rp->r_upd; 150 if(rupdate.last_rpupd == &src_rp->r_upd) rupdate.last_rpupd = &dst_rp->r_upd; 151 rupdate_upd_init(&src_rp->r_upd, NULL); 152 src_rp->r_new_rp = NULL; 153 } 154 155 /*===========================================================================* 156 * request_prepare_update_service_debug * 157 *===========================================================================*/ 158 void request_prepare_update_service_debug(char *file, int line, 159 struct rproc *rp, int state) 160 { 161 /* Request a service to prepare/cancel the update. */ 162 message m; 163 struct rprocpub *rpub; 164 int no_reply; 165 166 rpub = rp->r_pub; 167 168 if(state != SEF_LU_STATE_NULL) { 169 struct rprocupd *rpupd = &rp->r_upd; 170 getticks(&rpupd->prepare_tm); 171 if(!UPD_IS_PREPARING_ONLY(rpupd)) { 172 assert(rp->r_new_rp); 173 rp->r_flags |= RS_UPDATING; 174 rp->r_new_rp->r_flags |= RS_UPDATING; 175 } 176 else { 177 assert(!rp->r_new_rp); 178 } 179 180 m.m_rs_update.flags = rpupd->lu_flags; 181 m.m_rs_update.state_data_gid = rpupd->prepare_state_data_gid; 182 183 if(rs_verbose) 184 printf("RS: %s being requested to prepare for the %s at %s:%d\n", 185 srv_to_string(rp), srv_upd_to_string(rpupd), file, line); 186 } 187 else { 188 if(rs_verbose) 189 printf("RS: %s being requested to cancel the update at %s:%d\n", 190 srv_to_string(rp), file, line); 191 } 192 193 /* Request to prepare for the update or cancel the update. */ 194 m.m_type = RS_LU_PREPARE; 195 m.m_rs_update.state = state; 196 no_reply = !(rp->r_flags & RS_PREPARE_DONE); 197 rs_asynsend(rp, &m, no_reply); 198 } 199 200 /*===========================================================================* 201 * srv_update * 202 *===========================================================================*/ 203 int srv_update(endpoint_t src_e, endpoint_t dst_e, int sys_upd_flags) 204 { 205 int r = OK; 206 207 /* Ask VM to swap the slots of the two processes and tell the kernel to 208 * do the same. If VM is being updated, only perform the kernel 209 * part of the call. The new instance of VM will do the rest at 210 * initialization time. If a multi-component update includes VM, let VM 211 * handle updates at state transfer time and rollbacks afterwards. 212 */ 213 if(src_e == VM_PROC_NR) { 214 if(rs_verbose) 215 printf("RS: executing sys_update(%d, %d)\n", src_e, dst_e); 216 r = sys_update(src_e, dst_e, 217 sys_upd_flags & SF_VM_ROLLBACK ? SYS_UPD_ROLLBACK : 0); 218 } 219 else if(!RUPDATE_IS_UPD_VM_MULTI() || RUPDATE_IS_VM_INIT_DONE()) { 220 if(rs_verbose) 221 printf("RS: executing vm_update(%d, %d)\n", src_e, dst_e); 222 r = vm_update(src_e, dst_e, sys_upd_flags); 223 } 224 else { 225 if(rs_verbose) 226 printf("RS: skipping srv_update(%d, %d)\n", src_e, dst_e); 227 } 228 229 return r; 230 } 231 232 /*===========================================================================* 233 * update_service * 234 *===========================================================================*/ 235 int update_service(src_rpp, dst_rpp, swap_flag, sys_upd_flags) 236 struct rproc **src_rpp; 237 struct rproc **dst_rpp; 238 int swap_flag; 239 int sys_upd_flags; 240 { 241 /* Update an existing service. */ 242 int r; 243 struct rproc *src_rp; 244 struct rproc *dst_rp; 245 struct rprocpub *src_rpub; 246 struct rprocpub *dst_rpub; 247 int pid; 248 endpoint_t endpoint; 249 250 src_rp = *src_rpp; 251 dst_rp = *dst_rpp; 252 src_rpub = src_rp->r_pub; 253 dst_rpub = dst_rp->r_pub; 254 255 if(rs_verbose) 256 printf("RS: %s updating into %s\n", 257 srv_to_string(src_rp), srv_to_string(dst_rp)); 258 259 /* Swap the slots of the two processes when asked to. */ 260 if(swap_flag == RS_SWAP) { 261 if((r = srv_update(src_rpub->endpoint, dst_rpub->endpoint, sys_upd_flags)) != OK) { 262 return r; 263 } 264 } 265 266 /* Swap slots here as well. */ 267 pid = src_rp->r_pid; 268 endpoint = src_rpub->endpoint; 269 270 swap_slot(&src_rp, &dst_rp); 271 272 /* Reassign pids and endpoints. */ 273 src_rp->r_pid = dst_rp->r_pid; 274 src_rp->r_pub->endpoint = dst_rp->r_pub->endpoint; 275 rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)] = src_rp; 276 dst_rp->r_pid = pid; 277 dst_rp->r_pub->endpoint = endpoint; 278 rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)] = dst_rp; 279 280 /* Update in-RS priv structs */ 281 if ((r = sys_getpriv(&src_rp->r_priv, src_rp->r_pub->endpoint)) != OK) 282 panic("RS: update: could not update RS copies of priv of src: %d\n", r); 283 if ((r = sys_getpriv(&dst_rp->r_priv, dst_rp->r_pub->endpoint)) != OK) 284 panic("RS: update: could not update RS copies of priv of dst: %d\n", r); 285 286 /* Adjust input pointers. */ 287 *src_rpp = src_rp; 288 *dst_rpp = dst_rp; 289 290 /* Make the new version active. */ 291 activate_service(dst_rp, src_rp); 292 293 if(rs_verbose) 294 printf("RS: %s updated into %s\n", 295 srv_to_string(src_rp), srv_to_string(dst_rp)); 296 297 return OK; 298 } 299 300 /*===========================================================================* 301 * rollback_service * 302 *===========================================================================*/ 303 void rollback_service(struct rproc **new_rpp, struct rproc **old_rpp) 304 { 305 /* Rollback an updated service. */ 306 struct rproc *rp; 307 int r = OK; 308 309 /* RS is special, we may only need to swap the slots to rollback. */ 310 if((*old_rpp)->r_pub->endpoint == RS_PROC_NR) { 311 endpoint_t me = NONE; 312 char name[20]; 313 int priv_flags, init_flags; 314 315 r = sys_whoami(&me, name, sizeof(name), &priv_flags, &init_flags); 316 assert(r == OK); 317 if(me != RS_PROC_NR) { 318 r = vm_update((*new_rpp)->r_pub->endpoint, (*old_rpp)->r_pub->endpoint, SF_VM_ROLLBACK); 319 if(rs_verbose) 320 printf("RS: %s performed rollback\n", srv_to_string(*new_rpp)); 321 } 322 /* Since we may now have missed heartbeat replies, resend requests. */ 323 for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) 324 if (rp->r_flags & RS_ACTIVE) 325 rp->r_check_tm = 0; 326 } 327 else { 328 int swap_flag = ((*new_rpp)->r_flags & RS_INIT_PENDING ? RS_DONTSWAP : RS_SWAP); 329 if(rs_verbose) 330 printf("RS: %s performs rollback\n", srv_to_string(*new_rpp)); 331 if(swap_flag == RS_SWAP) { 332 /* Freeze the new instance to rollback safely. */ 333 sys_privctl((*new_rpp)->r_pub->endpoint, SYS_PRIV_DISALLOW, NULL); 334 } 335 r = update_service(new_rpp, old_rpp, swap_flag, SF_VM_ROLLBACK); 336 } 337 338 assert(r == OK); /* can't fail */ 339 } 340 341 /*===========================================================================* 342 * update_period * 343 *===========================================================================*/ 344 void update_period(message *m_ptr) 345 { 346 /* Periodically check the status of the update (preparation phase). */ 347 clock_t now = m_ptr->m_notify.timestamp; 348 short has_update_timed_out; 349 message m; 350 struct rprocupd *rpupd; 351 struct rproc *rp; 352 struct rprocpub *rpub; 353 354 rpupd = rupdate.curr_rpupd; 355 rp = rpupd->rp; 356 rpub = rp->r_pub; 357 358 /* See if a timeout has occurred. */ 359 has_update_timed_out = (rpupd->prepare_maxtime > 0) && (now - rpupd->prepare_tm > rpupd->prepare_maxtime); 360 361 /* If an update timed out, end the update process and notify 362 * the old version that the update has been canceled. From now on, the old 363 * version will continue executing. 364 */ 365 if(has_update_timed_out) { 366 printf("RS: update failed: maximum prepare time reached\n"); 367 end_update(EINTR, RS_CANCEL); 368 } 369 } 370 371 /*===========================================================================* 372 * start_update_prepare * 373 *===========================================================================*/ 374 int start_update_prepare(int allow_retries) 375 { 376 /* Start the preparation phase of the update process. */ 377 struct rprocupd *prev_rpupd, *rpupd; 378 struct rproc *rp, *new_rp; 379 int r; 380 381 if(!RUPDATE_IS_UPD_SCHEDULED()) { 382 return EINVAL; 383 } 384 if(!rs_is_idle()) { 385 printf("RS: not idle now, try again\n"); 386 if(!allow_retries) { 387 abort_update_proc(EAGAIN); 388 } 389 return EAGAIN; 390 } 391 392 if(rs_verbose) 393 printf("RS: starting the preparation phase of the update process\n"); 394 395 if(rupdate.rs_rpupd) { 396 assert(rupdate.rs_rpupd == rupdate.last_rpupd); 397 assert(rupdate.rs_rpupd->rp->r_pub->endpoint == RS_PROC_NR); 398 assert(!UPD_IS_PREPARING_ONLY(rupdate.rs_rpupd)); 399 } 400 if(rupdate.vm_rpupd) { 401 assert(rupdate.vm_rpupd->rp->r_pub->endpoint == VM_PROC_NR); 402 assert(!UPD_IS_PREPARING_ONLY(rupdate.vm_rpupd)); 403 } 404 405 /* If a multi-component update includes VM, fill information about old 406 * and new endpoints, as well as update flags. VM needs this to complete 407 * the update internally at state transfer time. 408 */ 409 if(RUPDATE_IS_UPD_VM_MULTI()) { 410 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 411 if(!UPD_IS_PREPARING_ONLY(rpupd)) { 412 rp = rpupd->rp; 413 new_rp = rp->r_new_rp; 414 assert(rp && new_rp); 415 rp->r_pub->old_endpoint = rpupd->state_endpoint; 416 rp->r_pub->new_endpoint = rp->r_pub->endpoint; 417 if(rpupd != rupdate.vm_rpupd && rpupd != rupdate.rs_rpupd) { 418 rp->r_pub->sys_flags |= SF_VM_UPDATE; 419 if(rpupd->lu_flags & SEF_LU_NOMMAP) { 420 rp->r_pub->sys_flags |= SF_VM_NOMMAP; 421 } 422 if(!(rpupd->lu_flags & SEF_LU_UNSAFE)) { 423 if(rs_verbose) 424 printf("RS: %s pinning memory\n", srv_to_string(rp)); 425 vm_memctl(rp->r_pub->new_endpoint, VM_RS_MEM_PIN, 0, 0); 426 if(rs_verbose) 427 printf("RS: %s pinning memory\n", srv_to_string(new_rp)); 428 vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_PIN, 0, 0); 429 } 430 } 431 } 432 ); 433 } 434 435 /* Request the first service to prepare for the update. */ 436 if(start_update_prepare_next() == NULL) { 437 /* If we are done already, end the update now. */ 438 end_update(OK, RS_REPLY); 439 return ESRCH; 440 } 441 442 return OK; 443 } 444 445 /*===========================================================================* 446 * start_update_prepare_next * 447 *===========================================================================*/ 448 struct rprocupd* start_update_prepare_next() 449 { 450 /* Request the next service in the update chain to prepare for the update. */ 451 struct rprocupd *rpupd = NULL; 452 if(!RUPDATE_IS_UPDATING()) { 453 rpupd = rupdate.first_rpupd; 454 } 455 else { 456 rpupd = rupdate.curr_rpupd->next_rpupd; 457 } 458 if(!rpupd) { 459 return NULL; 460 } 461 rupdate.flags |= RS_UPDATING; 462 463 while(1) { 464 rupdate.curr_rpupd = rpupd; 465 request_prepare_update_service(rupdate.curr_rpupd->rp, rupdate.curr_rpupd->prepare_state); 466 if(!UPD_IS_PREPARING_ONLY(rpupd)) { 467 /* Continue only if the current service requires a prepare-only update. */ 468 break; 469 } 470 if(!rupdate.curr_rpupd->next_rpupd) { 471 /* Continue only if there are services left. */ 472 break; 473 } 474 rpupd = rupdate.curr_rpupd->next_rpupd; 475 } 476 477 return rpupd; 478 } 479 480 /*===========================================================================* 481 * start_update * 482 *===========================================================================*/ 483 int start_update() 484 { 485 /* Start the update phase of the update process. */ 486 struct rprocupd *prev_rpupd, *rpupd; 487 int r, init_ready_pending=0; 488 489 if(rs_verbose) 490 printf("RS: starting a %s-component update process\n", 491 RUPDATE_IS_UPD_MULTI() ? "multi" : "single"); 492 493 assert(RUPDATE_IS_UPDATING()); 494 assert(rupdate.num_rpupds > 0); 495 assert(rupdate.num_init_ready_pending == 0); 496 assert(rupdate.first_rpupd); 497 assert(rupdate.last_rpupd); 498 assert(rupdate.curr_rpupd == rupdate.last_rpupd); 499 rupdate.flags |= RS_INITIALIZING; 500 501 /* Cancel the update for the prepare-only services now. */ 502 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 503 if(UPD_IS_PREPARING_ONLY(rpupd)) { 504 request_prepare_update_service(rpupd->rp, SEF_LU_STATE_NULL); 505 } 506 ); 507 508 /* Iterate over all the processes scheduled for the update. Update each 509 * service and initialize the new instance. If VM is part of a 510 * multi-component live update, initialize VM first. 511 */ 512 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 513 rupdate.curr_rpupd = rpupd; 514 if(!UPD_IS_PREPARING_ONLY(rpupd)) { 515 init_ready_pending=1; 516 r = start_srv_update(rpupd); 517 if(r != OK) { 518 return r; 519 } 520 if(!RUPDATE_IS_UPD_VM_MULTI() || rpupd == rupdate.vm_rpupd) { 521 r = complete_srv_update(rpupd); 522 if(r != OK) { 523 return r; 524 } 525 } 526 } 527 ); 528 529 /* End update if there is nothing more to do. */ 530 if (!init_ready_pending) { 531 end_update(OK, 0); 532 return OK; 533 } 534 535 /* Handle multi-component live updates including VM. */ 536 if(RUPDATE_IS_UPD_VM_MULTI()) { 537 message m; 538 /* Check VM initialization, assume failure after timeout. */ 539 if (rs_verbose) 540 printf("RS: waiting for VM to initialize...\n"); 541 r = rs_receive_ticks(VM_PROC_NR, &m, NULL, UPD_INIT_MAXTIME(rupdate.vm_rpupd)); 542 if(r != OK || m.m_type != RS_INIT || m.m_rs_init.result != OK) { 543 r = (r == OK && m.m_type == RS_INIT ? m.m_rs_init.result : EINTR); 544 m.m_source = VM_PROC_NR; 545 m.m_type = RS_INIT; 546 m.m_rs_init.result = r; 547 } 548 do_init_ready(&m); 549 /* If initialization was successfull, complete the update. */ 550 if(r == OK) { 551 /* Reply and unblock VM immediately. */ 552 m.m_type = OK; 553 reply(VM_PROC_NR, NULL, &m); 554 /* Initialize other services. */ 555 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 556 if(!UPD_IS_PREPARING_ONLY(rpupd) && rpupd != rupdate.vm_rpupd) { 557 r = complete_srv_update(rpupd); 558 if(r != OK) { 559 return r; 560 } 561 } 562 ); 563 } 564 } 565 566 return OK; 567 } 568 569 /*===========================================================================* 570 * start_srv_update * 571 *===========================================================================*/ 572 int start_srv_update(struct rprocupd *rpupd) 573 { 574 /* Start updating a single service given its update descriptor. */ 575 struct rproc *old_rp, *new_rp; 576 int r, sys_upd_flags = 0; 577 578 old_rp = rpupd->rp; 579 new_rp = old_rp->r_new_rp; 580 assert(old_rp && new_rp); 581 582 if(rs_verbose) 583 printf("RS: %s starting the %s\n", srv_to_string(old_rp), srv_upd_to_string(rpupd)); 584 585 rupdate.num_init_ready_pending++; 586 new_rp->r_flags |= RS_INITIALIZING; 587 new_rp->r_flags |= RS_INIT_PENDING; 588 if(rpupd->lu_flags & SEF_LU_NOMMAP) { 589 sys_upd_flags |= SF_VM_NOMMAP; 590 } 591 592 /* Perform the update, skip for RS. */ 593 if(old_rp->r_pub->endpoint != RS_PROC_NR) { 594 r = update_service(&old_rp, &new_rp, RS_SWAP, sys_upd_flags); 595 if(r != OK) { 596 end_update(r, RS_REPLY); 597 printf("RS: update failed: error %d\n", r); 598 return r; 599 } 600 } 601 602 return OK; 603 } 604 605 /*===========================================================================* 606 * complete_srv_update * 607 *===========================================================================*/ 608 int complete_srv_update(struct rprocupd *rpupd) 609 { 610 /* Complete update of a service given its update descriptor. */ 611 struct rproc *old_rp, *new_rp; 612 int r; 613 614 old_rp = rpupd->rp; 615 new_rp = old_rp->r_new_rp; 616 assert(old_rp && new_rp); 617 618 if(rs_verbose) 619 printf("RS: %s completing the %s\n", srv_to_string(old_rp), srv_upd_to_string(rpupd)); 620 621 new_rp->r_flags &= ~RS_INIT_PENDING; 622 623 /* If RS itself is updating, yield control to the new version immediately. */ 624 if(old_rp->r_pub->endpoint == RS_PROC_NR) { 625 r = init_service(new_rp, SEF_INIT_LU, rpupd->init_flags); 626 if(r != OK) { 627 panic("unable to initialize the new RS instance: %d", r); 628 } 629 if(rs_verbose) 630 printf("RS: %s is the new RS instance we'll yield control to\n", srv_to_string(new_rp)); 631 r = sys_privctl(new_rp->r_pub->endpoint, SYS_PRIV_YIELD, NULL); 632 if(r != OK) { 633 panic("unable to yield control to the new RS instance: %d", r); 634 } 635 /* If we get this far, the new version failed to initialize. Rollback. */ 636 rollback_service(&new_rp, &old_rp); 637 end_update(ERESTART, RS_REPLY); 638 printf("RS: update failed: state transfer failed for the new RS instance\n"); 639 return ERESTART; 640 } 641 642 /* Let the new version run. */ 643 r = run_service(new_rp, SEF_INIT_LU, rpupd->init_flags); 644 if(r != OK) { 645 /* Something went wrong. Rollback. */ 646 rollback_service(&new_rp, &old_rp); 647 end_update(r, RS_REPLY); 648 printf("RS: update failed: error %d\n", r); 649 return r; 650 } 651 652 return OK; 653 } 654 655 /*===========================================================================* 656 * abort_update_proc * 657 *===========================================================================*/ 658 int abort_update_proc(int reason) 659 { 660 /* This function is called to abort a scheduled/in-progress update process 661 * indiscriminately. If the update is in progress, simply pretend the 662 * current service is causing premature termination of the update. 663 */ 664 int is_updating = RUPDATE_IS_UPDATING(); 665 assert(reason != OK); 666 667 if(!is_updating && !RUPDATE_IS_UPD_SCHEDULED()) { 668 return EINVAL; 669 } 670 671 if(rs_verbose) 672 printf("RS: aborting the %s update process prematurely\n", 673 is_updating ? "in-progress" : "scheduled"); 674 675 if(!is_updating) { 676 rupdate_clear_upds(); 677 return OK; 678 } 679 680 if(rupdate.flags & RS_INITIALIZING) { 681 /* Pretend the current service under update failed to initialize. */ 682 end_update(reason, RS_REPLY); 683 } 684 else { 685 /* Pretend the current service under update failed to prepare. */ 686 end_update(reason, RS_CANCEL); 687 } 688 689 return OK; 690 } 691 692 /*===========================================================================* 693 * end_update_curr * 694 *===========================================================================*/ 695 static void end_update_curr(struct rprocupd *rpupd, int result, int reply_flag) 696 { 697 /* Execute the requested action on the current service under update. */ 698 struct rproc *old_rp, *new_rp; 699 assert(rpupd == rupdate.curr_rpupd); 700 701 old_rp = rpupd->rp; 702 new_rp = old_rp->r_new_rp; 703 assert(old_rp && new_rp); 704 if(result != OK && SRV_IS_UPDATING_AND_INITIALIZING(new_rp) && rpupd != rupdate.rs_rpupd) { 705 /* Rollback in case of failures at initialization time. */ 706 rollback_service(&new_rp, &old_rp); 707 } 708 end_srv_update(rpupd, result, reply_flag); 709 } 710 711 /*===========================================================================* 712 * end_update_before_prepare * 713 *===========================================================================*/ 714 static void end_update_before_prepare(struct rprocupd *rpupd, int result) 715 { 716 /* The service is still waiting for the update. Cleanup the new version and 717 * keep the old version running. 718 */ 719 struct rproc *old_rp, *new_rp; 720 assert(result != OK); 721 722 old_rp = rpupd->rp; 723 new_rp = old_rp->r_new_rp; 724 assert(old_rp && new_rp); 725 cleanup_service(new_rp); 726 } 727 728 /*===========================================================================* 729 * end_update_prepare_done * 730 *===========================================================================*/ 731 static void end_update_prepare_done(struct rprocupd *rpupd, int result) 732 { 733 /* The service is blocked after preparing for the update. Unblock it 734 * and cleanup the new version. 735 */ 736 assert(!RUPDATE_IS_INITIALIZING()); 737 assert(result != OK); 738 assert(!(rpupd->rp->r_flags & RS_INITIALIZING)); 739 740 end_srv_update(rpupd, result, RS_REPLY); 741 } 742 743 /*===========================================================================* 744 * end_update_initializing * 745 *===========================================================================*/ 746 static void end_update_initializing(struct rprocupd *rpupd, int result) 747 { 748 /* The service is initializing after a live udate. Cleanup the version that 749 * has to die out and let the other version run. 750 */ 751 struct rproc *old_rp, *new_rp; 752 753 old_rp = rpupd->rp; 754 new_rp = old_rp->r_new_rp; 755 assert(old_rp && new_rp); 756 assert(SRV_IS_UPDATING_AND_INITIALIZING(new_rp)); 757 if(result != OK && rpupd != rupdate.rs_rpupd) { 758 /* Rollback in case of failures at initialization time. */ 759 rollback_service(&new_rp, &old_rp); 760 } 761 end_srv_update(rpupd, result, RS_REPLY); 762 } 763 764 /*===========================================================================* 765 * end_update_rev_iter * 766 *===========================================================================*/ 767 static void end_update_rev_iter(int result, int reply_flag, 768 struct rprocupd *skip_rpupd, struct rprocupd *only_rpupd) 769 { 770 /* End the update for all the requested services. */ 771 struct rprocupd *prev_rpupd, *rpupd; 772 short is_curr, is_before_curr, is_after_curr; 773 774 is_after_curr = 1; 775 RUPDATE_REV_ITER(rupdate.last_rpupd, prev_rpupd, rpupd, 776 is_curr = (rupdate.curr_rpupd == rpupd); 777 is_after_curr = is_after_curr && !is_curr; 778 if(!UPD_IS_PREPARING_ONLY(rpupd)) { 779 short is_before_prepare; 780 short is_prepare_done; 781 short is_initializing; 782 is_before_curr = !is_curr && !is_after_curr; 783 if(RUPDATE_IS_INITIALIZING()) { 784 is_before_prepare = 0; 785 is_prepare_done = is_after_curr; 786 is_initializing = is_before_curr; 787 } 788 else { 789 is_before_prepare = is_after_curr; 790 is_prepare_done = is_before_curr; 791 is_initializing = 0; 792 } 793 if((!skip_rpupd || rpupd != skip_rpupd) && (!only_rpupd || rpupd == only_rpupd)) { 794 /* Analyze different cases. */ 795 if(is_curr) { 796 end_update_curr(rpupd, result, reply_flag); 797 } 798 else if(is_before_prepare) { 799 end_update_before_prepare(rpupd, result); 800 } 801 else if(is_prepare_done) { 802 end_update_prepare_done(rpupd, result); 803 } 804 else { 805 assert(is_initializing); 806 end_update_initializing(rpupd, result); 807 } 808 } 809 } 810 ); 811 } 812 813 /*===========================================================================* 814 * end_update_debug * 815 *===========================================================================*/ 816 void end_update_debug(char *file, int line, 817 int result, int reply_flag) 818 { 819 /* End an in-progress update process. */ 820 struct rprocupd *prev_rpupd, *rpupd, *rpupd_it; 821 struct rproc *rp, *old_rp, *new_rp; 822 int i, r, slot_nr; 823 824 assert(RUPDATE_IS_UPDATING()); 825 826 if(rs_verbose) 827 printf("RS: %s ending the update: result=%d, reply=%d at %s:%d\n", 828 srv_to_string(rupdate.curr_rpupd->rp), result, (reply_flag==RS_REPLY), 829 file, line); 830 831 /* If the new instance of RS is active and the update failed, ending 832 * the update couldn't be any easier. 833 */ 834 if(result != OK && RUPDATE_IS_RS_INIT_DONE()) { 835 if(rs_verbose) 836 printf("RS: update failed, new RS instance will now exit\n"); 837 exit(1); 838 } 839 840 /* If VM is updated as part of a multi-component live update and something 841 * goes wrong after VM has completed initialization, rollback is only 842 * supported in a best-effort way in unsafe mode. The new VM instance might 843 * have important state changes that won't be reflected in the old version 844 * once we rollback. 845 */ 846 if(result != OK && RUPDATE_IS_UPD_VM_MULTI() && RUPDATE_IS_VM_INIT_DONE() && (rupdate.vm_rpupd->lu_flags & SEF_LU_UNSAFE)) { 847 printf("RS: Warning rollbacking in unsafe multi-component update including VM!\n"); 848 } 849 850 /* Handle prepare-only services first: simply cancel the update. */ 851 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 852 if(UPD_IS_PREPARING_ONLY(rpupd)) { 853 if(!RUPDATE_IS_INITIALIZING()) { 854 request_prepare_update_service(rpupd->rp, SEF_LU_STATE_NULL); 855 } 856 rpupd->rp->r_flags &= ~RS_PREPARE_DONE; 857 } 858 ); 859 860 /* Handle all the other services now, VM always last to support rollback. */ 861 end_update_rev_iter(result, reply_flag, rupdate.vm_rpupd, NULL); 862 if(rupdate.vm_rpupd) { 863 end_update_rev_iter(result, reply_flag, NULL, rupdate.vm_rpupd); 864 } 865 866 /* End the update and complete initialization in case of success. */ 867 RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 868 if(prev_rpupd) { 869 rupdate_upd_clear(prev_rpupd); 870 } 871 if(result == OK && !UPD_IS_PREPARING_ONLY(rpupd)) { 872 /* The rp pointer points to the new instance in this case. */ 873 new_rp = rpupd->rp; 874 end_srv_init(new_rp); 875 } 876 ); 877 late_reply(rupdate.last_rpupd->rp, result); 878 rupdate_upd_clear(rupdate.last_rpupd); 879 RUPDATE_CLEAR(); 880 881 /* Clear all the old/new endpoints and update flags in the public entries. */ 882 for(slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { 883 rp = &rproc[slot_nr]; 884 rp->r_pub->old_endpoint = NONE; 885 rp->r_pub->new_endpoint = NONE; 886 rp->r_pub->sys_flags &= ~(SF_VM_UPDATE|SF_VM_ROLLBACK|SF_VM_NOMMAP); 887 } 888 } 889 890 /*===========================================================================* 891 * end_srv_update * 892 *===========================================================================*/ 893 void end_srv_update(struct rprocupd *rpupd, int result, int reply_flag) 894 { 895 /* End the update for the given service. There are two possibilities: 896 * 1) the update succeeded. In that case, cleanup the old version and mark the 897 * new version as no longer under update. 898 * 2) the update failed. In that case, cleanup the new version and mark the old 899 * version as no longer under update. Eventual late ready to update 900 * messages (if any) will simply be ignored and the service can 901 * continue executing. In addition, reset the check timestamp, so that if the 902 * service has a period, a status request will be forced in the next period. 903 */ 904 struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp; 905 struct rproc **rps; 906 907 struct rprocpub *rpub; 908 int nr_rps, i; 909 910 old_rp = rpupd->rp; 911 new_rp = old_rp->r_new_rp; 912 assert(old_rp && new_rp); 913 if(result == OK && new_rp->r_pub->endpoint == VM_PROC_NR && RUPDATE_IS_UPD_MULTI()) { 914 /* VM has already been replied to in case of multi-component live update. 915 * Send an update cancel message to trigger cleanup. 916 */ 917 reply_flag = RS_CANCEL; 918 } 919 920 if(rs_verbose) 921 printf("RS: ending update from %s to %s with result=%d, reply=%d\n", 922 srv_to_string(old_rp), srv_to_string(new_rp), result, (reply_flag==RS_REPLY)); 923 924 /* Decide which version has to die out and which version has to survive. */ 925 surviving_rp = (result == OK ? new_rp : old_rp); 926 exiting_rp = (result == OK ? old_rp : new_rp); 927 surviving_rp->r_flags &= ~RS_INITIALIZING; 928 surviving_rp->r_check_tm = 0; 929 getticks(&surviving_rp->r_alive_tm); 930 931 /* Keep track of the surviving process in the update descriptor from now on. */ 932 rpupd->rp = surviving_rp; 933 934 /* Unlink the two versions. */ 935 old_rp->r_new_rp = NULL; 936 new_rp->r_old_rp = NULL; 937 938 /* Mark the version that has to survive as no longer updating and 939 * reply when asked to. 940 */ 941 surviving_rp->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING); 942 if(reply_flag == RS_REPLY) { 943 message m; 944 m.m_type = result; 945 reply(surviving_rp->r_pub->endpoint, surviving_rp, &m); 946 } 947 else if(reply_flag == RS_CANCEL) { 948 if(!(surviving_rp->r_flags & RS_TERMINATED)) { 949 request_prepare_update_service(surviving_rp, SEF_LU_STATE_NULL); 950 } 951 } 952 953 /* Cleanup or detach the version that has to die out. */ 954 get_service_instances(exiting_rp, &rps, &nr_rps); 955 for(i=0;i<nr_rps;i++) { 956 if(rps[i] == old_rp && (rpupd->lu_flags & SEF_LU_DETACHED)) { 957 message m; 958 m.m_type = EDEADEPT; 959 rps[i]->r_flags |= RS_CLEANUP_DETACH; 960 cleanup_service(rps[i]); 961 reply(rps[i]->r_pub->endpoint, rps[i], &m); 962 } 963 else { 964 cleanup_service(rps[i]); 965 } 966 } 967 968 if(rs_verbose) 969 printf("RS: %s ended the %s\n", srv_to_string(surviving_rp), 970 srv_upd_to_string(rpupd)); 971 } 972 973