1433d6423SLionel Sambuc /* 2433d6423SLionel Sambuc * Changes: 3433d6423SLionel Sambuc * Jan 22, 2010: Created (Cristiano Giuffrida) 4433d6423SLionel Sambuc */ 5433d6423SLionel Sambuc 6433d6423SLionel Sambuc #include "inc.h" 7433d6423SLionel Sambuc 8433d6423SLionel Sambuc #include "kernel/proc.h" 9433d6423SLionel Sambuc 10433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start); 11433d6423SLionel Sambuc 12433d6423SLionel Sambuc /*===========================================================================* 13433d6423SLionel Sambuc * do_up * 14433d6423SLionel Sambuc *===========================================================================*/ 15433d6423SLionel Sambuc int do_up(m_ptr) 16433d6423SLionel Sambuc message *m_ptr; /* request message pointer */ 17433d6423SLionel Sambuc { 18433d6423SLionel Sambuc /* A request was made to start a new system service. */ 19433d6423SLionel Sambuc struct rproc *rp; 20433d6423SLionel Sambuc struct rprocpub *rpub; 21433d6423SLionel Sambuc int r; 22433d6423SLionel Sambuc struct rs_start rs_start; 23433d6423SLionel Sambuc int noblock; 24433d6423SLionel Sambuc 25433d6423SLionel Sambuc /* Check if the call can be allowed. */ 26433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK) 27433d6423SLionel Sambuc return r; 28433d6423SLionel Sambuc 29433d6423SLionel Sambuc /* Allocate a new system service slot. */ 30433d6423SLionel Sambuc r = alloc_slot(&rp); 31433d6423SLionel Sambuc if(r != OK) { 32433d6423SLionel Sambuc printf("RS: do_up: unable to allocate a new slot: %d\n", r); 33433d6423SLionel Sambuc return r; 34433d6423SLionel Sambuc } 35433d6423SLionel Sambuc rpub = rp->r_pub; 36433d6423SLionel Sambuc 37433d6423SLionel Sambuc /* Copy the request structure. */ 38433d6423SLionel Sambuc r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 39433d6423SLionel Sambuc if (r != OK) { 40433d6423SLionel Sambuc return r; 41433d6423SLionel Sambuc } 42433d6423SLionel Sambuc r = check_request(&rs_start); 43433d6423SLionel Sambuc if (r != OK) { 44433d6423SLionel Sambuc return r; 45433d6423SLionel Sambuc } 46433d6423SLionel Sambuc noblock = (rs_start.rss_flags & RSS_NOBLOCK); 47433d6423SLionel Sambuc 48433d6423SLionel Sambuc /* Initialize the slot as requested. */ 49433d6423SLionel Sambuc r = init_slot(rp, &rs_start, m_ptr->m_source); 50433d6423SLionel Sambuc if(r != OK) { 51433d6423SLionel Sambuc printf("RS: do_up: unable to init the new slot: %d\n", r); 52433d6423SLionel Sambuc return r; 53433d6423SLionel Sambuc } 54433d6423SLionel Sambuc 55433d6423SLionel Sambuc /* Check for duplicates */ 56433d6423SLionel Sambuc if(lookup_slot_by_label(rpub->label)) { 57433d6423SLionel Sambuc printf("RS: service with the same label '%s' already exists\n", 58433d6423SLionel Sambuc rpub->label); 59433d6423SLionel Sambuc return EBUSY; 60433d6423SLionel Sambuc } 61433d6423SLionel Sambuc if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) { 62433d6423SLionel Sambuc printf("RS: service with the same device number %d already exists\n", 63433d6423SLionel Sambuc rpub->dev_nr); 64433d6423SLionel Sambuc return EBUSY; 65433d6423SLionel Sambuc } 66433d6423SLionel Sambuc 67433d6423SLionel Sambuc /* All information was gathered. Now try to start the system service. */ 68433d6423SLionel Sambuc r = start_service(rp); 69433d6423SLionel Sambuc if(r != OK) { 70433d6423SLionel Sambuc return r; 71433d6423SLionel Sambuc } 72433d6423SLionel Sambuc 73433d6423SLionel Sambuc /* Unblock the caller immediately if requested. */ 74433d6423SLionel Sambuc if(noblock) { 75433d6423SLionel Sambuc return OK; 76433d6423SLionel Sambuc } 77433d6423SLionel Sambuc 78433d6423SLionel Sambuc /* Late reply - send a reply when service completes initialization. */ 79433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 80433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 81433d6423SLionel Sambuc rp->r_caller_request = RS_UP; 82433d6423SLionel Sambuc 83433d6423SLionel Sambuc return EDONTREPLY; 84433d6423SLionel Sambuc } 85433d6423SLionel Sambuc 86433d6423SLionel Sambuc /*===========================================================================* 87433d6423SLionel Sambuc * do_down * 88433d6423SLionel Sambuc *===========================================================================*/ 89433d6423SLionel Sambuc int do_down(message *m_ptr) 90433d6423SLionel Sambuc { 91433d6423SLionel Sambuc register struct rproc *rp; 92433d6423SLionel Sambuc int s; 93433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 94433d6423SLionel Sambuc 95433d6423SLionel Sambuc /* Copy label. */ 96433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 97433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 98433d6423SLionel Sambuc if(s != OK) { 99433d6423SLionel Sambuc return s; 100433d6423SLionel Sambuc } 101433d6423SLionel Sambuc 102433d6423SLionel Sambuc /* Lookup slot by label. */ 103433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 104433d6423SLionel Sambuc if(!rp) { 105433d6423SLionel Sambuc if(rs_verbose) 106433d6423SLionel Sambuc printf("RS: do_down: service '%s' not found\n", label); 107433d6423SLionel Sambuc return(ESRCH); 108433d6423SLionel Sambuc } 109433d6423SLionel Sambuc 110433d6423SLionel Sambuc /* Check if the call can be allowed. */ 111433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK) 112433d6423SLionel Sambuc return s; 113433d6423SLionel Sambuc 114433d6423SLionel Sambuc /* Stop service. */ 115433d6423SLionel Sambuc if (rp->r_flags & RS_TERMINATED) { 116433d6423SLionel Sambuc /* A recovery script is requesting us to bring down the service. 117433d6423SLionel Sambuc * The service is already gone, simply perform cleanup. 118433d6423SLionel Sambuc */ 119433d6423SLionel Sambuc if(rs_verbose) 120433d6423SLionel Sambuc printf("RS: recovery script performs service down...\n"); 121433d6423SLionel Sambuc unpublish_service(rp); 122433d6423SLionel Sambuc cleanup_service(rp); 123433d6423SLionel Sambuc return(OK); 124433d6423SLionel Sambuc } 125433d6423SLionel Sambuc stop_service(rp,RS_EXITING); 126433d6423SLionel Sambuc 127433d6423SLionel Sambuc /* Late reply - send a reply when service dies. */ 128433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 129433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 130433d6423SLionel Sambuc rp->r_caller_request = RS_DOWN; 131433d6423SLionel Sambuc 132433d6423SLionel Sambuc return EDONTREPLY; 133433d6423SLionel Sambuc } 134433d6423SLionel Sambuc 135433d6423SLionel Sambuc /*===========================================================================* 136433d6423SLionel Sambuc * do_restart * 137433d6423SLionel Sambuc *===========================================================================*/ 138433d6423SLionel Sambuc int do_restart(message *m_ptr) 139433d6423SLionel Sambuc { 140433d6423SLionel Sambuc struct rproc *rp; 141433d6423SLionel Sambuc int s, r; 142433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 143433d6423SLionel Sambuc char script[MAX_SCRIPT_LEN]; 144433d6423SLionel Sambuc 145433d6423SLionel Sambuc /* Copy label. */ 146433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 147433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 148433d6423SLionel Sambuc if(s != OK) { 149433d6423SLionel Sambuc return s; 150433d6423SLionel Sambuc } 151433d6423SLionel Sambuc 152433d6423SLionel Sambuc /* Lookup slot by label. */ 153433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 154433d6423SLionel Sambuc if(!rp) { 155433d6423SLionel Sambuc if(rs_verbose) 156433d6423SLionel Sambuc printf("RS: do_restart: service '%s' not found\n", label); 157433d6423SLionel Sambuc return(ESRCH); 158433d6423SLionel Sambuc } 159433d6423SLionel Sambuc 160433d6423SLionel Sambuc /* Check if the call can be allowed. */ 161433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK) 162433d6423SLionel Sambuc return r; 163433d6423SLionel Sambuc 164433d6423SLionel Sambuc /* We can only be asked to restart a service from a recovery script. */ 165433d6423SLionel Sambuc if (! (rp->r_flags & RS_TERMINATED) ) { 166433d6423SLionel Sambuc if(rs_verbose) 167433d6423SLionel Sambuc printf("RS: %s is still running\n", srv_to_string(rp)); 168433d6423SLionel Sambuc return EBUSY; 169433d6423SLionel Sambuc } 170433d6423SLionel Sambuc 171433d6423SLionel Sambuc if(rs_verbose) 172433d6423SLionel Sambuc printf("RS: recovery script performs service restart...\n"); 173433d6423SLionel Sambuc 174433d6423SLionel Sambuc /* Restart the service, but make sure we don't call the script again. */ 175433d6423SLionel Sambuc strcpy(script, rp->r_script); 176433d6423SLionel Sambuc rp->r_script[0] = '\0'; 177433d6423SLionel Sambuc restart_service(rp); 178433d6423SLionel Sambuc strcpy(rp->r_script, script); 179433d6423SLionel Sambuc 180433d6423SLionel Sambuc return OK; 181433d6423SLionel Sambuc } 182433d6423SLionel Sambuc 183433d6423SLionel Sambuc /*===========================================================================* 184433d6423SLionel Sambuc * do_clone * 185433d6423SLionel Sambuc *===========================================================================*/ 186433d6423SLionel Sambuc int do_clone(message *m_ptr) 187433d6423SLionel Sambuc { 188433d6423SLionel Sambuc struct rproc *rp; 189433d6423SLionel Sambuc struct rprocpub *rpub; 190433d6423SLionel Sambuc int s, r; 191433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 192433d6423SLionel Sambuc 193433d6423SLionel Sambuc /* Copy label. */ 194433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 195433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 196433d6423SLionel Sambuc if(s != OK) { 197433d6423SLionel Sambuc return s; 198433d6423SLionel Sambuc } 199433d6423SLionel Sambuc 200433d6423SLionel Sambuc /* Lookup slot by label. */ 201433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 202433d6423SLionel Sambuc if(!rp) { 203433d6423SLionel Sambuc if(rs_verbose) 204433d6423SLionel Sambuc printf("RS: do_clone: service '%s' not found\n", label); 205433d6423SLionel Sambuc return(ESRCH); 206433d6423SLionel Sambuc } 207433d6423SLionel Sambuc rpub = rp->r_pub; 208433d6423SLionel Sambuc 209433d6423SLionel Sambuc /* Check if the call can be allowed. */ 210433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK) 211433d6423SLionel Sambuc return r; 212433d6423SLionel Sambuc 213433d6423SLionel Sambuc /* Don't clone if a replica is already available. */ 214433d6423SLionel Sambuc if(rp->r_next_rp) { 215433d6423SLionel Sambuc return EEXIST; 216433d6423SLionel Sambuc } 217433d6423SLionel Sambuc 218433d6423SLionel Sambuc /* Clone the service as requested. */ 219433d6423SLionel Sambuc rpub->sys_flags |= SF_USE_REPL; 220433d6423SLionel Sambuc if ((r = clone_service(rp, RST_SYS_PROC)) != OK) { 221433d6423SLionel Sambuc rpub->sys_flags &= ~SF_USE_REPL; 222433d6423SLionel Sambuc return r; 223433d6423SLionel Sambuc } 224433d6423SLionel Sambuc 225433d6423SLionel Sambuc return OK; 226433d6423SLionel Sambuc } 227433d6423SLionel Sambuc 228433d6423SLionel Sambuc /*===========================================================================* 229433d6423SLionel Sambuc * do_edit * 230433d6423SLionel Sambuc *===========================================================================*/ 231433d6423SLionel Sambuc int do_edit(message *m_ptr) 232433d6423SLionel Sambuc { 233433d6423SLionel Sambuc struct rproc *rp; 234433d6423SLionel Sambuc struct rprocpub *rpub; 235433d6423SLionel Sambuc struct rs_start rs_start; 236433d6423SLionel Sambuc int r; 237433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 238433d6423SLionel Sambuc 239433d6423SLionel Sambuc /* Copy the request structure. */ 240433d6423SLionel Sambuc r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 241433d6423SLionel Sambuc if (r != OK) { 242433d6423SLionel Sambuc return r; 243433d6423SLionel Sambuc } 244433d6423SLionel Sambuc 245433d6423SLionel Sambuc /* Copy label. */ 246433d6423SLionel Sambuc r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 247433d6423SLionel Sambuc rs_start.rss_label.l_len, label, sizeof(label)); 248433d6423SLionel Sambuc if(r != OK) { 249433d6423SLionel Sambuc return r; 250433d6423SLionel Sambuc } 251433d6423SLionel Sambuc 252433d6423SLionel Sambuc /* Lookup slot by label. */ 253433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 254433d6423SLionel Sambuc if(!rp) { 255433d6423SLionel Sambuc if(rs_verbose) 256433d6423SLionel Sambuc printf("RS: do_edit: service '%s' not found\n", label); 257433d6423SLionel Sambuc return ESRCH; 258433d6423SLionel Sambuc } 259433d6423SLionel Sambuc rpub = rp->r_pub; 260433d6423SLionel Sambuc 261433d6423SLionel Sambuc /* Check if the call can be allowed. */ 262433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK) 263433d6423SLionel Sambuc return r; 264433d6423SLionel Sambuc 265433d6423SLionel Sambuc if(rs_verbose) 266433d6423SLionel Sambuc printf("RS: %s edits settings\n", srv_to_string(rp)); 267433d6423SLionel Sambuc 268433d6423SLionel Sambuc /* Synch the privilege structure with the kernel. */ 269433d6423SLionel Sambuc if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) { 270433d6423SLionel Sambuc printf("RS: do_edit: unable to synch privilege structure: %d\n", r); 271433d6423SLionel Sambuc return r; 272433d6423SLionel Sambuc } 273433d6423SLionel Sambuc 274433d6423SLionel Sambuc /* Tell scheduler this process is finished */ 275433d6423SLionel Sambuc if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) { 276433d6423SLionel Sambuc printf("RS: do_edit: scheduler won't give up process: %d\n", r); 277433d6423SLionel Sambuc return r; 278433d6423SLionel Sambuc } 279433d6423SLionel Sambuc 280433d6423SLionel Sambuc /* Edit the slot as requested. */ 281433d6423SLionel Sambuc if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) { 282433d6423SLionel Sambuc printf("RS: do_edit: unable to edit the existing slot: %d\n", r); 283433d6423SLionel Sambuc return r; 284433d6423SLionel Sambuc } 285433d6423SLionel Sambuc 286433d6423SLionel Sambuc /* Update privilege structure. */ 287433d6423SLionel Sambuc r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv); 288433d6423SLionel Sambuc if(r != OK) { 289433d6423SLionel Sambuc printf("RS: do_edit: unable to update privilege structure: %d\n", r); 290433d6423SLionel Sambuc return r; 291433d6423SLionel Sambuc } 292433d6423SLionel Sambuc 293433d6423SLionel Sambuc /* Update VM calls. */ 294433d6423SLionel Sambuc if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0], 295433d6423SLionel Sambuc !!(rp->r_priv.s_flags & SYS_PROC))) != OK) { 296433d6423SLionel Sambuc printf("RS: do_edit: failed: %d\n", r); 297433d6423SLionel Sambuc return r; 298433d6423SLionel Sambuc } 299433d6423SLionel Sambuc 300433d6423SLionel Sambuc /* Reinitialize scheduling. */ 301433d6423SLionel Sambuc if ((r = sched_init_proc(rp)) != OK) { 302433d6423SLionel Sambuc printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r); 303433d6423SLionel Sambuc return r; 304433d6423SLionel Sambuc } 305433d6423SLionel Sambuc 306433d6423SLionel Sambuc /* Cleanup old replicas and create a new one, if necessary. */ 307433d6423SLionel Sambuc if(rpub->sys_flags & SF_USE_REPL) { 308433d6423SLionel Sambuc if(rp->r_next_rp) { 309433d6423SLionel Sambuc cleanup_service(rp->r_next_rp); 310433d6423SLionel Sambuc rp->r_next_rp = NULL; 311433d6423SLionel Sambuc } 312433d6423SLionel Sambuc if ((r = clone_service(rp, RST_SYS_PROC)) != OK) { 313433d6423SLionel Sambuc printf("RS: warning: unable to clone %s\n", srv_to_string(rp)); 314433d6423SLionel Sambuc } 315433d6423SLionel Sambuc } 316433d6423SLionel Sambuc 317433d6423SLionel Sambuc return OK; 318433d6423SLionel Sambuc } 319433d6423SLionel Sambuc 320433d6423SLionel Sambuc /*===========================================================================* 321433d6423SLionel Sambuc * do_refresh * 322433d6423SLionel Sambuc *===========================================================================*/ 323433d6423SLionel Sambuc int do_refresh(message *m_ptr) 324433d6423SLionel Sambuc { 325433d6423SLionel Sambuc register struct rproc *rp; 326433d6423SLionel Sambuc int s; 327433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 328433d6423SLionel Sambuc 329433d6423SLionel Sambuc /* Copy label. */ 330433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 331433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 332433d6423SLionel Sambuc if(s != OK) { 333433d6423SLionel Sambuc return s; 334433d6423SLionel Sambuc } 335433d6423SLionel Sambuc 336433d6423SLionel Sambuc /* Lookup slot by label. */ 337433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 338433d6423SLionel Sambuc if(!rp) { 339433d6423SLionel Sambuc if(rs_verbose) 340433d6423SLionel Sambuc printf("RS: do_refresh: service '%s' not found\n", label); 341433d6423SLionel Sambuc return(ESRCH); 342433d6423SLionel Sambuc } 343433d6423SLionel Sambuc 344433d6423SLionel Sambuc /* Check if the call can be allowed. */ 345433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK) 346433d6423SLionel Sambuc return s; 347433d6423SLionel Sambuc 348433d6423SLionel Sambuc /* Refresh service. */ 349433d6423SLionel Sambuc if(rs_verbose) 350433d6423SLionel Sambuc printf("RS: %s refreshing\n", srv_to_string(rp)); 351433d6423SLionel Sambuc stop_service(rp,RS_REFRESHING); 352433d6423SLionel Sambuc 353433d6423SLionel Sambuc return OK; 354433d6423SLionel Sambuc } 355433d6423SLionel Sambuc 356433d6423SLionel Sambuc /*===========================================================================* 357433d6423SLionel Sambuc * do_shutdown * 358433d6423SLionel Sambuc *===========================================================================*/ 359433d6423SLionel Sambuc int do_shutdown(message *m_ptr) 360433d6423SLionel Sambuc { 361433d6423SLionel Sambuc int slot_nr; 362433d6423SLionel Sambuc struct rproc *rp; 363433d6423SLionel Sambuc int r; 364433d6423SLionel Sambuc 365433d6423SLionel Sambuc /* Check if the call can be allowed. */ 366433d6423SLionel Sambuc if (m_ptr != NULL) { 367433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK) 368433d6423SLionel Sambuc return r; 369433d6423SLionel Sambuc } 370433d6423SLionel Sambuc 371433d6423SLionel Sambuc if(rs_verbose) 372433d6423SLionel Sambuc printf("RS: shutting down...\n"); 373433d6423SLionel Sambuc 374433d6423SLionel Sambuc /* Set flag to tell RS we are shutting down. */ 375433d6423SLionel Sambuc shutting_down = TRUE; 376433d6423SLionel Sambuc 377433d6423SLionel Sambuc /* Don't restart dead services. */ 378433d6423SLionel Sambuc for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { 379433d6423SLionel Sambuc rp = &rproc[slot_nr]; 380433d6423SLionel Sambuc if (rp->r_flags & RS_IN_USE) { 381433d6423SLionel Sambuc rp->r_flags |= RS_EXITING; 382433d6423SLionel Sambuc } 383433d6423SLionel Sambuc } 384433d6423SLionel Sambuc return(OK); 385433d6423SLionel Sambuc } 386433d6423SLionel Sambuc 387433d6423SLionel Sambuc /*===========================================================================* 388433d6423SLionel Sambuc * do_init_ready * 389433d6423SLionel Sambuc *===========================================================================*/ 390433d6423SLionel Sambuc int do_init_ready(message *m_ptr) 391433d6423SLionel Sambuc { 392433d6423SLionel Sambuc int who_p; 393433d6423SLionel Sambuc message m; 394433d6423SLionel Sambuc struct rproc *rp; 395433d6423SLionel Sambuc struct rprocpub *rpub; 396433d6423SLionel Sambuc int result, is_rs; 397433d6423SLionel Sambuc int r; 398433d6423SLionel Sambuc 399433d6423SLionel Sambuc is_rs = (m_ptr->m_source == RS_PROC_NR); 400433d6423SLionel Sambuc who_p = _ENDPOINT_P(m_ptr->m_source); 401433d6423SLionel Sambuc result = m_ptr->m_rs_init.result; 402433d6423SLionel Sambuc 403433d6423SLionel Sambuc /* Check for RS failing initialization first. */ 404433d6423SLionel Sambuc if(is_rs && result != OK) { 405433d6423SLionel Sambuc return result; 406433d6423SLionel Sambuc } 407433d6423SLionel Sambuc 408433d6423SLionel Sambuc rp = rproc_ptr[who_p]; 409433d6423SLionel Sambuc rpub = rp->r_pub; 410433d6423SLionel Sambuc 411433d6423SLionel Sambuc /* Make sure the originating service was requested to initialize. */ 412433d6423SLionel Sambuc if(! (rp->r_flags & RS_INITIALIZING) ) { 413433d6423SLionel Sambuc if(rs_verbose) 414433d6423SLionel Sambuc printf("RS: do_init_ready: got unexpected init ready msg from %d\n", 415433d6423SLionel Sambuc m_ptr->m_source); 416433d6423SLionel Sambuc return EINVAL; 417433d6423SLionel Sambuc } 418433d6423SLionel Sambuc 419433d6423SLionel Sambuc /* Check if something went wrong and the service failed to init. 420433d6423SLionel Sambuc * In that case, kill the service. 421433d6423SLionel Sambuc */ 422433d6423SLionel Sambuc if(result != OK) { 423433d6423SLionel Sambuc if(rs_verbose) 424433d6423SLionel Sambuc printf("RS: %s initialization error: %s\n", srv_to_string(rp), 425433d6423SLionel Sambuc init_strerror(result)); 426433d6423SLionel Sambuc if (result == ERESTART) 427433d6423SLionel Sambuc rp->r_flags |= RS_REINCARNATE; 428433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 429433d6423SLionel Sambuc return EDONTREPLY; 430433d6423SLionel Sambuc } 431433d6423SLionel Sambuc 432433d6423SLionel Sambuc /* Mark the slot as no longer initializing. */ 433433d6423SLionel Sambuc rp->r_flags &= ~RS_INITIALIZING; 434433d6423SLionel Sambuc rp->r_check_tm = 0; 435433d6423SLionel Sambuc getticks(&rp->r_alive_tm); 436433d6423SLionel Sambuc 437433d6423SLionel Sambuc /* Reply and unblock the service before doing anything else. */ 438433d6423SLionel Sambuc m.m_type = OK; 439433d6423SLionel Sambuc reply(rpub->endpoint, rp, &m); 440433d6423SLionel Sambuc 441433d6423SLionel Sambuc /* See if a late reply has to be sent. */ 442433d6423SLionel Sambuc late_reply(rp, OK); 443433d6423SLionel Sambuc 444433d6423SLionel Sambuc if(rs_verbose) 445433d6423SLionel Sambuc printf("RS: %s initialized\n", srv_to_string(rp)); 446433d6423SLionel Sambuc 447433d6423SLionel Sambuc /* If the service has completed initialization after a live 448433d6423SLionel Sambuc * update, end the update now. 449433d6423SLionel Sambuc */ 450433d6423SLionel Sambuc if(rp->r_flags & RS_UPDATING) { 451433d6423SLionel Sambuc printf("RS: update succeeded\n"); 452433d6423SLionel Sambuc end_update(OK, RS_DONTREPLY); 453433d6423SLionel Sambuc } 454433d6423SLionel Sambuc 455433d6423SLionel Sambuc /* If the service has completed initialization after a crash 456433d6423SLionel Sambuc * make the new instance active and cleanup the old replica. 457433d6423SLionel Sambuc */ 458433d6423SLionel Sambuc if(rp->r_prev_rp) { 459433d6423SLionel Sambuc cleanup_service(rp->r_prev_rp); 460433d6423SLionel Sambuc rp->r_prev_rp = NULL; 461433d6423SLionel Sambuc rp->r_restarts += 1; 462433d6423SLionel Sambuc 463433d6423SLionel Sambuc if(rs_verbose) 464433d6423SLionel Sambuc printf("RS: %s completed restart\n", srv_to_string(rp)); 465433d6423SLionel Sambuc } 466433d6423SLionel Sambuc 467433d6423SLionel Sambuc /* If we must keep a replica of this system service, create it now. */ 468433d6423SLionel Sambuc if(rpub->sys_flags & SF_USE_REPL) { 469433d6423SLionel Sambuc if ((r = clone_service(rp, RST_SYS_PROC)) != OK) { 470433d6423SLionel Sambuc printf("RS: warning: unable to clone %s\n", srv_to_string(rp)); 471433d6423SLionel Sambuc } 472433d6423SLionel Sambuc } 473433d6423SLionel Sambuc 474433d6423SLionel Sambuc return is_rs ? OK : EDONTREPLY; /* return what the caller expects */ 475433d6423SLionel Sambuc } 476433d6423SLionel Sambuc 477433d6423SLionel Sambuc /*===========================================================================* 478433d6423SLionel Sambuc * do_update * 479433d6423SLionel Sambuc *===========================================================================*/ 480433d6423SLionel Sambuc int do_update(message *m_ptr) 481433d6423SLionel Sambuc { 482433d6423SLionel Sambuc struct rproc *rp; 483433d6423SLionel Sambuc struct rproc *new_rp; 484433d6423SLionel Sambuc struct rprocpub *rpub; 485433d6423SLionel Sambuc struct rs_start rs_start; 486433d6423SLionel Sambuc int noblock, do_self_update; 487433d6423SLionel Sambuc int s; 488433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 489433d6423SLionel Sambuc int lu_state; 490433d6423SLionel Sambuc int prepare_maxtime; 491433d6423SLionel Sambuc 492433d6423SLionel Sambuc /* Copy the request structure. */ 493433d6423SLionel Sambuc s = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 494433d6423SLionel Sambuc if (s != OK) { 495433d6423SLionel Sambuc return s; 496433d6423SLionel Sambuc } 497433d6423SLionel Sambuc noblock = (rs_start.rss_flags & RSS_NOBLOCK); 498433d6423SLionel Sambuc do_self_update = (rs_start.rss_flags & RSS_SELF_LU); 499433d6423SLionel Sambuc s = check_request(&rs_start); 500433d6423SLionel Sambuc if (s != OK) { 501433d6423SLionel Sambuc return s; 502433d6423SLionel Sambuc } 503433d6423SLionel Sambuc 504433d6423SLionel Sambuc /* Copy label. */ 505433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 506433d6423SLionel Sambuc rs_start.rss_label.l_len, label, sizeof(label)); 507433d6423SLionel Sambuc if(s != OK) { 508433d6423SLionel Sambuc return s; 509433d6423SLionel Sambuc } 510433d6423SLionel Sambuc 511433d6423SLionel Sambuc /* Lookup slot by label. */ 512433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 513433d6423SLionel Sambuc if(!rp) { 514433d6423SLionel Sambuc if(rs_verbose) 515433d6423SLionel Sambuc printf("RS: do_update: service '%s' not found\n", label); 516433d6423SLionel Sambuc return ESRCH; 517433d6423SLionel Sambuc } 518433d6423SLionel Sambuc rpub = rp->r_pub; 519433d6423SLionel Sambuc 520433d6423SLionel Sambuc /* Check if the call can be allowed. */ 521433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK) 522433d6423SLionel Sambuc return s; 523433d6423SLionel Sambuc 524433d6423SLionel Sambuc /* Retrieve live update state. */ 525433d6423SLionel Sambuc lu_state = m_ptr->m_rs_update.state; 526433d6423SLionel Sambuc if(lu_state == SEF_LU_STATE_NULL) { 527433d6423SLionel Sambuc return(EINVAL); 528433d6423SLionel Sambuc } 529433d6423SLionel Sambuc 530433d6423SLionel Sambuc /* Retrieve prepare max time. */ 531433d6423SLionel Sambuc prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime; 532433d6423SLionel Sambuc if(prepare_maxtime) { 533433d6423SLionel Sambuc if(prepare_maxtime < 0 || prepare_maxtime > RS_MAX_PREPARE_MAXTIME) { 534433d6423SLionel Sambuc return(EINVAL); 535433d6423SLionel Sambuc } 536433d6423SLionel Sambuc } 537433d6423SLionel Sambuc else { 538433d6423SLionel Sambuc prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME; 539433d6423SLionel Sambuc } 540433d6423SLionel Sambuc 541433d6423SLionel Sambuc /* Make sure we are not already updating. */ 542433d6423SLionel Sambuc if(rupdate.flags & RS_UPDATING) { 543433d6423SLionel Sambuc if(rs_verbose) 544433d6423SLionel Sambuc printf("RS: do_update: an update is already in progress\n"); 545433d6423SLionel Sambuc return EBUSY; 546433d6423SLionel Sambuc } 547433d6423SLionel Sambuc 548433d6423SLionel Sambuc /* A self update live updates a service instance into a replica, a regular 549433d6423SLionel Sambuc * update live updates a service instance into a new version, as specified 550433d6423SLionel Sambuc * by the given binary. 551433d6423SLionel Sambuc */ 552433d6423SLionel Sambuc if(do_self_update) { 553433d6423SLionel Sambuc if(rs_verbose) 554433d6423SLionel Sambuc printf("RS: %s performs self update\n", srv_to_string(rp)); 555433d6423SLionel Sambuc 556433d6423SLionel Sambuc /* Clone the system service and use the replica as the new version. */ 557433d6423SLionel Sambuc s = clone_service(rp, LU_SYS_PROC); 558433d6423SLionel Sambuc if(s != OK) { 559433d6423SLionel Sambuc printf("RS: do_update: unable to clone service: %d\n", s); 560433d6423SLionel Sambuc return s; 561433d6423SLionel Sambuc } 562433d6423SLionel Sambuc } 563433d6423SLionel Sambuc else { 564433d6423SLionel Sambuc if(rs_verbose) 565433d6423SLionel Sambuc printf("RS: %s performs regular update\n", srv_to_string(rp)); 566433d6423SLionel Sambuc 567433d6423SLionel Sambuc /* Allocate a system service slot for the new version. */ 568433d6423SLionel Sambuc s = alloc_slot(&new_rp); 569433d6423SLionel Sambuc if(s != OK) { 570433d6423SLionel Sambuc printf("RS: do_update: unable to allocate a new slot: %d\n", s); 571433d6423SLionel Sambuc return s; 572433d6423SLionel Sambuc } 573433d6423SLionel Sambuc 574433d6423SLionel Sambuc /* Initialize the slot as requested. */ 575433d6423SLionel Sambuc s = init_slot(new_rp, &rs_start, m_ptr->m_source); 576433d6423SLionel Sambuc if(s != OK) { 577433d6423SLionel Sambuc printf("RS: do_update: unable to init the new slot: %d\n", s); 578433d6423SLionel Sambuc return s; 579433d6423SLionel Sambuc } 580433d6423SLionel Sambuc 581433d6423SLionel Sambuc /* Let the new version inherit defaults from the old one. */ 582433d6423SLionel Sambuc inherit_service_defaults(rp, new_rp); 583433d6423SLionel Sambuc 584433d6423SLionel Sambuc /* Link the two versions. */ 585433d6423SLionel Sambuc rp->r_new_rp = new_rp; 586433d6423SLionel Sambuc new_rp->r_old_rp = rp; 587433d6423SLionel Sambuc 588433d6423SLionel Sambuc /* Create new version of the service but don't let it run. */ 589433d6423SLionel Sambuc new_rp->r_priv.s_flags |= LU_SYS_PROC; 590433d6423SLionel Sambuc s = create_service(new_rp); 591433d6423SLionel Sambuc if(s != OK) { 592433d6423SLionel Sambuc printf("RS: do_update: unable to create a new service: %d\n", s); 593433d6423SLionel Sambuc return s; 594433d6423SLionel Sambuc } 595433d6423SLionel Sambuc } 596433d6423SLionel Sambuc 597433d6423SLionel Sambuc /* Mark both versions as updating. */ 598433d6423SLionel Sambuc rp->r_flags |= RS_UPDATING; 599433d6423SLionel Sambuc rp->r_new_rp->r_flags |= RS_UPDATING; 600433d6423SLionel Sambuc rupdate.flags |= RS_UPDATING; 601433d6423SLionel Sambuc getticks(&rupdate.prepare_tm); 602433d6423SLionel Sambuc rupdate.prepare_maxtime = prepare_maxtime; 603433d6423SLionel Sambuc rupdate.rp = rp; 604433d6423SLionel Sambuc 605433d6423SLionel Sambuc if(rs_verbose) 606433d6423SLionel Sambuc printf("RS: %s updating\n", srv_to_string(rp)); 607433d6423SLionel Sambuc 608433d6423SLionel Sambuc /* If RS is updating, set up signal managers for the new instance. 609433d6423SLionel Sambuc * The current RS instance must be made the backup signal manager to 610433d6423SLionel Sambuc * support rollback in case of a crash during initialization. 611433d6423SLionel Sambuc */ 612433d6423SLionel Sambuc if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 613433d6423SLionel Sambuc new_rp = rp->r_new_rp; 614433d6423SLionel Sambuc 615433d6423SLionel Sambuc s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint); 616433d6423SLionel Sambuc if(s != OK) { 617433d6423SLionel Sambuc cleanup_service(new_rp); 618433d6423SLionel Sambuc return s; 619433d6423SLionel Sambuc } 620433d6423SLionel Sambuc } 621433d6423SLionel Sambuc 622433d6423SLionel Sambuc if(noblock) { 623433d6423SLionel Sambuc /* Unblock the caller immediately if requested. */ 624433d6423SLionel Sambuc m_ptr->m_type = OK; 625433d6423SLionel Sambuc reply(m_ptr->m_source, NULL, m_ptr); 626433d6423SLionel Sambuc } 627433d6423SLionel Sambuc else { 628433d6423SLionel Sambuc /* Send a reply when the new version completes initialization. */ 629433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 630433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 631433d6423SLionel Sambuc rp->r_caller_request = RS_UPDATE; 632433d6423SLionel Sambuc } 633433d6423SLionel Sambuc 634433d6423SLionel Sambuc /* Request to update. */ 635433d6423SLionel Sambuc m_ptr->m_type = RS_LU_PREPARE; 636433d6423SLionel Sambuc if(rpub->endpoint == RS_PROC_NR) { 637433d6423SLionel Sambuc /* RS can process the request directly. */ 638433d6423SLionel Sambuc do_sef_lu_request(m_ptr); 639433d6423SLionel Sambuc } 640433d6423SLionel Sambuc else { 641433d6423SLionel Sambuc /* Send request message to the system service. */ 642433d6423SLionel Sambuc asynsend3(rpub->endpoint, m_ptr, AMF_NOREPLY); 643433d6423SLionel Sambuc } 644433d6423SLionel Sambuc 645433d6423SLionel Sambuc return EDONTREPLY; 646433d6423SLionel Sambuc } 647433d6423SLionel Sambuc 648433d6423SLionel Sambuc /*===========================================================================* 649433d6423SLionel Sambuc * do_upd_ready * 650433d6423SLionel Sambuc *===========================================================================*/ 651433d6423SLionel Sambuc int do_upd_ready(message *m_ptr) 652433d6423SLionel Sambuc { 653433d6423SLionel Sambuc struct rproc *rp, *old_rp, *new_rp; 654433d6423SLionel Sambuc int who_p; 655433d6423SLionel Sambuc int result; 656433d6423SLionel Sambuc int is_rs; 657433d6423SLionel Sambuc int r; 658433d6423SLionel Sambuc 659433d6423SLionel Sambuc who_p = _ENDPOINT_P(m_ptr->m_source); 660433d6423SLionel Sambuc rp = rproc_ptr[who_p]; 661433d6423SLionel Sambuc result = m_ptr->m_rs_update.result; 662433d6423SLionel Sambuc is_rs = (m_ptr->m_source == RS_PROC_NR); 663433d6423SLionel Sambuc 664433d6423SLionel Sambuc /* Make sure the originating service was requested to prepare for update. */ 665433d6423SLionel Sambuc if(rp != rupdate.rp) { 666433d6423SLionel Sambuc if(rs_verbose) 667433d6423SLionel Sambuc printf("RS: do_upd_ready: got unexpected update ready msg from %d\n", 668433d6423SLionel Sambuc m_ptr->m_source); 669433d6423SLionel Sambuc return EINVAL; 670433d6423SLionel Sambuc } 671433d6423SLionel Sambuc 672433d6423SLionel Sambuc /* Check if something went wrong and the service failed to prepare 673433d6423SLionel Sambuc * for the update. In that case, end the update process. The old version will 674433d6423SLionel Sambuc * be replied to and continue executing. 675433d6423SLionel Sambuc */ 676433d6423SLionel Sambuc if(result != OK) { 677433d6423SLionel Sambuc end_update(result, RS_REPLY); 678433d6423SLionel Sambuc 679433d6423SLionel Sambuc printf("RS: update failed: %s\n", lu_strerror(result)); 680433d6423SLionel Sambuc return is_rs ? result : EDONTREPLY; /* return what the caller expects */ 681433d6423SLionel Sambuc } 682433d6423SLionel Sambuc 683433d6423SLionel Sambuc old_rp = rp; 684433d6423SLionel Sambuc new_rp = rp->r_new_rp; 685433d6423SLionel Sambuc 686433d6423SLionel Sambuc /* If RS itself is updating, yield control to the new version immediately. */ 687433d6423SLionel Sambuc if(is_rs) { 688433d6423SLionel Sambuc r = init_service(new_rp, SEF_INIT_LU); 689433d6423SLionel Sambuc if(r != OK) { 690433d6423SLionel Sambuc panic("unable to initialize the new RS instance: %d", r); 691433d6423SLionel Sambuc } 692433d6423SLionel Sambuc r = sys_privctl(new_rp->r_pub->endpoint, SYS_PRIV_YIELD, NULL); 693433d6423SLionel Sambuc if(r != OK) { 694433d6423SLionel Sambuc panic("unable to yield control to the new RS instance: %d", r); 695433d6423SLionel Sambuc } 696433d6423SLionel Sambuc /* If we get this far, the new version failed to initialize. Rollback. */ 697433d6423SLionel Sambuc r = srv_update(RS_PROC_NR, new_rp->r_pub->endpoint); 698433d6423SLionel Sambuc assert(r == OK); /* can't fail */ 699433d6423SLionel Sambuc end_update(ERESTART, RS_REPLY); 700433d6423SLionel Sambuc return ERESTART; 701433d6423SLionel Sambuc } 702433d6423SLionel Sambuc 703433d6423SLionel Sambuc /* Perform the update. */ 704433d6423SLionel Sambuc r = update_service(&old_rp, &new_rp, RS_SWAP); 705433d6423SLionel Sambuc if(r != OK) { 706433d6423SLionel Sambuc end_update(r, RS_REPLY); 707433d6423SLionel Sambuc printf("RS: update failed: error %d\n", r); 708433d6423SLionel Sambuc return EDONTREPLY; 709433d6423SLionel Sambuc } 710433d6423SLionel Sambuc 711433d6423SLionel Sambuc /* Let the new version run. */ 712433d6423SLionel Sambuc r = run_service(new_rp, SEF_INIT_LU); 713433d6423SLionel Sambuc if(r != OK) { 714433d6423SLionel Sambuc /* Something went wrong. Rollback. */ 715433d6423SLionel Sambuc r = update_service(&new_rp, &old_rp, RS_SWAP); 716433d6423SLionel Sambuc assert(r == OK); /* can't fail */ 717433d6423SLionel Sambuc end_update(r, RS_REPLY); 718433d6423SLionel Sambuc printf("RS: update failed: error %d\n", r); 719433d6423SLionel Sambuc return EDONTREPLY; 720433d6423SLionel Sambuc } 721433d6423SLionel Sambuc 722433d6423SLionel Sambuc return EDONTREPLY; 723433d6423SLionel Sambuc } 724433d6423SLionel Sambuc 725433d6423SLionel Sambuc /*===========================================================================* 726433d6423SLionel Sambuc * do_period * 727433d6423SLionel Sambuc *===========================================================================*/ 728433d6423SLionel Sambuc void do_period(m_ptr) 729433d6423SLionel Sambuc message *m_ptr; 730433d6423SLionel Sambuc { 731433d6423SLionel Sambuc register struct rproc *rp; 732433d6423SLionel Sambuc register struct rprocpub *rpub; 733433d6423SLionel Sambuc clock_t now = m_ptr->m_notify.timestamp; 734433d6423SLionel Sambuc int s; 735433d6423SLionel Sambuc long period; 736433d6423SLionel Sambuc 737433d6423SLionel Sambuc /* If an update is in progress, check its status. */ 738433d6423SLionel Sambuc if(rupdate.flags & RS_UPDATING) { 739433d6423SLionel Sambuc update_period(m_ptr); 740433d6423SLionel Sambuc } 741433d6423SLionel Sambuc 742433d6423SLionel Sambuc /* Search system services table. Only check slots that are in use and not 743433d6423SLionel Sambuc * updating. 744433d6423SLionel Sambuc */ 745433d6423SLionel Sambuc for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { 746433d6423SLionel Sambuc rpub = rp->r_pub; 747433d6423SLionel Sambuc if ((rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_UPDATING)) { 748433d6423SLionel Sambuc 749433d6423SLionel Sambuc /* Compute period. */ 750433d6423SLionel Sambuc period = rp->r_period; 751433d6423SLionel Sambuc if(rp->r_flags & RS_INITIALIZING) { 752433d6423SLionel Sambuc period = RS_INIT_T; 753433d6423SLionel Sambuc } 754433d6423SLionel Sambuc 755433d6423SLionel Sambuc /* If the service is to be revived (because it repeatedly exited, 756433d6423SLionel Sambuc * and was not directly restarted), the binary backoff field is 757433d6423SLionel Sambuc * greater than zero. 758433d6423SLionel Sambuc */ 759433d6423SLionel Sambuc if (rp->r_backoff > 0) { 760433d6423SLionel Sambuc rp->r_backoff -= 1; 761433d6423SLionel Sambuc if (rp->r_backoff == 0) { 762433d6423SLionel Sambuc restart_service(rp); 763433d6423SLionel Sambuc } 764433d6423SLionel Sambuc } 765433d6423SLionel Sambuc 766433d6423SLionel Sambuc /* If the service was signaled with a SIGTERM and fails to respond, 767433d6423SLionel Sambuc * kill the system service with a SIGKILL signal. 768433d6423SLionel Sambuc */ 769433d6423SLionel Sambuc else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T 770433d6423SLionel Sambuc && rp->r_pid > 0) { 771433d6423SLionel Sambuc rp->r_stop_tm = 0; 772433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 773433d6423SLionel Sambuc } 774433d6423SLionel Sambuc 775433d6423SLionel Sambuc /* There seems to be no special conditions. If the service has a 776433d6423SLionel Sambuc * period assigned check its status. 777433d6423SLionel Sambuc */ 778433d6423SLionel Sambuc else if (period > 0) { 779433d6423SLionel Sambuc 780433d6423SLionel Sambuc /* Check if an answer to a status request is still pending. If 781433d6423SLionel Sambuc * the service didn't respond within time, kill it to simulate 782433d6423SLionel Sambuc * a crash. The failure will be detected and the service will 783433d6423SLionel Sambuc * be restarted automatically. Give the service a free pass if 784433d6423SLionel Sambuc * somebody is initializing. There may be some weird dependencies 785433d6423SLionel Sambuc * if another service is, for example, restarting at the same 786433d6423SLionel Sambuc * time. 787433d6423SLionel Sambuc */ 788433d6423SLionel Sambuc if (rp->r_alive_tm < rp->r_check_tm) { 789433d6423SLionel Sambuc if (now - rp->r_alive_tm > 2*period && 790433d6423SLionel Sambuc rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) { 791433d6423SLionel Sambuc if(rs_verbose) 792433d6423SLionel Sambuc printf("RS: %s reported late\n", srv_to_string(rp)); 793433d6423SLionel Sambuc if(lookup_slot_by_flags(RS_INITIALIZING)) { 794433d6423SLionel Sambuc /* Skip for now. */ 795433d6423SLionel Sambuc if(rs_verbose) 796433d6423SLionel Sambuc printf("RS: %s gets a free pass\n", 797433d6423SLionel Sambuc srv_to_string(rp)); 798433d6423SLionel Sambuc rp->r_alive_tm = now; 799433d6423SLionel Sambuc rp->r_check_tm = now+1; 800433d6423SLionel Sambuc continue; 801433d6423SLionel Sambuc } 802433d6423SLionel Sambuc rp->r_flags |= RS_NOPINGREPLY; 803433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 804433d6423SLionel Sambuc } 805433d6423SLionel Sambuc } 806433d6423SLionel Sambuc 807433d6423SLionel Sambuc /* No answer pending. Check if a period expired since the last 808433d6423SLionel Sambuc * check and, if so request the system service's status. 809433d6423SLionel Sambuc */ 810433d6423SLionel Sambuc else if (now - rp->r_check_tm > rp->r_period) { 811433d6423SLionel Sambuc ipc_notify(rpub->endpoint); /* request status */ 812433d6423SLionel Sambuc rp->r_check_tm = now; /* mark time */ 813433d6423SLionel Sambuc } 814433d6423SLionel Sambuc } 815433d6423SLionel Sambuc } 816433d6423SLionel Sambuc } 817433d6423SLionel Sambuc 818433d6423SLionel Sambuc /* Reschedule a synchronous alarm for the next period. */ 819433d6423SLionel Sambuc if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) 820433d6423SLionel Sambuc panic("couldn't set alarm: %d", s); 821433d6423SLionel Sambuc } 822433d6423SLionel Sambuc 823433d6423SLionel Sambuc /*===========================================================================* 824433d6423SLionel Sambuc * do_sigchld * 825433d6423SLionel Sambuc *===========================================================================*/ 826433d6423SLionel Sambuc void do_sigchld() 827433d6423SLionel Sambuc { 828433d6423SLionel Sambuc /* PM informed us that there are dead children to cleanup. Go get them. */ 829433d6423SLionel Sambuc pid_t pid; 830433d6423SLionel Sambuc int status; 831433d6423SLionel Sambuc struct rproc *rp; 832433d6423SLionel Sambuc struct rproc **rps; 833433d6423SLionel Sambuc int i, nr_rps; 834433d6423SLionel Sambuc 835433d6423SLionel Sambuc if(rs_verbose) 836433d6423SLionel Sambuc printf("RS: got SIGCHLD signal, cleaning up dead children\n"); 837433d6423SLionel Sambuc 838433d6423SLionel Sambuc while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) { 839433d6423SLionel Sambuc rp = lookup_slot_by_pid(pid); 840433d6423SLionel Sambuc if(rp != NULL) { 841433d6423SLionel Sambuc 842433d6423SLionel Sambuc if(rs_verbose) 843433d6423SLionel Sambuc printf("RS: %s exited via another signal manager\n", 844433d6423SLionel Sambuc srv_to_string(rp)); 845433d6423SLionel Sambuc 846433d6423SLionel Sambuc /* The slot is still there. This means RS is not the signal 847433d6423SLionel Sambuc * manager assigned to the process. Ignore the event but 848433d6423SLionel Sambuc * free slots for all the service instances and send a late 849433d6423SLionel Sambuc * reply if necessary. 850433d6423SLionel Sambuc */ 851433d6423SLionel Sambuc get_service_instances(rp, &rps, &nr_rps); 852433d6423SLionel Sambuc for(i=0;i<nr_rps;i++) { 853433d6423SLionel Sambuc if(rupdate.flags & RS_UPDATING) { 854433d6423SLionel Sambuc rupdate.flags &= ~RS_UPDATING; 855433d6423SLionel Sambuc } 856433d6423SLionel Sambuc free_slot(rps[i]); 857433d6423SLionel Sambuc } 858433d6423SLionel Sambuc } 859433d6423SLionel Sambuc } 860433d6423SLionel Sambuc } 861433d6423SLionel Sambuc 862433d6423SLionel Sambuc /*===========================================================================* 863433d6423SLionel Sambuc * do_getsysinfo * 864433d6423SLionel Sambuc *===========================================================================*/ 865433d6423SLionel Sambuc int do_getsysinfo(m_ptr) 866433d6423SLionel Sambuc message *m_ptr; 867433d6423SLionel Sambuc { 868433d6423SLionel Sambuc vir_bytes src_addr, dst_addr; 869433d6423SLionel Sambuc int dst_proc; 870*0eabb93cSDavid van Moolenbroek size_t size, len; 871433d6423SLionel Sambuc int s; 872433d6423SLionel Sambuc 873433d6423SLionel Sambuc /* Check if the call can be allowed. */ 874433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK) 875433d6423SLionel Sambuc return s; 876433d6423SLionel Sambuc 877*0eabb93cSDavid van Moolenbroek dst_proc = m_ptr->m_source; 878*0eabb93cSDavid van Moolenbroek dst_addr = m_ptr->m_lsys_getsysinfo.where; 879*0eabb93cSDavid van Moolenbroek size = m_ptr->m_lsys_getsysinfo.size; 880*0eabb93cSDavid van Moolenbroek 881433d6423SLionel Sambuc switch(m_ptr->m_lsys_getsysinfo.what) { 882433d6423SLionel Sambuc case SI_PROC_TAB: 883433d6423SLionel Sambuc src_addr = (vir_bytes) rproc; 884433d6423SLionel Sambuc len = sizeof(struct rproc) * NR_SYS_PROCS; 885433d6423SLionel Sambuc break; 886*0eabb93cSDavid van Moolenbroek case SI_PROCALL_TAB: 887*0eabb93cSDavid van Moolenbroek /* Copy out both tables, one after the other. */ 888*0eabb93cSDavid van Moolenbroek src_addr = (vir_bytes) rproc; 889*0eabb93cSDavid van Moolenbroek len = sizeof(struct rproc) * NR_SYS_PROCS; 890*0eabb93cSDavid van Moolenbroek if (len > size) 891*0eabb93cSDavid van Moolenbroek return EINVAL; 892*0eabb93cSDavid van Moolenbroek if ((s = sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)) != OK) 893*0eabb93cSDavid van Moolenbroek return s; 894*0eabb93cSDavid van Moolenbroek dst_addr += len; 895*0eabb93cSDavid van Moolenbroek size -= len; 896*0eabb93cSDavid van Moolenbroek /* FALLTHROUGH */ 897433d6423SLionel Sambuc case SI_PROCPUB_TAB: 898433d6423SLionel Sambuc src_addr = (vir_bytes) rprocpub; 899433d6423SLionel Sambuc len = sizeof(struct rprocpub) * NR_SYS_PROCS; 900433d6423SLionel Sambuc break; 901433d6423SLionel Sambuc default: 902433d6423SLionel Sambuc return(EINVAL); 903433d6423SLionel Sambuc } 904433d6423SLionel Sambuc 905*0eabb93cSDavid van Moolenbroek if (len != size) 906433d6423SLionel Sambuc return(EINVAL); 907433d6423SLionel Sambuc 908433d6423SLionel Sambuc return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len); 909433d6423SLionel Sambuc } 910433d6423SLionel Sambuc 911433d6423SLionel Sambuc /*===========================================================================* 912433d6423SLionel Sambuc * do_lookup * 913433d6423SLionel Sambuc *===========================================================================*/ 914433d6423SLionel Sambuc int do_lookup(m_ptr) 915433d6423SLionel Sambuc message *m_ptr; 916433d6423SLionel Sambuc { 917433d6423SLionel Sambuc static char namebuf[100]; 918433d6423SLionel Sambuc int len, r; 919433d6423SLionel Sambuc struct rproc *rrp; 920433d6423SLionel Sambuc struct rprocpub *rrpub; 921433d6423SLionel Sambuc 922433d6423SLionel Sambuc len = m_ptr->m_rs_req.name_len; 923433d6423SLionel Sambuc 924433d6423SLionel Sambuc if(len < 2 || len >= sizeof(namebuf)) { 925433d6423SLionel Sambuc printf("RS: len too weird (%d)\n", len); 926433d6423SLionel Sambuc return EINVAL; 927433d6423SLionel Sambuc } 928433d6423SLionel Sambuc 929433d6423SLionel Sambuc if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name, 930433d6423SLionel Sambuc SELF, (vir_bytes) namebuf, len)) != OK) { 931433d6423SLionel Sambuc printf("RS: name copy failed\n"); 932433d6423SLionel Sambuc return r; 933433d6423SLionel Sambuc 934433d6423SLionel Sambuc } 935433d6423SLionel Sambuc 936433d6423SLionel Sambuc namebuf[len] = '\0'; 937433d6423SLionel Sambuc 938433d6423SLionel Sambuc rrp = lookup_slot_by_label(namebuf); 939433d6423SLionel Sambuc if(!rrp) { 940433d6423SLionel Sambuc return ESRCH; 941433d6423SLionel Sambuc } 942433d6423SLionel Sambuc rrpub = rrp->r_pub; 943433d6423SLionel Sambuc m_ptr->m_rs_req.endpoint = rrpub->endpoint; 944433d6423SLionel Sambuc 945433d6423SLionel Sambuc return OK; 946433d6423SLionel Sambuc } 947433d6423SLionel Sambuc 948433d6423SLionel Sambuc /*===========================================================================* 949433d6423SLionel Sambuc * check_request * 950433d6423SLionel Sambuc *===========================================================================*/ 951433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start) 952433d6423SLionel Sambuc { 953433d6423SLionel Sambuc /* Verify scheduling parameters */ 954433d6423SLionel Sambuc if (rs_start->rss_scheduler != KERNEL && 955433d6423SLionel Sambuc (rs_start->rss_scheduler < 0 || 956433d6423SLionel Sambuc rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) { 957433d6423SLionel Sambuc printf("RS: check_request: invalid scheduler %d\n", 958433d6423SLionel Sambuc rs_start->rss_scheduler); 959433d6423SLionel Sambuc return EINVAL; 960433d6423SLionel Sambuc } 961433d6423SLionel Sambuc if (rs_start->rss_priority >= NR_SCHED_QUEUES) { 962433d6423SLionel Sambuc printf("RS: check_request: priority %u out of range\n", 963433d6423SLionel Sambuc rs_start->rss_priority); 964433d6423SLionel Sambuc return EINVAL; 965433d6423SLionel Sambuc } 966433d6423SLionel Sambuc if (rs_start->rss_quantum <= 0) { 967433d6423SLionel Sambuc printf("RS: check_request: quantum %u out of range\n", 968433d6423SLionel Sambuc rs_start->rss_quantum); 969433d6423SLionel Sambuc return EINVAL; 970433d6423SLionel Sambuc } 971433d6423SLionel Sambuc 972433d6423SLionel Sambuc if (rs_start->rss_cpu == RS_CPU_BSP) 973433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 974433d6423SLionel Sambuc else if (rs_start->rss_cpu == RS_CPU_DEFAULT) { 975433d6423SLionel Sambuc /* keep the default value */ 976433d6423SLionel Sambuc } else if (rs_start->rss_cpu < 0) 977433d6423SLionel Sambuc return EINVAL; 978433d6423SLionel Sambuc else if (rs_start->rss_cpu > machine.processors_count) { 979433d6423SLionel Sambuc printf("RS: cpu number %d out of range 0-%d, using BSP\n", 980433d6423SLionel Sambuc rs_start->rss_cpu, machine.processors_count); 981433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 982433d6423SLionel Sambuc } 983433d6423SLionel Sambuc 984433d6423SLionel Sambuc /* Verify signal manager. */ 985433d6423SLionel Sambuc if (rs_start->rss_sigmgr != SELF && 986433d6423SLionel Sambuc (rs_start->rss_sigmgr < 0 || 987433d6423SLionel Sambuc rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) { 988433d6423SLionel Sambuc printf("RS: check_request: invalid signal manager %d\n", 989433d6423SLionel Sambuc rs_start->rss_sigmgr); 990433d6423SLionel Sambuc return EINVAL; 991433d6423SLionel Sambuc } 992433d6423SLionel Sambuc 993433d6423SLionel Sambuc return OK; 994433d6423SLionel Sambuc } 995433d6423SLionel Sambuc 996