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