1 /* 2 * Changes: 3 * Jan 22, 2010: Created (Cristiano Giuffrida) 4 */ 5 6 #include "inc.h" 7 8 #include "kernel/proc.h" 9 10 static int check_request(struct rs_start *rs_start); 11 12 /*===========================================================================* 13 * do_up * 14 *===========================================================================*/ 15 int do_up(m_ptr) 16 message *m_ptr; /* request message pointer */ 17 { 18 /* A request was made to start a new system service. */ 19 struct rproc *rp; 20 struct rprocpub *rpub; 21 int i, r; 22 struct rs_start rs_start; 23 int noblock; 24 int init_flags = 0; 25 26 /* Check if the call can be allowed. */ 27 if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK) 28 return r; 29 30 /* Allocate a new system service slot. */ 31 r = alloc_slot(&rp); 32 if(r != OK) { 33 printf("RS: do_up: unable to allocate a new slot: %d\n", r); 34 return r; 35 } 36 rpub = rp->r_pub; 37 38 /* Copy the request structure. */ 39 r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 40 if (r != OK) { 41 return r; 42 } 43 r = check_request(&rs_start); 44 if (r != OK) { 45 return r; 46 } 47 48 /* Check flags. */ 49 noblock = (rs_start.rss_flags & RSS_NOBLOCK); 50 if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) { 51 init_flags |= SEF_INIT_CRASH; 52 } 53 if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) { 54 init_flags |= SEF_INIT_FAIL; 55 } 56 if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) { 57 init_flags |= SEF_INIT_TIMEOUT; 58 } 59 if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) { 60 init_flags |= SEF_INIT_DEFCB; 61 } 62 63 /* Initialize the slot as requested. */ 64 r = init_slot(rp, &rs_start, m_ptr->m_source); 65 if(r != OK) { 66 printf("RS: do_up: unable to init the new slot: %d\n", r); 67 return r; 68 } 69 70 /* Check for duplicates */ 71 if(lookup_slot_by_label(rpub->label)) { 72 printf("RS: service with the same label '%s' already exists\n", 73 rpub->label); 74 return EBUSY; 75 } 76 if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) { 77 printf("RS: service with the same device number %d already exists\n", 78 rpub->dev_nr); 79 return EBUSY; 80 } 81 for (i = 0; i < rpub->nr_domain; i++) { 82 if (lookup_slot_by_domain(rpub->domain[i]) != NULL) { 83 printf("RS: service with the same domain %d already exists\n", 84 rpub->domain[i]); 85 return EBUSY; 86 } 87 } 88 89 /* All information was gathered. Now try to start the system service. */ 90 r = start_service(rp, init_flags); 91 if(r != OK) { 92 return r; 93 } 94 95 /* Unblock the caller immediately if requested. */ 96 if(noblock) { 97 return OK; 98 } 99 100 /* Late reply - send a reply when service completes initialization. */ 101 rp->r_flags |= RS_LATEREPLY; 102 rp->r_caller = m_ptr->m_source; 103 rp->r_caller_request = RS_UP; 104 105 return EDONTREPLY; 106 } 107 108 /*===========================================================================* 109 * do_down * 110 *===========================================================================*/ 111 int do_down(message *m_ptr) 112 { 113 register struct rproc *rp; 114 int s; 115 char label[RS_MAX_LABEL_LEN]; 116 117 /* Copy label. */ 118 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 119 m_ptr->m_rs_req.len, label, sizeof(label)); 120 if(s != OK) { 121 return s; 122 } 123 124 /* Lookup slot by label. */ 125 rp = lookup_slot_by_label(label); 126 if(!rp) { 127 if(rs_verbose) 128 printf("RS: do_down: service '%s' not found\n", label); 129 return(ESRCH); 130 } 131 132 /* Check if the call can be allowed. */ 133 if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK) 134 return s; 135 136 /* Stop service. */ 137 if (rp->r_flags & RS_TERMINATED) { 138 /* A recovery script is requesting us to bring down the service. 139 * The service is already gone, simply perform cleanup. 140 */ 141 if(rs_verbose) 142 printf("RS: recovery script performs service down...\n"); 143 unpublish_service(rp); 144 cleanup_service(rp); 145 return(OK); 146 } 147 stop_service(rp,RS_EXITING); 148 149 /* Late reply - send a reply when service dies. */ 150 rp->r_flags |= RS_LATEREPLY; 151 rp->r_caller = m_ptr->m_source; 152 rp->r_caller_request = RS_DOWN; 153 154 return EDONTREPLY; 155 } 156 157 /*===========================================================================* 158 * do_restart * 159 *===========================================================================*/ 160 int do_restart(message *m_ptr) 161 { 162 struct rproc *rp; 163 int s, r; 164 char label[RS_MAX_LABEL_LEN]; 165 char script[MAX_SCRIPT_LEN]; 166 167 /* Copy label. */ 168 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 169 m_ptr->m_rs_req.len, label, sizeof(label)); 170 if(s != OK) { 171 return s; 172 } 173 174 /* Lookup slot by label. */ 175 rp = lookup_slot_by_label(label); 176 if(!rp) { 177 if(rs_verbose) 178 printf("RS: do_restart: service '%s' not found\n", label); 179 return(ESRCH); 180 } 181 182 /* Check if the call can be allowed. */ 183 if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK) 184 return r; 185 186 /* We can only be asked to restart a service from a recovery script. */ 187 if (! (rp->r_flags & RS_TERMINATED) ) { 188 if(rs_verbose) 189 printf("RS: %s is still running\n", srv_to_string(rp)); 190 return EBUSY; 191 } 192 193 if(rs_verbose) 194 printf("RS: recovery script performs service restart...\n"); 195 196 /* Restart the service, but make sure we don't call the script again. */ 197 strcpy(script, rp->r_script); 198 rp->r_script[0] = '\0'; 199 restart_service(rp); 200 strcpy(rp->r_script, script); 201 202 return OK; 203 } 204 205 /*===========================================================================* 206 * do_clone * 207 *===========================================================================*/ 208 int do_clone(message *m_ptr) 209 { 210 struct rproc *rp; 211 struct rprocpub *rpub; 212 int s, r; 213 char label[RS_MAX_LABEL_LEN]; 214 215 /* Copy label. */ 216 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 217 m_ptr->m_rs_req.len, label, sizeof(label)); 218 if(s != OK) { 219 return s; 220 } 221 222 /* Lookup slot by label. */ 223 rp = lookup_slot_by_label(label); 224 if(!rp) { 225 if(rs_verbose) 226 printf("RS: do_clone: service '%s' not found\n", label); 227 return(ESRCH); 228 } 229 rpub = rp->r_pub; 230 231 /* Check if the call can be allowed. */ 232 if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK) 233 return r; 234 235 /* Don't clone if a replica is already available. */ 236 if(rp->r_next_rp) { 237 return EEXIST; 238 } 239 240 /* Clone the service as requested. */ 241 rpub->sys_flags |= SF_USE_REPL; 242 if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) { 243 rpub->sys_flags &= ~SF_USE_REPL; 244 return r; 245 } 246 247 return OK; 248 } 249 250 /*===========================================================================* 251 * do_unclone * 252 *===========================================================================*/ 253 int do_unclone(message *m_ptr) 254 { 255 struct rproc *rp; 256 struct rprocpub *rpub; 257 int s, r; 258 char label[RS_MAX_LABEL_LEN]; 259 260 /* Copy label. */ 261 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 262 m_ptr->m_rs_req.len, label, sizeof(label)); 263 if(s != OK) { 264 return s; 265 } 266 267 /* Lookup slot by label. */ 268 rp = lookup_slot_by_label(label); 269 if(!rp) { 270 if(rs_verbose) 271 printf("RS: do_unclone: service '%s' not found\n", label); 272 return(ESRCH); 273 } 274 rpub = rp->r_pub; 275 276 /* Check if the call can be allowed. */ 277 if((r = check_call_permission(m_ptr->m_source, RS_UNCLONE, rp)) != OK) 278 return r; 279 280 /* Don't unclone if no replica is available. */ 281 if(!(rpub->sys_flags & SF_USE_REPL)) { 282 return ENOENT; 283 } 284 285 /* Unclone the service as requested. */ 286 rpub->sys_flags &= ~SF_USE_REPL; 287 if(rp->r_next_rp) { 288 cleanup_service_now(rp->r_next_rp); 289 rp->r_next_rp = NULL; 290 } 291 292 return OK; 293 } 294 295 /*===========================================================================* 296 * do_edit * 297 *===========================================================================*/ 298 int do_edit(message *m_ptr) 299 { 300 struct rproc *rp; 301 struct rprocpub *rpub; 302 struct rs_start rs_start; 303 int r; 304 char label[RS_MAX_LABEL_LEN]; 305 306 /* Copy the request structure. */ 307 r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 308 if (r != OK) { 309 return r; 310 } 311 312 /* Copy label. */ 313 r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 314 rs_start.rss_label.l_len, label, sizeof(label)); 315 if(r != OK) { 316 return r; 317 } 318 319 /* Lookup slot by label. */ 320 rp = lookup_slot_by_label(label); 321 if(!rp) { 322 if(rs_verbose) 323 printf("RS: do_edit: service '%s' not found\n", label); 324 return ESRCH; 325 } 326 rpub = rp->r_pub; 327 328 /* Check if the call can be allowed. */ 329 if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK) 330 return r; 331 332 if(rs_verbose) 333 printf("RS: %s edits settings\n", srv_to_string(rp)); 334 335 /* Synch the privilege structure with the kernel. */ 336 if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) { 337 printf("RS: do_edit: unable to synch privilege structure: %d\n", r); 338 return r; 339 } 340 341 /* Tell scheduler this process is finished */ 342 if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) { 343 printf("RS: do_edit: scheduler won't give up process: %d\n", r); 344 return r; 345 } 346 347 /* Edit the slot as requested. */ 348 if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) { 349 printf("RS: do_edit: unable to edit the existing slot: %d\n", r); 350 return r; 351 } 352 353 /* Update privilege structure. */ 354 r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv); 355 if(r != OK) { 356 printf("RS: do_edit: unable to update privilege structure: %d\n", r); 357 return r; 358 } 359 360 /* Update VM calls. */ 361 if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0], 362 !!(rp->r_priv.s_flags & SYS_PROC))) != OK) { 363 printf("RS: do_edit: failed: %d\n", r); 364 return r; 365 } 366 367 /* Reinitialize scheduling. */ 368 if ((r = sched_init_proc(rp)) != OK) { 369 printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r); 370 return r; 371 } 372 373 /* Cleanup old replicas and create a new one, if necessary. */ 374 if(rpub->sys_flags & SF_USE_REPL) { 375 if(rp->r_next_rp) { 376 cleanup_service(rp->r_next_rp); 377 rp->r_next_rp = NULL; 378 } 379 if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) { 380 printf("RS: warning: unable to clone %s\n", srv_to_string(rp)); 381 } 382 } 383 384 return OK; 385 } 386 387 /*===========================================================================* 388 * do_refresh * 389 *===========================================================================*/ 390 int do_refresh(message *m_ptr) 391 { 392 register struct rproc *rp; 393 int s; 394 char label[RS_MAX_LABEL_LEN]; 395 396 /* Copy label. */ 397 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 398 m_ptr->m_rs_req.len, label, sizeof(label)); 399 if(s != OK) { 400 return s; 401 } 402 403 /* Lookup slot by label. */ 404 rp = lookup_slot_by_label(label); 405 if(!rp) { 406 if(rs_verbose) 407 printf("RS: do_refresh: service '%s' not found\n", label); 408 return(ESRCH); 409 } 410 411 /* Check if the call can be allowed. */ 412 if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK) 413 return s; 414 415 /* Refresh service. */ 416 if(rs_verbose) 417 printf("RS: %s refreshing\n", srv_to_string(rp)); 418 stop_service(rp,RS_REFRESHING); 419 420 /* Late reply - send a reply when refresh completes. */ 421 rp->r_flags |= RS_LATEREPLY; 422 rp->r_caller = m_ptr->m_source; 423 rp->r_caller_request = RS_REFRESH; 424 425 return EDONTREPLY; 426 } 427 428 /*===========================================================================* 429 * do_shutdown * 430 *===========================================================================*/ 431 int do_shutdown(message *m_ptr) 432 { 433 int slot_nr; 434 struct rproc *rp; 435 int r; 436 437 /* Check if the call can be allowed. */ 438 if (m_ptr != NULL) { 439 if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK) 440 return r; 441 } 442 443 if(rs_verbose) 444 printf("RS: shutting down...\n"); 445 446 /* Set flag to tell RS we are shutting down. */ 447 shutting_down = TRUE; 448 449 /* Don't restart dead services. */ 450 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { 451 rp = &rproc[slot_nr]; 452 if (rp->r_flags & RS_IN_USE) { 453 rp->r_flags |= RS_EXITING; 454 } 455 } 456 return(OK); 457 } 458 459 /*===========================================================================* 460 * do_init_ready * 461 *===========================================================================*/ 462 int do_init_ready(message *m_ptr) 463 { 464 int who_p; 465 message m; 466 struct rproc *rp, *new_rp; 467 struct rprocpub *rpub; 468 int result; 469 int r; 470 471 who_p = _ENDPOINT_P(m_ptr->m_source); 472 result = m_ptr->m_rs_init.result; 473 474 rp = rproc_ptr[who_p]; 475 rpub = rp->r_pub; 476 477 /* Make sure the originating service was requested to initialize. */ 478 if(! (rp->r_flags & RS_INITIALIZING) ) { 479 if(rs_verbose) 480 printf("RS: do_init_ready: got unexpected init ready msg from %d\n", 481 m_ptr->m_source); 482 return EINVAL; 483 } 484 485 /* Check if something went wrong and the service failed to init. 486 * In that case, kill the service. 487 */ 488 if(result != OK) { 489 if(rs_verbose) 490 printf("RS: %s initialization error: %s\n", srv_to_string(rp), 491 init_strerror(result)); 492 if (result == ERESTART && !SRV_IS_UPDATING(rp)) 493 rp->r_flags |= RS_REINCARNATE; 494 crash_service(rp); /* simulate crash */ 495 rp->r_init_err = result; 496 return EDONTREPLY; 497 } 498 499 if(rs_verbose) 500 printf("RS: %s initialized\n", srv_to_string(rp)); 501 502 /* If updating, check if there is no service to update left. In that case, 503 * end the update process. If VM has completed initialization as part of 504 * multi-component live update, let the other services under update run now. 505 */ 506 if(SRV_IS_UPDATING(rp)) { 507 rupdate.num_init_ready_pending--; 508 rp->r_flags |= RS_INIT_DONE; 509 if(rupdate.num_init_ready_pending == 0) { 510 printf("RS: update succeeded\n"); 511 end_update(OK, RS_REPLY); 512 } 513 } 514 else { 515 /* Mark the slot as no longer initializing. */ 516 rp->r_flags &= ~RS_INITIALIZING; 517 rp->r_check_tm = 0; 518 rp->r_alive_tm = getticks(); 519 520 /* Reply and unblock the service before doing anything else. */ 521 m.m_type = OK; 522 reply(rpub->endpoint, rp, &m); 523 524 /* Finalize initialization. */ 525 end_srv_init(rp); 526 } 527 528 return EDONTREPLY; 529 } 530 531 /*===========================================================================* 532 * do_update * 533 *===========================================================================*/ 534 int do_update(message *m_ptr) 535 { 536 struct rproc *rp; 537 struct rproc *trg_rp; 538 struct rproc *new_rp; 539 struct rprocpub *rpub; 540 struct rprocupd *rpupd; 541 struct rs_start rs_start; 542 int noblock, do_self_update, force_self_update, batch_mode, prepare_only; 543 int s; 544 char label[RS_MAX_LABEL_LEN]; 545 int prepare_state, prepare_maxtime; 546 endpoint_t state_endpoint; 547 int lu_flags = 0; 548 int init_flags = 0; 549 int allow_retries = 0; 550 551 /* Copy the request structure. */ 552 s = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 553 if (s != OK) { 554 return s; 555 } 556 557 /* Copy label. */ 558 s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 559 rs_start.rss_label.l_len, label, sizeof(label)); 560 if(s != OK) { 561 return s; 562 } 563 564 /* Lookup slot by label. */ 565 rp = lookup_slot_by_label(label); 566 if(!rp) { 567 if(rs_verbose) 568 printf("RS: do_update: service '%s' not found\n", label); 569 return ESRCH; 570 } 571 rpub = rp->r_pub; 572 573 /* Check flags. */ 574 noblock = (rs_start.rss_flags & RSS_NOBLOCK); 575 do_self_update = (rs_start.rss_flags & RSS_SELF_LU); 576 force_self_update = (rs_start.rss_flags & RSS_FORCE_SELF_LU); 577 batch_mode = (rs_start.rss_flags & RSS_BATCH); 578 prepare_only = (rs_start.rss_flags & RSS_PREPARE_ONLY_LU); 579 if(do_self_update || force_self_update) { 580 lu_flags |= SEF_LU_SELF; 581 } 582 if(prepare_only) { 583 lu_flags |= SEF_LU_PREPARE_ONLY; 584 } 585 if(rs_start.rss_flags & RSS_ASR_LU) { 586 lu_flags |= SEF_LU_ASR; 587 } 588 if(!prepare_only && (rs_start.rss_flags & RSS_DETACH)) { 589 lu_flags |= SEF_LU_DETACHED; 590 } 591 if(rs_start.rss_map_prealloc_bytes <= 0 592 && rpub->endpoint == VM_PROC_NR 593 && (((lu_flags & (SEF_LU_SELF|SEF_LU_ASR)) != SEF_LU_SELF) || rs_start.rss_flags & RSS_FORCE_INIT_ST) 594 && RS_VM_DEFAULT_MAP_PREALLOC_LEN > 0) { 595 /* Give VM some mmapped regions by default on non-identical updates.*/ 596 rs_start.rss_map_prealloc_bytes = RS_VM_DEFAULT_MAP_PREALLOC_LEN; 597 if(rs_verbose) 598 printf("RS: %s gets %ld default mmap bytes\n", srv_to_string(rp), 599 rs_start.rss_map_prealloc_bytes); 600 } 601 if((rs_start.rss_flags & RSS_NOMMAP_LU) || rs_start.rss_map_prealloc_bytes) { 602 /* Don't inherit mmapped regions at update time if requested or if 603 * mmap preallocation is used. 604 */ 605 lu_flags |= SEF_LU_NOMMAP; 606 } 607 if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) { 608 init_flags |= SEF_INIT_CRASH; 609 } 610 if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) { 611 init_flags |= SEF_INIT_FAIL; 612 } 613 if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) { 614 init_flags |= SEF_INIT_TIMEOUT; 615 } 616 if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) { 617 init_flags |= SEF_INIT_DEFCB; 618 } 619 if(rs_start.rss_flags & RSS_FORCE_INIT_ST) { 620 init_flags |= SEF_INIT_ST; 621 } 622 init_flags |= lu_flags; 623 624 /* Lookup target label (if any). */ 625 trg_rp = NULL; 626 state_endpoint = NONE; 627 if(rs_start.rss_trg_label.l_len > 0) { 628 s = copy_label(m_ptr->m_source, rs_start.rss_trg_label.l_addr, 629 rs_start.rss_trg_label.l_len, label, sizeof(label)); 630 if(s != OK) { 631 return s; 632 } 633 trg_rp = lookup_slot_by_label(label); 634 if(!trg_rp) { 635 if(rs_verbose) 636 printf("RS: do_update: target service '%s' not found\n", label); 637 return ESRCH; 638 } 639 state_endpoint = trg_rp->r_pub->endpoint; 640 } 641 642 /* Check if the call can be allowed. */ 643 if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK) 644 return s; 645 646 /* Retrieve live update state. */ 647 prepare_state = m_ptr->m_rs_update.state; 648 if(prepare_state == SEF_LU_STATE_NULL) { 649 return(EINVAL); 650 } 651 652 /* Retrieve prepare max time. */ 653 prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime; 654 if(prepare_maxtime == 0) { 655 prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME; 656 } 657 658 /* Make sure we are not already updating. */ 659 if(RUPDATE_IS_UPDATING()) { 660 printf("RS: an update is already in progress\n"); 661 return EBUSY; 662 } 663 664 /* If an update is already scheduled, check constraints. */ 665 if(RUPDATE_IS_UPD_SCHEDULED()) { 666 if(!batch_mode) { 667 printf("RS: an update is already scheduled, cannot start a new one\n"); 668 return EBUSY; 669 } 670 if(SRV_IS_UPD_SCHEDULED(rp)) { 671 printf("RS: the specified process is already part of the currently scheduled update\n"); 672 return EINVAL; 673 } 674 } 675 676 /* Prepare-only update for VM, PM, and VFS is only supported with an unreachable state. */ 677 if(prepare_only 678 && (rp->r_pub->endpoint == VM_PROC_NR || rp->r_pub->endpoint == PM_PROC_NR || rp->r_pub->endpoint == VFS_PROC_NR)) { 679 if(prepare_state != SEF_LU_STATE_UNREACHABLE) { 680 printf("RS: prepare-only update for VM, PM and VFS is only supported with state %d\n", SEF_LU_STATE_UNREACHABLE); 681 return EINVAL; 682 } 683 } 684 685 /* Prepare-only update for RS is not supported. */ 686 if(prepare_only && rp->r_pub->endpoint == RS_PROC_NR) { 687 printf("RS: prepare-only update for RS is not supported\n"); 688 return EINVAL; 689 } 690 691 /* Initialize update descriptor. */ 692 rpupd = &rp->r_upd; 693 rupdate_upd_init(rpupd, rp); 694 rpupd->lu_flags |= lu_flags; 695 rpupd->init_flags |= init_flags; 696 rupdate_set_new_upd_flags(rpupd); 697 698 /* A self update live updates a service instance into a replica, a regular 699 * update live updates a service instance into a new version, as specified 700 * by the given binary. 701 */ 702 if(!prepare_only) { 703 if(do_self_update) { 704 if(rs_verbose) 705 printf("RS: %s requested to perform self update\n", srv_to_string(rp)); 706 707 /* Clone the system service and use the replica as the new version. */ 708 s = clone_service(rp, LU_SYS_PROC, rpupd->init_flags); 709 if(s != OK) { 710 printf("RS: do_update: unable to clone service: %d\n", s); 711 return s; 712 } 713 new_rp = rp->r_new_rp; 714 } 715 else { 716 if(rs_verbose) 717 printf("RS: %s requested to perform %s update\n", srv_to_string(rp), 718 force_self_update ? "(forced) self" : "regular"); 719 720 /* Allocate a system service slot for the new version. */ 721 s = alloc_slot(&new_rp); 722 if(s != OK) { 723 printf("RS: do_update: unable to allocate a new slot: %d\n", s); 724 return s; 725 } 726 727 /* Initialize the slot as requested. */ 728 s = init_slot(new_rp, &rs_start, m_ptr->m_source); 729 if(s != OK) { 730 printf("RS: do_update: unable to init the new slot: %d\n", s); 731 return s; 732 } 733 734 /* Let the new version inherit defaults from the old one. */ 735 inherit_service_defaults(rp, new_rp); 736 737 /* Link the two versions. */ 738 rp->r_new_rp = new_rp; 739 new_rp->r_old_rp = rp; 740 741 /* Create new version of the service but don't let it run. */ 742 new_rp->r_priv.s_flags |= LU_SYS_PROC; 743 new_rp->r_priv.s_init_flags |= rpupd->init_flags; 744 s = create_service(new_rp); 745 if(s != OK) { 746 printf("RS: do_update: unable to create a new service: %d\n", s); 747 return s; 748 } 749 } 750 751 /* Set default state endpoint. */ 752 if(state_endpoint == NONE) { 753 state_endpoint = new_rp->r_pub->endpoint; 754 } 755 756 /* If RS is updating, set up signal managers for the new instance. 757 * The current RS instance must be made the backup signal manager to 758 * support rollback in case of a crash during initialization. 759 */ 760 if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 761 s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint); 762 if(s != OK) { 763 cleanup_service(new_rp); 764 return s; 765 } 766 } 767 768 /* Preallocate heap regions if requested. */ 769 if(rs_start.rss_heap_prealloc_bytes < 0) { 770 rs_start.rss_heap_prealloc_bytes = 0; 771 } 772 if(rs_start.rss_heap_prealloc_bytes) { 773 size_t len; 774 if(rs_verbose) 775 printf("RS: %s preallocating %ld heap bytes\n", srv_to_string(new_rp), 776 rs_start.rss_heap_prealloc_bytes); 777 778 len = rs_start.rss_heap_prealloc_bytes; 779 s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_HEAP_PREALLOC, 780 NULL, &len); 781 if(s != OK) { 782 printf("vm_memctl(VM_RS_MEM_HEAP_PREALLOC) failed: %d\n", s); 783 cleanup_service(new_rp); 784 return s; 785 } 786 if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 787 vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_PIN, 0, 0); 788 } 789 } 790 791 /* Preallocate mmapped regions if requested. */ 792 if(rs_start.rss_map_prealloc_bytes < 0) { 793 rs_start.rss_map_prealloc_bytes = 0; 794 } 795 if(rs_start.rss_map_prealloc_bytes) { 796 void *addr = NULL; 797 if(rs_verbose) 798 printf("RS: %s preallocating %ld mmap bytes\n", srv_to_string(new_rp), 799 rs_start.rss_map_prealloc_bytes); 800 801 new_rp->r_map_prealloc_len = rs_start.rss_map_prealloc_bytes; 802 s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_MAP_PREALLOC, 803 &addr, &new_rp->r_map_prealloc_len); 804 if(s != OK) { 805 printf("vm_memctl(VM_RS_MEM_MAP_PREALLOC) failed: %d\n", s); 806 cleanup_service(new_rp); 807 return s; 808 } 809 new_rp->r_map_prealloc_addr = (vir_bytes) addr; 810 } 811 } 812 813 /* Process state data. */ 814 s = init_state_data(m_ptr->m_source, prepare_state, &rs_start.rss_state_data, &rpupd->prepare_state_data); 815 if(s != OK) { 816 rupdate_upd_clear(rpupd); 817 return s; 818 } 819 820 /* Create update grants. */ 821 if(rpupd->prepare_state_data.size > 0) { 822 struct rs_state_data *state_data = &rpupd->prepare_state_data; 823 rpupd->prepare_state_data_gid = cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data, 824 state_data->size, CPF_READ); 825 if(rpupd->prepare_state_data_gid == GRANT_INVALID) { 826 rupdate_upd_clear(rpupd); 827 return ENOMEM; 828 } 829 state_data->ipcf_els_gid = GRANT_INVALID; 830 if(state_data->ipcf_els) { 831 state_data->ipcf_els_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->ipcf_els, 832 state_data->ipcf_els_size, CPF_READ); 833 if(state_data->ipcf_els_gid == GRANT_INVALID) { 834 rupdate_upd_clear(rpupd); 835 return ENOMEM; 836 } 837 } 838 state_data->eval_gid = GRANT_INVALID; 839 if(state_data->eval_addr) { 840 state_data->eval_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->eval_addr, 841 state_data->eval_len, CPF_READ); 842 if(state_data->eval_gid == GRANT_INVALID) { 843 rupdate_upd_clear(rpupd); 844 return ENOMEM; 845 } 846 } 847 } 848 849 /* Fill the new update descriptor and add it to the update chain. */ 850 rpupd->prepare_state = prepare_state; 851 rpupd->state_endpoint = state_endpoint; 852 rpupd->prepare_tm = getticks(); 853 rpupd->prepare_maxtime = prepare_maxtime; 854 rupdate_add_upd(rpupd); 855 856 if(rs_verbose) 857 printf("RS: %s scheduled for %s\n", srv_to_string(rp), srv_upd_to_string(rpupd)); 858 859 /* If batch mode, reply immediately. More services to update will follow. */ 860 if(batch_mode) { 861 return OK; 862 } 863 864 /* Start preparing for the update process. */ 865 s = start_update_prepare(allow_retries); 866 if(s == ESRCH) { 867 /* No process left in the update chain. We are done already. */ 868 return OK; 869 } 870 if(s != OK) { 871 return s; 872 } 873 874 /* Unblock the caller immediately if requested. */ 875 if(noblock) { 876 return OK; 877 } 878 879 /* Otherwise, send a reply when the new version completes initialization. */ 880 rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY; 881 rupdate.last_rpupd->rp->r_caller = m_ptr->m_source; 882 rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE; 883 884 return EDONTREPLY; 885 } 886 887 /*===========================================================================* 888 * do_upd_ready * 889 *===========================================================================*/ 890 int do_upd_ready(message *m_ptr) 891 { 892 struct rproc *rp; 893 struct rprocupd *prev_rpupd, *rpupd; 894 int who_p; 895 int result; 896 int is_rs; 897 int i; 898 899 who_p = _ENDPOINT_P(m_ptr->m_source); 900 rp = rproc_ptr[who_p]; 901 result = m_ptr->m_rs_update.result; 902 903 /* Make sure the originating service was requested to prepare for update. */ 904 rpupd = rupdate.curr_rpupd; 905 if(!rpupd || rp != rpupd->rp || RUPDATE_IS_INITIALIZING()) { 906 if(rs_verbose) 907 printf("RS: %s sent late/unexpected update ready msg\n", 908 srv_to_string(rp)); 909 return EINVAL; 910 } 911 rp->r_flags |= RS_PREPARE_DONE; 912 913 /* Check if something went wrong and the service failed to prepare 914 * for the update. In that case, end the update process. The old version will 915 * be replied to and continue executing. 916 */ 917 if(result != OK) { 918 printf("RS: update failed: %s\n", lu_strerror(result)); 919 end_update(result, RS_REPLY); 920 921 return EDONTREPLY; 922 } 923 924 if(rs_verbose) 925 printf("RS: %s ready to update\n", srv_to_string(rp)); 926 927 /* If this is a multi-component update and this is not the last service 928 * in the update, request the next process to update. 929 */ 930 if(start_update_prepare_next() != NULL) { 931 return EDONTREPLY; 932 } 933 934 /* Now perform the update and request each new instance to initialize. */ 935 start_update(); 936 937 return EDONTREPLY; 938 } 939 940 /*===========================================================================* 941 * do_period * 942 *===========================================================================*/ 943 void do_period(m_ptr) 944 message *m_ptr; 945 { 946 register struct rproc *rp; 947 register struct rprocpub *rpub; 948 clock_t now = m_ptr->m_notify.timestamp; 949 int s; 950 long period; 951 952 /* If an update is in progress, check its status. */ 953 if(RUPDATE_IS_UPDATING() && !RUPDATE_IS_INITIALIZING()) { 954 update_period(m_ptr); 955 } 956 957 /* Search system services table. Only check slots that are in use and not 958 * updating. 959 */ 960 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { 961 rpub = rp->r_pub; 962 963 if ((rp->r_flags & RS_ACTIVE) && (!SRV_IS_UPDATING(rp) || ((rp->r_flags & (RS_INITIALIZING|RS_INIT_DONE|RS_INIT_PENDING)) == RS_INITIALIZING))) { 964 965 /* Compute period. */ 966 period = rp->r_period; 967 if(rp->r_flags & RS_INITIALIZING) { 968 period = SRV_IS_UPDATING(rp) ? UPD_INIT_MAXTIME(&rp->r_upd) : RS_INIT_T; 969 } 970 971 /* If the service is to be revived (because it repeatedly exited, 972 * and was not directly restarted), the binary backoff field is 973 * greater than zero. 974 */ 975 if (rp->r_backoff > 0) { 976 rp->r_backoff -= 1; 977 if (rp->r_backoff == 0) { 978 restart_service(rp); 979 } 980 } 981 982 /* If the service was signaled with a SIGTERM and fails to respond, 983 * kill the system service with a SIGKILL signal. 984 */ 985 else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T 986 && rp->r_pid > 0) { 987 rp->r_stop_tm = 0; 988 crash_service(rp); /* simulate crash */ 989 } 990 991 /* There seems to be no special conditions. If the service has a 992 * period assigned check its status. 993 */ 994 else if (period > 0) { 995 996 /* Check if an answer to a status request is still pending. If 997 * the service didn't respond within time, kill it to simulate 998 * a crash. The failure will be detected and the service will 999 * be restarted automatically. Give the service a free pass if 1000 * somebody is initializing. There may be some weird dependencies 1001 * if another service is, for example, restarting at the same 1002 * time. 1003 */ 1004 if (rp->r_alive_tm < rp->r_check_tm) { 1005 if (now - rp->r_alive_tm > 2*period && 1006 rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) { 1007 struct rproc *rp2; 1008 int init_flag; 1009 if(rs_verbose) 1010 printf("RS: %s reported late\n", srv_to_string(rp)); 1011 init_flag = rp->r_flags & RS_INITIALIZING; 1012 rp->r_flags &= ~RS_INITIALIZING; 1013 rp2 = lookup_slot_by_flags(RS_INITIALIZING); 1014 rp->r_flags |= init_flag; 1015 if(rp2 != NULL && !SRV_IS_UPDATING(rp)) { 1016 /* Skip for now. */ 1017 if(rs_verbose) 1018 printf("RS: %s gets a free pass\n", 1019 srv_to_string(rp)); 1020 rp->r_alive_tm = now; 1021 rp->r_check_tm = now+1; 1022 continue; 1023 } 1024 rp->r_flags |= RS_NOPINGREPLY; 1025 crash_service(rp); /* simulate crash */ 1026 if(rp->r_flags & RS_INITIALIZING) { 1027 rp->r_init_err = EINTR; 1028 } 1029 } 1030 } 1031 1032 /* No answer pending. Check if a period expired since the last 1033 * check and, if so request the system service's status. 1034 */ 1035 else if (now - rp->r_check_tm > rp->r_period) { 1036 ipc_notify(rpub->endpoint); /* request status */ 1037 rp->r_check_tm = now; /* mark time */ 1038 } 1039 } 1040 } 1041 } 1042 1043 /* Reschedule a synchronous alarm for the next period. */ 1044 if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) 1045 panic("couldn't set alarm: %d", s); 1046 } 1047 1048 /*===========================================================================* 1049 * do_sigchld * 1050 *===========================================================================*/ 1051 void do_sigchld() 1052 { 1053 /* PM informed us that there are dead children to cleanup. Go get them. */ 1054 pid_t pid; 1055 int status; 1056 struct rproc *rp; 1057 struct rproc **rps; 1058 int i, nr_rps, found; 1059 1060 if(rs_verbose) 1061 printf("RS: got SIGCHLD signal, cleaning up dead children\n"); 1062 1063 while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) { 1064 rp = lookup_slot_by_pid(pid); 1065 if(rp != NULL) { 1066 1067 if(rs_verbose) 1068 printf("RS: %s exited via another signal manager\n", 1069 srv_to_string(rp)); 1070 1071 /* The slot is still there. This means RS is not the signal 1072 * manager assigned to the process. Ignore the event but 1073 * free slots for all the service instances and send a late 1074 * reply if necessary. 1075 */ 1076 found = 0; 1077 get_service_instances(rp, &rps, &nr_rps); 1078 for(i=0;i<nr_rps;i++) { 1079 if(SRV_IS_UPDATING(rps[i])) { 1080 rps[i]->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING); 1081 found = 1; 1082 } 1083 free_slot(rps[i]); 1084 } 1085 if(found) { 1086 rupdate_clear_upds(); 1087 } 1088 } 1089 } 1090 } 1091 1092 /*===========================================================================* 1093 * do_getsysinfo * 1094 *===========================================================================*/ 1095 int do_getsysinfo(m_ptr) 1096 message *m_ptr; 1097 { 1098 vir_bytes src_addr, dst_addr; 1099 int dst_proc; 1100 size_t size, len; 1101 int s; 1102 1103 /* Check if the call can be allowed. */ 1104 if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK) 1105 return s; 1106 1107 dst_proc = m_ptr->m_source; 1108 dst_addr = m_ptr->m_lsys_getsysinfo.where; 1109 size = m_ptr->m_lsys_getsysinfo.size; 1110 1111 switch(m_ptr->m_lsys_getsysinfo.what) { 1112 case SI_PROC_TAB: 1113 src_addr = (vir_bytes) rproc; 1114 len = sizeof(struct rproc) * NR_SYS_PROCS; 1115 break; 1116 case SI_PROCALL_TAB: 1117 /* Copy out both tables, one after the other. */ 1118 src_addr = (vir_bytes) rproc; 1119 len = sizeof(struct rproc) * NR_SYS_PROCS; 1120 if (len > size) 1121 return EINVAL; 1122 if ((s = sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)) != OK) 1123 return s; 1124 dst_addr += len; 1125 size -= len; 1126 /* FALLTHROUGH */ 1127 case SI_PROCPUB_TAB: 1128 src_addr = (vir_bytes) rprocpub; 1129 len = sizeof(struct rprocpub) * NR_SYS_PROCS; 1130 break; 1131 default: 1132 return(EINVAL); 1133 } 1134 1135 if (len != size) 1136 return(EINVAL); 1137 1138 return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len); 1139 } 1140 1141 /*===========================================================================* 1142 * do_lookup * 1143 *===========================================================================*/ 1144 int do_lookup(m_ptr) 1145 message *m_ptr; 1146 { 1147 static char namebuf[100]; 1148 int len, r; 1149 struct rproc *rrp; 1150 struct rprocpub *rrpub; 1151 1152 len = m_ptr->m_rs_req.name_len; 1153 1154 if(len < 2 || len >= sizeof(namebuf)) { 1155 printf("RS: len too weird (%d)\n", len); 1156 return EINVAL; 1157 } 1158 1159 if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name, 1160 SELF, (vir_bytes) namebuf, len)) != OK) { 1161 printf("RS: name copy failed\n"); 1162 return r; 1163 1164 } 1165 1166 namebuf[len] = '\0'; 1167 1168 rrp = lookup_slot_by_label(namebuf); 1169 if(!rrp) { 1170 return ESRCH; 1171 } 1172 rrpub = rrp->r_pub; 1173 m_ptr->m_rs_req.endpoint = rrpub->endpoint; 1174 1175 return OK; 1176 } 1177 1178 /*===========================================================================* 1179 * do_sysctl * 1180 *===========================================================================*/ 1181 int do_sysctl(message *m_ptr) 1182 { 1183 int request_type = m_ptr->m_rs_req.subtype; 1184 int r, allow_retries = 1; 1185 switch(request_type) { 1186 case RS_SYSCTL_SRV_STATUS: 1187 print_services_status(); 1188 break; 1189 case RS_SYSCTL_UPD_START: 1190 case RS_SYSCTL_UPD_RUN: 1191 r = start_update_prepare(allow_retries); 1192 print_update_status(); 1193 if(r != OK) { 1194 if(r == ESRCH) { 1195 /* We are done already. */ 1196 r = OK; 1197 } 1198 return r; 1199 } 1200 if(request_type == RS_SYSCTL_UPD_START) { 1201 return OK; 1202 } 1203 /* Send a reply when done. */ 1204 rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY; 1205 rupdate.last_rpupd->rp->r_caller = m_ptr->m_source; 1206 rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE; 1207 return EDONTREPLY; 1208 break; 1209 case RS_SYSCTL_UPD_STOP: 1210 r = abort_update_proc(EINTR); 1211 print_update_status(); 1212 return r; 1213 break; 1214 case RS_SYSCTL_UPD_STATUS: 1215 print_update_status(); 1216 break; 1217 default: 1218 printf("RS: bad sysctl type\n"); 1219 return EINVAL; 1220 break; 1221 } 1222 1223 return OK; 1224 } 1225 1226 /*===========================================================================* 1227 * do_fi * 1228 *===========================================================================*/ 1229 int do_fi(message *m_ptr) 1230 { 1231 struct rproc *rp; 1232 struct rprocpub *rpub; 1233 int s, r; 1234 char label[RS_MAX_LABEL_LEN]; 1235 1236 /* Copy label. */ 1237 s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 1238 m_ptr->m_rs_req.len, label, sizeof(label)); 1239 if(s != OK) { 1240 return s; 1241 } 1242 1243 /* Lookup slot by label. */ 1244 rp = lookup_slot_by_label(label); 1245 if(!rp) { 1246 if(rs_verbose) 1247 printf("RS: do_fi: service '%s' not found\n", label); 1248 return(ESRCH); 1249 } 1250 rpub = rp->r_pub; 1251 1252 /* Check if the call can be allowed. */ 1253 if((r = check_call_permission(m_ptr->m_source, RS_FI, rp)) != OK) 1254 return r; 1255 1256 /* Inject fault into the service as requested. */ 1257 s = fi_service(rp); 1258 1259 return s; 1260 } 1261 1262 /*===========================================================================* 1263 * check_request * 1264 *===========================================================================*/ 1265 static int check_request(struct rs_start *rs_start) 1266 { 1267 /* Verify scheduling parameters */ 1268 if (rs_start->rss_scheduler != KERNEL && 1269 (rs_start->rss_scheduler < 0 || 1270 rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) { 1271 printf("RS: check_request: invalid scheduler %d\n", 1272 rs_start->rss_scheduler); 1273 return EINVAL; 1274 } 1275 if (rs_start->rss_priority >= NR_SCHED_QUEUES) { 1276 printf("RS: check_request: priority %u out of range\n", 1277 rs_start->rss_priority); 1278 return EINVAL; 1279 } 1280 if (rs_start->rss_quantum <= 0) { 1281 printf("RS: check_request: quantum %u out of range\n", 1282 rs_start->rss_quantum); 1283 return EINVAL; 1284 } 1285 1286 if (rs_start->rss_cpu == RS_CPU_BSP) 1287 rs_start->rss_cpu = machine.bsp_id; 1288 else if (rs_start->rss_cpu == RS_CPU_DEFAULT) { 1289 /* keep the default value */ 1290 } else if (rs_start->rss_cpu < 0) 1291 return EINVAL; 1292 else if (rs_start->rss_cpu > machine.processors_count) { 1293 printf("RS: cpu number %d out of range 0-%d, using BSP\n", 1294 rs_start->rss_cpu, machine.processors_count); 1295 rs_start->rss_cpu = machine.bsp_id; 1296 } 1297 1298 /* Verify signal manager. */ 1299 if (rs_start->rss_sigmgr != SELF && 1300 (rs_start->rss_sigmgr < 0 || 1301 rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) { 1302 printf("RS: check_request: invalid signal manager %d\n", 1303 rs_start->rss_sigmgr); 1304 return EINVAL; 1305 } 1306 1307 return OK; 1308 } 1309 1310