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; 24fb6bd596SCristiano Giuffrida int init_flags = 0; 25433d6423SLionel Sambuc 26433d6423SLionel Sambuc /* Check if the call can be allowed. */ 27433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK) 28433d6423SLionel Sambuc return r; 29433d6423SLionel Sambuc 30433d6423SLionel Sambuc /* Allocate a new system service slot. */ 31433d6423SLionel Sambuc r = alloc_slot(&rp); 32433d6423SLionel Sambuc if(r != OK) { 33433d6423SLionel Sambuc printf("RS: do_up: unable to allocate a new slot: %d\n", r); 34433d6423SLionel Sambuc return r; 35433d6423SLionel Sambuc } 36433d6423SLionel Sambuc rpub = rp->r_pub; 37433d6423SLionel Sambuc 38433d6423SLionel Sambuc /* Copy the request structure. */ 39433d6423SLionel Sambuc r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 40433d6423SLionel Sambuc if (r != OK) { 41433d6423SLionel Sambuc return r; 42433d6423SLionel Sambuc } 43433d6423SLionel Sambuc r = check_request(&rs_start); 44433d6423SLionel Sambuc if (r != OK) { 45433d6423SLionel Sambuc return r; 46433d6423SLionel Sambuc } 47fb6bd596SCristiano Giuffrida 48fb6bd596SCristiano Giuffrida /* Check flags. */ 49433d6423SLionel Sambuc noblock = (rs_start.rss_flags & RSS_NOBLOCK); 50fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) { 51fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_CRASH; 52fb6bd596SCristiano Giuffrida } 53fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) { 54fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_FAIL; 55fb6bd596SCristiano Giuffrida } 56fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) { 57fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_TIMEOUT; 58fb6bd596SCristiano Giuffrida } 59fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) { 60fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_DEFCB; 61fb6bd596SCristiano Giuffrida } 62433d6423SLionel Sambuc 63433d6423SLionel Sambuc /* Initialize the slot as requested. */ 64433d6423SLionel Sambuc r = init_slot(rp, &rs_start, m_ptr->m_source); 65433d6423SLionel Sambuc if(r != OK) { 66433d6423SLionel Sambuc printf("RS: do_up: unable to init the new slot: %d\n", r); 67433d6423SLionel Sambuc return r; 68433d6423SLionel Sambuc } 69433d6423SLionel Sambuc 70433d6423SLionel Sambuc /* Check for duplicates */ 71433d6423SLionel Sambuc if(lookup_slot_by_label(rpub->label)) { 72433d6423SLionel Sambuc printf("RS: service with the same label '%s' already exists\n", 73433d6423SLionel Sambuc rpub->label); 74433d6423SLionel Sambuc return EBUSY; 75433d6423SLionel Sambuc } 76433d6423SLionel Sambuc if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) { 77433d6423SLionel Sambuc printf("RS: service with the same device number %d already exists\n", 78433d6423SLionel Sambuc rpub->dev_nr); 79433d6423SLionel Sambuc return EBUSY; 80433d6423SLionel Sambuc } 81433d6423SLionel Sambuc 82433d6423SLionel Sambuc /* All information was gathered. Now try to start the system service. */ 83fb6bd596SCristiano Giuffrida r = start_service(rp, init_flags); 84433d6423SLionel Sambuc if(r != OK) { 85433d6423SLionel Sambuc return r; 86433d6423SLionel Sambuc } 87433d6423SLionel Sambuc 88433d6423SLionel Sambuc /* Unblock the caller immediately if requested. */ 89433d6423SLionel Sambuc if(noblock) { 90433d6423SLionel Sambuc return OK; 91433d6423SLionel Sambuc } 92433d6423SLionel Sambuc 93433d6423SLionel Sambuc /* Late reply - send a reply when service completes initialization. */ 94433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 95433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 96433d6423SLionel Sambuc rp->r_caller_request = RS_UP; 97433d6423SLionel Sambuc 98433d6423SLionel Sambuc return EDONTREPLY; 99433d6423SLionel Sambuc } 100433d6423SLionel Sambuc 101433d6423SLionel Sambuc /*===========================================================================* 102433d6423SLionel Sambuc * do_down * 103433d6423SLionel Sambuc *===========================================================================*/ 104433d6423SLionel Sambuc int do_down(message *m_ptr) 105433d6423SLionel Sambuc { 106433d6423SLionel Sambuc register struct rproc *rp; 107433d6423SLionel Sambuc int s; 108433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 109433d6423SLionel Sambuc 110433d6423SLionel Sambuc /* Copy label. */ 111433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 112433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 113433d6423SLionel Sambuc if(s != OK) { 114433d6423SLionel Sambuc return s; 115433d6423SLionel Sambuc } 116433d6423SLionel Sambuc 117433d6423SLionel Sambuc /* Lookup slot by label. */ 118433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 119433d6423SLionel Sambuc if(!rp) { 120433d6423SLionel Sambuc if(rs_verbose) 121433d6423SLionel Sambuc printf("RS: do_down: service '%s' not found\n", label); 122433d6423SLionel Sambuc return(ESRCH); 123433d6423SLionel Sambuc } 124433d6423SLionel Sambuc 125433d6423SLionel Sambuc /* Check if the call can be allowed. */ 126433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK) 127433d6423SLionel Sambuc return s; 128433d6423SLionel Sambuc 129433d6423SLionel Sambuc /* Stop service. */ 130433d6423SLionel Sambuc if (rp->r_flags & RS_TERMINATED) { 131433d6423SLionel Sambuc /* A recovery script is requesting us to bring down the service. 132433d6423SLionel Sambuc * The service is already gone, simply perform cleanup. 133433d6423SLionel Sambuc */ 134433d6423SLionel Sambuc if(rs_verbose) 135433d6423SLionel Sambuc printf("RS: recovery script performs service down...\n"); 136433d6423SLionel Sambuc unpublish_service(rp); 137433d6423SLionel Sambuc cleanup_service(rp); 138433d6423SLionel Sambuc return(OK); 139433d6423SLionel Sambuc } 140433d6423SLionel Sambuc stop_service(rp,RS_EXITING); 141433d6423SLionel Sambuc 142433d6423SLionel Sambuc /* Late reply - send a reply when service dies. */ 143433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 144433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 145433d6423SLionel Sambuc rp->r_caller_request = RS_DOWN; 146433d6423SLionel Sambuc 147433d6423SLionel Sambuc return EDONTREPLY; 148433d6423SLionel Sambuc } 149433d6423SLionel Sambuc 150433d6423SLionel Sambuc /*===========================================================================* 151433d6423SLionel Sambuc * do_restart * 152433d6423SLionel Sambuc *===========================================================================*/ 153433d6423SLionel Sambuc int do_restart(message *m_ptr) 154433d6423SLionel Sambuc { 155433d6423SLionel Sambuc struct rproc *rp; 156433d6423SLionel Sambuc int s, r; 157433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 158433d6423SLionel Sambuc char script[MAX_SCRIPT_LEN]; 159433d6423SLionel Sambuc 160433d6423SLionel Sambuc /* Copy label. */ 161433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 162433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 163433d6423SLionel Sambuc if(s != OK) { 164433d6423SLionel Sambuc return s; 165433d6423SLionel Sambuc } 166433d6423SLionel Sambuc 167433d6423SLionel Sambuc /* Lookup slot by label. */ 168433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 169433d6423SLionel Sambuc if(!rp) { 170433d6423SLionel Sambuc if(rs_verbose) 171433d6423SLionel Sambuc printf("RS: do_restart: service '%s' not found\n", label); 172433d6423SLionel Sambuc return(ESRCH); 173433d6423SLionel Sambuc } 174433d6423SLionel Sambuc 175433d6423SLionel Sambuc /* Check if the call can be allowed. */ 176433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK) 177433d6423SLionel Sambuc return r; 178433d6423SLionel Sambuc 179433d6423SLionel Sambuc /* We can only be asked to restart a service from a recovery script. */ 180433d6423SLionel Sambuc if (! (rp->r_flags & RS_TERMINATED) ) { 181433d6423SLionel Sambuc if(rs_verbose) 182433d6423SLionel Sambuc printf("RS: %s is still running\n", srv_to_string(rp)); 183433d6423SLionel Sambuc return EBUSY; 184433d6423SLionel Sambuc } 185433d6423SLionel Sambuc 186433d6423SLionel Sambuc if(rs_verbose) 187433d6423SLionel Sambuc printf("RS: recovery script performs service restart...\n"); 188433d6423SLionel Sambuc 189433d6423SLionel Sambuc /* Restart the service, but make sure we don't call the script again. */ 190433d6423SLionel Sambuc strcpy(script, rp->r_script); 191433d6423SLionel Sambuc rp->r_script[0] = '\0'; 192433d6423SLionel Sambuc restart_service(rp); 193433d6423SLionel Sambuc strcpy(rp->r_script, script); 194433d6423SLionel Sambuc 195433d6423SLionel Sambuc return OK; 196433d6423SLionel Sambuc } 197433d6423SLionel Sambuc 198433d6423SLionel Sambuc /*===========================================================================* 199433d6423SLionel Sambuc * do_clone * 200433d6423SLionel Sambuc *===========================================================================*/ 201433d6423SLionel Sambuc int do_clone(message *m_ptr) 202433d6423SLionel Sambuc { 203433d6423SLionel Sambuc struct rproc *rp; 204433d6423SLionel Sambuc struct rprocpub *rpub; 205433d6423SLionel Sambuc int s, r; 206433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 207433d6423SLionel Sambuc 208433d6423SLionel Sambuc /* Copy label. */ 209433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 210433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 211433d6423SLionel Sambuc if(s != OK) { 212433d6423SLionel Sambuc return s; 213433d6423SLionel Sambuc } 214433d6423SLionel Sambuc 215433d6423SLionel Sambuc /* Lookup slot by label. */ 216433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 217433d6423SLionel Sambuc if(!rp) { 218433d6423SLionel Sambuc if(rs_verbose) 219433d6423SLionel Sambuc printf("RS: do_clone: service '%s' not found\n", label); 220433d6423SLionel Sambuc return(ESRCH); 221433d6423SLionel Sambuc } 222433d6423SLionel Sambuc rpub = rp->r_pub; 223433d6423SLionel Sambuc 224433d6423SLionel Sambuc /* Check if the call can be allowed. */ 225433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK) 226433d6423SLionel Sambuc return r; 227433d6423SLionel Sambuc 228433d6423SLionel Sambuc /* Don't clone if a replica is already available. */ 229433d6423SLionel Sambuc if(rp->r_next_rp) { 230433d6423SLionel Sambuc return EEXIST; 231433d6423SLionel Sambuc } 232433d6423SLionel Sambuc 233433d6423SLionel Sambuc /* Clone the service as requested. */ 234433d6423SLionel Sambuc rpub->sys_flags |= SF_USE_REPL; 235fb6bd596SCristiano Giuffrida if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) { 236433d6423SLionel Sambuc rpub->sys_flags &= ~SF_USE_REPL; 237433d6423SLionel Sambuc return r; 238433d6423SLionel Sambuc } 239433d6423SLionel Sambuc 240433d6423SLionel Sambuc return OK; 241433d6423SLionel Sambuc } 242433d6423SLionel Sambuc 243433d6423SLionel Sambuc /*===========================================================================* 244fb6bd596SCristiano Giuffrida * do_unclone * 245fb6bd596SCristiano Giuffrida *===========================================================================*/ 246fb6bd596SCristiano Giuffrida int do_unclone(message *m_ptr) 247fb6bd596SCristiano Giuffrida { 248fb6bd596SCristiano Giuffrida struct rproc *rp; 249fb6bd596SCristiano Giuffrida struct rprocpub *rpub; 250fb6bd596SCristiano Giuffrida int s, r; 251fb6bd596SCristiano Giuffrida char label[RS_MAX_LABEL_LEN]; 252fb6bd596SCristiano Giuffrida 253fb6bd596SCristiano Giuffrida /* Copy label. */ 254fb6bd596SCristiano Giuffrida s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 255fb6bd596SCristiano Giuffrida m_ptr->m_rs_req.len, label, sizeof(label)); 256fb6bd596SCristiano Giuffrida if(s != OK) { 257fb6bd596SCristiano Giuffrida return s; 258fb6bd596SCristiano Giuffrida } 259fb6bd596SCristiano Giuffrida 260fb6bd596SCristiano Giuffrida /* Lookup slot by label. */ 261fb6bd596SCristiano Giuffrida rp = lookup_slot_by_label(label); 262fb6bd596SCristiano Giuffrida if(!rp) { 263fb6bd596SCristiano Giuffrida if(rs_verbose) 264fb6bd596SCristiano Giuffrida printf("RS: do_unclone: service '%s' not found\n", label); 265fb6bd596SCristiano Giuffrida return(ESRCH); 266fb6bd596SCristiano Giuffrida } 267fb6bd596SCristiano Giuffrida rpub = rp->r_pub; 268fb6bd596SCristiano Giuffrida 269fb6bd596SCristiano Giuffrida /* Check if the call can be allowed. */ 270fb6bd596SCristiano Giuffrida if((r = check_call_permission(m_ptr->m_source, RS_UNCLONE, rp)) != OK) 271fb6bd596SCristiano Giuffrida return r; 272fb6bd596SCristiano Giuffrida 273fb6bd596SCristiano Giuffrida /* Don't unclone if no replica is available. */ 274fb6bd596SCristiano Giuffrida if(!(rpub->sys_flags & SF_USE_REPL)) { 275fb6bd596SCristiano Giuffrida return ENOENT; 276fb6bd596SCristiano Giuffrida } 277fb6bd596SCristiano Giuffrida 278fb6bd596SCristiano Giuffrida /* Unclone the service as requested. */ 279fb6bd596SCristiano Giuffrida rpub->sys_flags &= ~SF_USE_REPL; 280fb6bd596SCristiano Giuffrida if(rp->r_next_rp) { 281fb6bd596SCristiano Giuffrida cleanup_service_now(rp->r_next_rp); 282fb6bd596SCristiano Giuffrida rp->r_next_rp = NULL; 283fb6bd596SCristiano Giuffrida } 284fb6bd596SCristiano Giuffrida 285fb6bd596SCristiano Giuffrida return OK; 286fb6bd596SCristiano Giuffrida } 287fb6bd596SCristiano Giuffrida 288fb6bd596SCristiano Giuffrida /*===========================================================================* 289433d6423SLionel Sambuc * do_edit * 290433d6423SLionel Sambuc *===========================================================================*/ 291433d6423SLionel Sambuc int do_edit(message *m_ptr) 292433d6423SLionel Sambuc { 293433d6423SLionel Sambuc struct rproc *rp; 294433d6423SLionel Sambuc struct rprocpub *rpub; 295433d6423SLionel Sambuc struct rs_start rs_start; 296433d6423SLionel Sambuc int r; 297433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 298433d6423SLionel Sambuc 299433d6423SLionel Sambuc /* Copy the request structure. */ 300433d6423SLionel Sambuc r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 301433d6423SLionel Sambuc if (r != OK) { 302433d6423SLionel Sambuc return r; 303433d6423SLionel Sambuc } 304433d6423SLionel Sambuc 305433d6423SLionel Sambuc /* Copy label. */ 306433d6423SLionel Sambuc r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 307433d6423SLionel Sambuc rs_start.rss_label.l_len, label, sizeof(label)); 308433d6423SLionel Sambuc if(r != OK) { 309433d6423SLionel Sambuc return r; 310433d6423SLionel Sambuc } 311433d6423SLionel Sambuc 312433d6423SLionel Sambuc /* Lookup slot by label. */ 313433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 314433d6423SLionel Sambuc if(!rp) { 315433d6423SLionel Sambuc if(rs_verbose) 316433d6423SLionel Sambuc printf("RS: do_edit: service '%s' not found\n", label); 317433d6423SLionel Sambuc return ESRCH; 318433d6423SLionel Sambuc } 319433d6423SLionel Sambuc rpub = rp->r_pub; 320433d6423SLionel Sambuc 321433d6423SLionel Sambuc /* Check if the call can be allowed. */ 322433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK) 323433d6423SLionel Sambuc return r; 324433d6423SLionel Sambuc 325433d6423SLionel Sambuc if(rs_verbose) 326433d6423SLionel Sambuc printf("RS: %s edits settings\n", srv_to_string(rp)); 327433d6423SLionel Sambuc 328433d6423SLionel Sambuc /* Synch the privilege structure with the kernel. */ 329433d6423SLionel Sambuc if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) { 330433d6423SLionel Sambuc printf("RS: do_edit: unable to synch privilege structure: %d\n", r); 331433d6423SLionel Sambuc return r; 332433d6423SLionel Sambuc } 333433d6423SLionel Sambuc 334433d6423SLionel Sambuc /* Tell scheduler this process is finished */ 335433d6423SLionel Sambuc if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) { 336433d6423SLionel Sambuc printf("RS: do_edit: scheduler won't give up process: %d\n", r); 337433d6423SLionel Sambuc return r; 338433d6423SLionel Sambuc } 339433d6423SLionel Sambuc 340433d6423SLionel Sambuc /* Edit the slot as requested. */ 341433d6423SLionel Sambuc if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) { 342433d6423SLionel Sambuc printf("RS: do_edit: unable to edit the existing slot: %d\n", r); 343433d6423SLionel Sambuc return r; 344433d6423SLionel Sambuc } 345433d6423SLionel Sambuc 346433d6423SLionel Sambuc /* Update privilege structure. */ 347433d6423SLionel Sambuc r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv); 348433d6423SLionel Sambuc if(r != OK) { 349433d6423SLionel Sambuc printf("RS: do_edit: unable to update privilege structure: %d\n", r); 350433d6423SLionel Sambuc return r; 351433d6423SLionel Sambuc } 352433d6423SLionel Sambuc 353433d6423SLionel Sambuc /* Update VM calls. */ 354433d6423SLionel Sambuc if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0], 355433d6423SLionel Sambuc !!(rp->r_priv.s_flags & SYS_PROC))) != OK) { 356433d6423SLionel Sambuc printf("RS: do_edit: failed: %d\n", r); 357433d6423SLionel Sambuc return r; 358433d6423SLionel Sambuc } 359433d6423SLionel Sambuc 360433d6423SLionel Sambuc /* Reinitialize scheduling. */ 361433d6423SLionel Sambuc if ((r = sched_init_proc(rp)) != OK) { 362433d6423SLionel Sambuc printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r); 363433d6423SLionel Sambuc return r; 364433d6423SLionel Sambuc } 365433d6423SLionel Sambuc 366433d6423SLionel Sambuc /* Cleanup old replicas and create a new one, if necessary. */ 367433d6423SLionel Sambuc if(rpub->sys_flags & SF_USE_REPL) { 368433d6423SLionel Sambuc if(rp->r_next_rp) { 369433d6423SLionel Sambuc cleanup_service(rp->r_next_rp); 370433d6423SLionel Sambuc rp->r_next_rp = NULL; 371433d6423SLionel Sambuc } 372fb6bd596SCristiano Giuffrida if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) { 373433d6423SLionel Sambuc printf("RS: warning: unable to clone %s\n", srv_to_string(rp)); 374433d6423SLionel Sambuc } 375433d6423SLionel Sambuc } 376433d6423SLionel Sambuc 377433d6423SLionel Sambuc return OK; 378433d6423SLionel Sambuc } 379433d6423SLionel Sambuc 380433d6423SLionel Sambuc /*===========================================================================* 381433d6423SLionel Sambuc * do_refresh * 382433d6423SLionel Sambuc *===========================================================================*/ 383433d6423SLionel Sambuc int do_refresh(message *m_ptr) 384433d6423SLionel Sambuc { 385433d6423SLionel Sambuc register struct rproc *rp; 386433d6423SLionel Sambuc int s; 387433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 388433d6423SLionel Sambuc 389433d6423SLionel Sambuc /* Copy label. */ 390433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 391433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 392433d6423SLionel Sambuc if(s != OK) { 393433d6423SLionel Sambuc return s; 394433d6423SLionel Sambuc } 395433d6423SLionel Sambuc 396433d6423SLionel Sambuc /* Lookup slot by label. */ 397433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 398433d6423SLionel Sambuc if(!rp) { 399433d6423SLionel Sambuc if(rs_verbose) 400433d6423SLionel Sambuc printf("RS: do_refresh: service '%s' not found\n", label); 401433d6423SLionel Sambuc return(ESRCH); 402433d6423SLionel Sambuc } 403433d6423SLionel Sambuc 404433d6423SLionel Sambuc /* Check if the call can be allowed. */ 405433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK) 406433d6423SLionel Sambuc return s; 407433d6423SLionel Sambuc 408433d6423SLionel Sambuc /* Refresh service. */ 409433d6423SLionel Sambuc if(rs_verbose) 410433d6423SLionel Sambuc printf("RS: %s refreshing\n", srv_to_string(rp)); 411433d6423SLionel Sambuc stop_service(rp,RS_REFRESHING); 412433d6423SLionel Sambuc 413fb6bd596SCristiano Giuffrida /* Late reply - send a reply when refresh completes. */ 414fb6bd596SCristiano Giuffrida rp->r_flags |= RS_LATEREPLY; 415fb6bd596SCristiano Giuffrida rp->r_caller = m_ptr->m_source; 416fb6bd596SCristiano Giuffrida rp->r_caller_request = RS_REFRESH; 417fb6bd596SCristiano Giuffrida 418fb6bd596SCristiano Giuffrida return EDONTREPLY; 419433d6423SLionel Sambuc } 420433d6423SLionel Sambuc 421433d6423SLionel Sambuc /*===========================================================================* 422433d6423SLionel Sambuc * do_shutdown * 423433d6423SLionel Sambuc *===========================================================================*/ 424433d6423SLionel Sambuc int do_shutdown(message *m_ptr) 425433d6423SLionel Sambuc { 426433d6423SLionel Sambuc int slot_nr; 427433d6423SLionel Sambuc struct rproc *rp; 428433d6423SLionel Sambuc int r; 429433d6423SLionel Sambuc 430433d6423SLionel Sambuc /* Check if the call can be allowed. */ 431433d6423SLionel Sambuc if (m_ptr != NULL) { 432433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK) 433433d6423SLionel Sambuc return r; 434433d6423SLionel Sambuc } 435433d6423SLionel Sambuc 436433d6423SLionel Sambuc if(rs_verbose) 437433d6423SLionel Sambuc printf("RS: shutting down...\n"); 438433d6423SLionel Sambuc 439433d6423SLionel Sambuc /* Set flag to tell RS we are shutting down. */ 440433d6423SLionel Sambuc shutting_down = TRUE; 441433d6423SLionel Sambuc 442433d6423SLionel Sambuc /* Don't restart dead services. */ 443433d6423SLionel Sambuc for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { 444433d6423SLionel Sambuc rp = &rproc[slot_nr]; 445433d6423SLionel Sambuc if (rp->r_flags & RS_IN_USE) { 446433d6423SLionel Sambuc rp->r_flags |= RS_EXITING; 447433d6423SLionel Sambuc } 448433d6423SLionel Sambuc } 449433d6423SLionel Sambuc return(OK); 450433d6423SLionel Sambuc } 451433d6423SLionel Sambuc 452433d6423SLionel Sambuc /*===========================================================================* 453433d6423SLionel Sambuc * do_init_ready * 454433d6423SLionel Sambuc *===========================================================================*/ 455433d6423SLionel Sambuc int do_init_ready(message *m_ptr) 456433d6423SLionel Sambuc { 457433d6423SLionel Sambuc int who_p; 458433d6423SLionel Sambuc message m; 459fb6bd596SCristiano Giuffrida struct rproc *rp, *new_rp; 460433d6423SLionel Sambuc struct rprocpub *rpub; 461fb6bd596SCristiano Giuffrida int result; 462433d6423SLionel Sambuc int r; 463433d6423SLionel Sambuc 464433d6423SLionel Sambuc who_p = _ENDPOINT_P(m_ptr->m_source); 465433d6423SLionel Sambuc result = m_ptr->m_rs_init.result; 466433d6423SLionel Sambuc 467433d6423SLionel Sambuc rp = rproc_ptr[who_p]; 468433d6423SLionel Sambuc rpub = rp->r_pub; 469433d6423SLionel Sambuc 470433d6423SLionel Sambuc /* Make sure the originating service was requested to initialize. */ 471433d6423SLionel Sambuc if(! (rp->r_flags & RS_INITIALIZING) ) { 472433d6423SLionel Sambuc if(rs_verbose) 473433d6423SLionel Sambuc printf("RS: do_init_ready: got unexpected init ready msg from %d\n", 474433d6423SLionel Sambuc m_ptr->m_source); 475433d6423SLionel Sambuc return EINVAL; 476433d6423SLionel Sambuc } 477433d6423SLionel Sambuc 478433d6423SLionel Sambuc /* Check if something went wrong and the service failed to init. 479433d6423SLionel Sambuc * In that case, kill the service. 480433d6423SLionel Sambuc */ 481433d6423SLionel Sambuc if(result != OK) { 482433d6423SLionel Sambuc if(rs_verbose) 483433d6423SLionel Sambuc printf("RS: %s initialization error: %s\n", srv_to_string(rp), 484433d6423SLionel Sambuc init_strerror(result)); 485fb6bd596SCristiano Giuffrida if (result == ERESTART && !SRV_IS_UPDATING(rp)) 486433d6423SLionel Sambuc rp->r_flags |= RS_REINCARNATE; 487433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 488fb6bd596SCristiano Giuffrida rp->r_init_err = result; 489433d6423SLionel Sambuc return EDONTREPLY; 490433d6423SLionel Sambuc } 491433d6423SLionel Sambuc 492fb6bd596SCristiano Giuffrida if(rs_verbose) 493fb6bd596SCristiano Giuffrida printf("RS: %s initialized\n", srv_to_string(rp)); 494fb6bd596SCristiano Giuffrida 495fb6bd596SCristiano Giuffrida /* If updating, check if there is no service to update left. In that case, 496fb6bd596SCristiano Giuffrida * end the update process. If VM has completed initialization as part of 497fb6bd596SCristiano Giuffrida * multi-component live update, let the other services under update run now. 498fb6bd596SCristiano Giuffrida */ 499fb6bd596SCristiano Giuffrida if(SRV_IS_UPDATING(rp)) { 500fb6bd596SCristiano Giuffrida rupdate.num_init_ready_pending--; 501fb6bd596SCristiano Giuffrida rp->r_flags |= RS_INIT_DONE; 502fb6bd596SCristiano Giuffrida if(rupdate.num_init_ready_pending == 0) { 503fb6bd596SCristiano Giuffrida printf("RS: update succeeded\n"); 504fb6bd596SCristiano Giuffrida end_update(OK, RS_REPLY); 505fb6bd596SCristiano Giuffrida } 506fb6bd596SCristiano Giuffrida } 507fb6bd596SCristiano Giuffrida else { 508433d6423SLionel Sambuc /* Mark the slot as no longer initializing. */ 509433d6423SLionel Sambuc rp->r_flags &= ~RS_INITIALIZING; 510433d6423SLionel Sambuc rp->r_check_tm = 0; 511433d6423SLionel Sambuc getticks(&rp->r_alive_tm); 512433d6423SLionel Sambuc 513433d6423SLionel Sambuc /* Reply and unblock the service before doing anything else. */ 514433d6423SLionel Sambuc m.m_type = OK; 515433d6423SLionel Sambuc reply(rpub->endpoint, rp, &m); 516433d6423SLionel Sambuc 517fb6bd596SCristiano Giuffrida /* Finalize initialization. */ 518fb6bd596SCristiano Giuffrida end_srv_init(rp); 519433d6423SLionel Sambuc } 520433d6423SLionel Sambuc 521fb6bd596SCristiano Giuffrida return EDONTREPLY; 522433d6423SLionel Sambuc } 523433d6423SLionel Sambuc 524433d6423SLionel Sambuc /*===========================================================================* 525433d6423SLionel Sambuc * do_update * 526433d6423SLionel Sambuc *===========================================================================*/ 527433d6423SLionel Sambuc int do_update(message *m_ptr) 528433d6423SLionel Sambuc { 529433d6423SLionel Sambuc struct rproc *rp; 530fb6bd596SCristiano Giuffrida struct rproc *trg_rp; 531433d6423SLionel Sambuc struct rproc *new_rp; 532433d6423SLionel Sambuc struct rprocpub *rpub; 533fb6bd596SCristiano Giuffrida struct rprocupd *rpupd; 534433d6423SLionel Sambuc struct rs_start rs_start; 535fb6bd596SCristiano Giuffrida int noblock, do_self_update, force_self_update, batch_mode, prepare_only; 536433d6423SLionel Sambuc int s; 537433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 538fb6bd596SCristiano Giuffrida int prepare_state, prepare_maxtime; 539fb6bd596SCristiano Giuffrida endpoint_t state_endpoint; 540fb6bd596SCristiano Giuffrida int lu_flags = 0; 541fb6bd596SCristiano Giuffrida int init_flags = 0; 542fb6bd596SCristiano Giuffrida int allow_retries = 0; 543433d6423SLionel Sambuc 544433d6423SLionel Sambuc /* Copy the request structure. */ 545433d6423SLionel Sambuc s = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 546433d6423SLionel Sambuc if (s != OK) { 547433d6423SLionel Sambuc return s; 548433d6423SLionel Sambuc } 549433d6423SLionel Sambuc 550433d6423SLionel Sambuc /* Copy label. */ 551433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 552433d6423SLionel Sambuc rs_start.rss_label.l_len, label, sizeof(label)); 553433d6423SLionel Sambuc if(s != OK) { 554433d6423SLionel Sambuc return s; 555433d6423SLionel Sambuc } 556433d6423SLionel Sambuc 557433d6423SLionel Sambuc /* Lookup slot by label. */ 558433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 559433d6423SLionel Sambuc if(!rp) { 560433d6423SLionel Sambuc if(rs_verbose) 561433d6423SLionel Sambuc printf("RS: do_update: service '%s' not found\n", label); 562433d6423SLionel Sambuc return ESRCH; 563433d6423SLionel Sambuc } 564433d6423SLionel Sambuc rpub = rp->r_pub; 565433d6423SLionel Sambuc 566fb6bd596SCristiano Giuffrida /* Check flags. */ 567fb6bd596SCristiano Giuffrida noblock = (rs_start.rss_flags & RSS_NOBLOCK); 568fb6bd596SCristiano Giuffrida do_self_update = (rs_start.rss_flags & RSS_SELF_LU); 569fb6bd596SCristiano Giuffrida force_self_update = (rs_start.rss_flags & RSS_FORCE_SELF_LU); 570fb6bd596SCristiano Giuffrida batch_mode = (rs_start.rss_flags & RSS_BATCH); 571fb6bd596SCristiano Giuffrida prepare_only = (rs_start.rss_flags & RSS_PREPARE_ONLY_LU); 572fb6bd596SCristiano Giuffrida if(do_self_update || force_self_update) { 573fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_SELF; 574fb6bd596SCristiano Giuffrida } 575fb6bd596SCristiano Giuffrida if(prepare_only) { 576fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_PREPARE_ONLY; 577fb6bd596SCristiano Giuffrida } 578fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_ASR_LU) { 579fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_ASR; 580fb6bd596SCristiano Giuffrida } 581fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_UNSAFE_LU) { 582fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_UNSAFE; 583fb6bd596SCristiano Giuffrida } 584fb6bd596SCristiano Giuffrida if(!prepare_only && (rs_start.rss_flags & RSS_DETACH)) { 585fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_DETACHED; 586fb6bd596SCristiano Giuffrida } 587fb6bd596SCristiano Giuffrida if(rs_start.rss_map_prealloc_bytes <= 0 588fb6bd596SCristiano Giuffrida && rpub->endpoint == VM_PROC_NR 589fb6bd596SCristiano Giuffrida && (((lu_flags & (SEF_LU_SELF|SEF_LU_ASR)) != SEF_LU_SELF) || rs_start.rss_flags & RSS_FORCE_INIT_ST) 590fb6bd596SCristiano Giuffrida && RS_VM_DEFAULT_MAP_PREALLOC_LEN > 0) { 591fb6bd596SCristiano Giuffrida /* Give VM some mmapped regions by default on non-identical updates.*/ 592fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes = RS_VM_DEFAULT_MAP_PREALLOC_LEN; 593fb6bd596SCristiano Giuffrida if(rs_verbose) 594fb6bd596SCristiano Giuffrida printf("RS: %s gets %ld default mmap bytes\n", srv_to_string(rp), 595fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes); 596fb6bd596SCristiano Giuffrida } 597fb6bd596SCristiano Giuffrida if((rs_start.rss_flags & RSS_NOMMAP_LU) || rs_start.rss_map_prealloc_bytes) { 598fb6bd596SCristiano Giuffrida /* Don't inherit mmapped regions at update time if requested or if 599fb6bd596SCristiano Giuffrida * mmap preallocation is used. 600fb6bd596SCristiano Giuffrida */ 601fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_NOMMAP; 602fb6bd596SCristiano Giuffrida } 603fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) { 604fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_CRASH; 605fb6bd596SCristiano Giuffrida } 606fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) { 607fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_FAIL; 608fb6bd596SCristiano Giuffrida } 609fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) { 610fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_TIMEOUT; 611fb6bd596SCristiano Giuffrida } 612fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) { 613fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_DEFCB; 614fb6bd596SCristiano Giuffrida } 615fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_ST) { 616fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_ST; 617fb6bd596SCristiano Giuffrida } 618fb6bd596SCristiano Giuffrida init_flags |= lu_flags; 619fb6bd596SCristiano Giuffrida 620fb6bd596SCristiano Giuffrida /* Lookup target label (if any). */ 621fb6bd596SCristiano Giuffrida trg_rp = NULL; 622fb6bd596SCristiano Giuffrida state_endpoint = NONE; 623fb6bd596SCristiano Giuffrida if(rs_start.rss_trg_label.l_len > 0) { 624fb6bd596SCristiano Giuffrida s = copy_label(m_ptr->m_source, rs_start.rss_trg_label.l_addr, 625fb6bd596SCristiano Giuffrida rs_start.rss_trg_label.l_len, label, sizeof(label)); 626fb6bd596SCristiano Giuffrida if(s != OK) { 627fb6bd596SCristiano Giuffrida return s; 628fb6bd596SCristiano Giuffrida } 629fb6bd596SCristiano Giuffrida trg_rp = lookup_slot_by_label(label); 630fb6bd596SCristiano Giuffrida if(!trg_rp) { 631fb6bd596SCristiano Giuffrida if(rs_verbose) 632fb6bd596SCristiano Giuffrida printf("RS: do_update: target service '%s' not found\n", label); 633fb6bd596SCristiano Giuffrida return ESRCH; 634fb6bd596SCristiano Giuffrida } 635fb6bd596SCristiano Giuffrida state_endpoint = trg_rp->r_pub->endpoint; 636fb6bd596SCristiano Giuffrida } 637fb6bd596SCristiano Giuffrida 638433d6423SLionel Sambuc /* Check if the call can be allowed. */ 639433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK) 640433d6423SLionel Sambuc return s; 641433d6423SLionel Sambuc 642433d6423SLionel Sambuc /* Retrieve live update state. */ 643fb6bd596SCristiano Giuffrida prepare_state = m_ptr->m_rs_update.state; 644fb6bd596SCristiano Giuffrida if(prepare_state == SEF_LU_STATE_NULL) { 645433d6423SLionel Sambuc return(EINVAL); 646433d6423SLionel Sambuc } 647433d6423SLionel Sambuc 648433d6423SLionel Sambuc /* Retrieve prepare max time. */ 649433d6423SLionel Sambuc prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime; 650fb6bd596SCristiano Giuffrida if(prepare_maxtime == 0) { 651433d6423SLionel Sambuc prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME; 652433d6423SLionel Sambuc } 653433d6423SLionel Sambuc 654433d6423SLionel Sambuc /* Make sure we are not already updating. */ 655fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPDATING()) { 656fb6bd596SCristiano Giuffrida printf("RS: an update is already in progress\n"); 657433d6423SLionel Sambuc return EBUSY; 658433d6423SLionel Sambuc } 659433d6423SLionel Sambuc 660fb6bd596SCristiano Giuffrida /* If an update is already scheduled, check constraints. */ 661fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPD_SCHEDULED()) { 662fb6bd596SCristiano Giuffrida if(!batch_mode) { 663fb6bd596SCristiano Giuffrida printf("RS: an update is already scheduled, cannot start a new one\n"); 664fb6bd596SCristiano Giuffrida return EBUSY; 665fb6bd596SCristiano Giuffrida } 666fb6bd596SCristiano Giuffrida if(SRV_IS_UPD_SCHEDULED(rp)) { 667fb6bd596SCristiano Giuffrida printf("RS: the specified process is already part of the currently scheduled update\n"); 668fb6bd596SCristiano Giuffrida return EINVAL; 669fb6bd596SCristiano Giuffrida } 670fb6bd596SCristiano Giuffrida if(rupdate.last_rpupd->rp->r_pub->endpoint == RS_PROC_NR) { 671fb6bd596SCristiano Giuffrida printf("RS: RS should always be the last service to update in a multi-component update\n"); 672fb6bd596SCristiano Giuffrida return EINVAL; 673fb6bd596SCristiano Giuffrida } 674fb6bd596SCristiano Giuffrida } 675fb6bd596SCristiano Giuffrida 676fb6bd596SCristiano Giuffrida /* Prepare-only update for VM, PM, and VFS is only supported with an unreachable state. */ 677fb6bd596SCristiano Giuffrida if(prepare_only 678fb6bd596SCristiano Giuffrida && (rp->r_pub->endpoint == VM_PROC_NR || rp->r_pub->endpoint == PM_PROC_NR || rp->r_pub->endpoint == VFS_PROC_NR)) { 679fb6bd596SCristiano Giuffrida if(prepare_state != SEF_LU_STATE_UNREACHABLE) { 680fb6bd596SCristiano Giuffrida printf("RS: prepare-only update for VM, PM and VFS is only supported with state %d\n", SEF_LU_STATE_UNREACHABLE); 681fb6bd596SCristiano Giuffrida return EINVAL; 682fb6bd596SCristiano Giuffrida } 683fb6bd596SCristiano Giuffrida } 684fb6bd596SCristiano Giuffrida 685fb6bd596SCristiano Giuffrida /* Prepare-only update for RS is not supported. */ 686fb6bd596SCristiano Giuffrida if(prepare_only && rp->r_pub->endpoint == RS_PROC_NR) { 687fb6bd596SCristiano Giuffrida printf("RS: prepare-only update for RS is not supported\n"); 688fb6bd596SCristiano Giuffrida return EINVAL; 689fb6bd596SCristiano Giuffrida } 690fb6bd596SCristiano Giuffrida 691fb6bd596SCristiano Giuffrida /* Initialize update descriptor. */ 692fb6bd596SCristiano Giuffrida rpupd = &rp->r_upd; 693fb6bd596SCristiano Giuffrida rupdate_upd_init(rpupd, rp); 694fb6bd596SCristiano Giuffrida rpupd->lu_flags |= lu_flags; 695fb6bd596SCristiano Giuffrida rpupd->init_flags |= init_flags; 696fb6bd596SCristiano Giuffrida rupdate_set_new_upd_flags(rpupd); 697fb6bd596SCristiano Giuffrida 698433d6423SLionel Sambuc /* A self update live updates a service instance into a replica, a regular 699433d6423SLionel Sambuc * update live updates a service instance into a new version, as specified 700433d6423SLionel Sambuc * by the given binary. 701433d6423SLionel Sambuc */ 702fb6bd596SCristiano Giuffrida if(!prepare_only) { 703433d6423SLionel Sambuc if(do_self_update) { 704433d6423SLionel Sambuc if(rs_verbose) 705fb6bd596SCristiano Giuffrida printf("RS: %s requested to perform self update\n", srv_to_string(rp)); 706433d6423SLionel Sambuc 707433d6423SLionel Sambuc /* Clone the system service and use the replica as the new version. */ 708fb6bd596SCristiano Giuffrida s = clone_service(rp, LU_SYS_PROC, rpupd->init_flags); 709433d6423SLionel Sambuc if(s != OK) { 710433d6423SLionel Sambuc printf("RS: do_update: unable to clone service: %d\n", s); 711433d6423SLionel Sambuc return s; 712433d6423SLionel Sambuc } 713fb6bd596SCristiano Giuffrida new_rp = rp->r_new_rp; 714433d6423SLionel Sambuc } 715433d6423SLionel Sambuc else { 716433d6423SLionel Sambuc if(rs_verbose) 717fb6bd596SCristiano Giuffrida printf("RS: %s requested to perform %s update\n", srv_to_string(rp), 718fb6bd596SCristiano Giuffrida force_self_update ? "(forced) self" : "regular"); 719433d6423SLionel Sambuc 720433d6423SLionel Sambuc /* Allocate a system service slot for the new version. */ 721433d6423SLionel Sambuc s = alloc_slot(&new_rp); 722433d6423SLionel Sambuc if(s != OK) { 723433d6423SLionel Sambuc printf("RS: do_update: unable to allocate a new slot: %d\n", s); 724433d6423SLionel Sambuc return s; 725433d6423SLionel Sambuc } 726433d6423SLionel Sambuc 727433d6423SLionel Sambuc /* Initialize the slot as requested. */ 728433d6423SLionel Sambuc s = init_slot(new_rp, &rs_start, m_ptr->m_source); 729433d6423SLionel Sambuc if(s != OK) { 730433d6423SLionel Sambuc printf("RS: do_update: unable to init the new slot: %d\n", s); 731433d6423SLionel Sambuc return s; 732433d6423SLionel Sambuc } 733433d6423SLionel Sambuc 734433d6423SLionel Sambuc /* Let the new version inherit defaults from the old one. */ 735433d6423SLionel Sambuc inherit_service_defaults(rp, new_rp); 736433d6423SLionel Sambuc 737433d6423SLionel Sambuc /* Link the two versions. */ 738433d6423SLionel Sambuc rp->r_new_rp = new_rp; 739433d6423SLionel Sambuc new_rp->r_old_rp = rp; 740433d6423SLionel Sambuc 741433d6423SLionel Sambuc /* Create new version of the service but don't let it run. */ 742433d6423SLionel Sambuc new_rp->r_priv.s_flags |= LU_SYS_PROC; 743fb6bd596SCristiano Giuffrida new_rp->r_priv.s_init_flags |= rpupd->init_flags; 744433d6423SLionel Sambuc s = create_service(new_rp); 745433d6423SLionel Sambuc if(s != OK) { 746433d6423SLionel Sambuc printf("RS: do_update: unable to create a new service: %d\n", s); 747433d6423SLionel Sambuc return s; 748433d6423SLionel Sambuc } 749433d6423SLionel Sambuc } 750433d6423SLionel Sambuc 751fb6bd596SCristiano Giuffrida /* Set default state endpoint. */ 752fb6bd596SCristiano Giuffrida if(state_endpoint == NONE) { 753fb6bd596SCristiano Giuffrida state_endpoint = new_rp->r_pub->endpoint; 754fb6bd596SCristiano Giuffrida } 755433d6423SLionel Sambuc 756433d6423SLionel Sambuc /* If RS is updating, set up signal managers for the new instance. 757433d6423SLionel Sambuc * The current RS instance must be made the backup signal manager to 758433d6423SLionel Sambuc * support rollback in case of a crash during initialization. 759433d6423SLionel Sambuc */ 760433d6423SLionel Sambuc if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 761433d6423SLionel Sambuc s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint); 762433d6423SLionel Sambuc if(s != OK) { 763433d6423SLionel Sambuc cleanup_service(new_rp); 764433d6423SLionel Sambuc return s; 765433d6423SLionel Sambuc } 766433d6423SLionel Sambuc } 767433d6423SLionel Sambuc 768fb6bd596SCristiano Giuffrida /* Preallocate heap regions if requested. */ 769fb6bd596SCristiano Giuffrida if(rs_start.rss_heap_prealloc_bytes < 0) { 770fb6bd596SCristiano Giuffrida rs_start.rss_heap_prealloc_bytes = 0; 771433d6423SLionel Sambuc } 772fb6bd596SCristiano Giuffrida if(rs_start.rss_heap_prealloc_bytes) { 773fb6bd596SCristiano Giuffrida size_t len; 774fb6bd596SCristiano Giuffrida if(rs_verbose) 775fb6bd596SCristiano Giuffrida printf("RS: %s preallocating %ld heap bytes\n", srv_to_string(new_rp), 776fb6bd596SCristiano Giuffrida rs_start.rss_heap_prealloc_bytes); 777fb6bd596SCristiano Giuffrida 778fb6bd596SCristiano Giuffrida len = rs_start.rss_heap_prealloc_bytes; 779fb6bd596SCristiano Giuffrida s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_HEAP_PREALLOC, 780fb6bd596SCristiano Giuffrida NULL, &len); 781fb6bd596SCristiano Giuffrida if(s != OK) { 782fb6bd596SCristiano Giuffrida printf("vm_memctl(VM_RS_MEM_HEAP_PREALLOC) failed: %d\n", s); 783fb6bd596SCristiano Giuffrida cleanup_service(new_rp); 784fb6bd596SCristiano Giuffrida return s; 785fb6bd596SCristiano Giuffrida } 786fb6bd596SCristiano Giuffrida if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 787fb6bd596SCristiano Giuffrida vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_PIN, 0, 0); 788fb6bd596SCristiano Giuffrida } 789433d6423SLionel Sambuc } 790433d6423SLionel Sambuc 791fb6bd596SCristiano Giuffrida /* Preallocate mmapped regions if requested. */ 792fb6bd596SCristiano Giuffrida if(rs_start.rss_map_prealloc_bytes < 0) { 793fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes = 0; 794433d6423SLionel Sambuc } 795fb6bd596SCristiano Giuffrida if(rs_start.rss_map_prealloc_bytes) { 796fb6bd596SCristiano Giuffrida void *addr = NULL; 797fb6bd596SCristiano Giuffrida if(rs_verbose) 798fb6bd596SCristiano Giuffrida printf("RS: %s preallocating %ld mmap bytes\n", srv_to_string(new_rp), 799fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes); 800fb6bd596SCristiano Giuffrida 801fb6bd596SCristiano Giuffrida new_rp->r_map_prealloc_len = rs_start.rss_map_prealloc_bytes; 802fb6bd596SCristiano Giuffrida s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_MAP_PREALLOC, 803fb6bd596SCristiano Giuffrida &addr, &new_rp->r_map_prealloc_len); 804fb6bd596SCristiano Giuffrida if(s != OK) { 805fb6bd596SCristiano Giuffrida printf("vm_memctl(VM_RS_MEM_MAP_PREALLOC) failed: %d\n", s); 806fb6bd596SCristiano Giuffrida cleanup_service(new_rp); 807fb6bd596SCristiano Giuffrida return s; 808433d6423SLionel Sambuc } 809fb6bd596SCristiano Giuffrida new_rp->r_map_prealloc_addr = (vir_bytes) addr; 810fb6bd596SCristiano Giuffrida } 811fb6bd596SCristiano Giuffrida } 812fb6bd596SCristiano Giuffrida 813fb6bd596SCristiano Giuffrida /* Process state data. */ 814fb6bd596SCristiano Giuffrida s = init_state_data(m_ptr->m_source, prepare_state, &rs_start.rss_state_data, &rpupd->prepare_state_data); 815fb6bd596SCristiano Giuffrida if(s != OK) { 816fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 817fb6bd596SCristiano Giuffrida return s; 818fb6bd596SCristiano Giuffrida } 819fb6bd596SCristiano Giuffrida 820fb6bd596SCristiano Giuffrida /* Create update grants. */ 821fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data.size > 0) { 822fb6bd596SCristiano Giuffrida struct rs_state_data *state_data = &rpupd->prepare_state_data; 823fb6bd596SCristiano Giuffrida rpupd->prepare_state_data_gid = cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data, 824fb6bd596SCristiano Giuffrida state_data->size, CPF_READ); 825fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data_gid == GRANT_INVALID) { 826fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 827fb6bd596SCristiano Giuffrida return ENOMEM; 828fb6bd596SCristiano Giuffrida } 829fb6bd596SCristiano Giuffrida state_data->ipcf_els_gid = GRANT_INVALID; 830fb6bd596SCristiano Giuffrida if(state_data->ipcf_els) { 831fb6bd596SCristiano Giuffrida state_data->ipcf_els_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->ipcf_els, 832fb6bd596SCristiano Giuffrida state_data->ipcf_els_size, CPF_READ); 833fb6bd596SCristiano Giuffrida if(state_data->ipcf_els_gid == GRANT_INVALID) { 834fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 835fb6bd596SCristiano Giuffrida return ENOMEM; 836fb6bd596SCristiano Giuffrida } 837fb6bd596SCristiano Giuffrida } 838fb6bd596SCristiano Giuffrida state_data->eval_gid = GRANT_INVALID; 839fb6bd596SCristiano Giuffrida if(state_data->eval_addr) { 840fb6bd596SCristiano Giuffrida state_data->eval_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->eval_addr, 841fb6bd596SCristiano Giuffrida state_data->eval_len, CPF_READ); 842fb6bd596SCristiano Giuffrida if(state_data->eval_gid == GRANT_INVALID) { 843fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 844fb6bd596SCristiano Giuffrida return ENOMEM; 845fb6bd596SCristiano Giuffrida } 846fb6bd596SCristiano Giuffrida } 847fb6bd596SCristiano Giuffrida } 848fb6bd596SCristiano Giuffrida 849fb6bd596SCristiano Giuffrida /* Fill the new update descriptor and add it to the update chain. */ 850fb6bd596SCristiano Giuffrida rpupd->prepare_state = prepare_state; 851fb6bd596SCristiano Giuffrida rpupd->state_endpoint = state_endpoint; 852fb6bd596SCristiano Giuffrida getticks(&rpupd->prepare_tm); 853fb6bd596SCristiano Giuffrida rpupd->prepare_maxtime = prepare_maxtime; 854fb6bd596SCristiano Giuffrida rupdate_add_upd(rpupd); 855fb6bd596SCristiano Giuffrida 856fb6bd596SCristiano Giuffrida if(rs_verbose) 857fb6bd596SCristiano Giuffrida printf("RS: %s scheduled for %s\n", srv_to_string(rp), srv_upd_to_string(rpupd)); 858fb6bd596SCristiano Giuffrida 859fb6bd596SCristiano Giuffrida /* If batch mode, reply immediately. More services to update will follow. */ 860fb6bd596SCristiano Giuffrida if(batch_mode) { 861fb6bd596SCristiano Giuffrida return OK; 862fb6bd596SCristiano Giuffrida } 863fb6bd596SCristiano Giuffrida 864fb6bd596SCristiano Giuffrida /* Start preparing for the update process. */ 865fb6bd596SCristiano Giuffrida s = start_update_prepare(allow_retries); 866fb6bd596SCristiano Giuffrida if(s == ESRCH) { 867fb6bd596SCristiano Giuffrida /* No process left in the update chain. We are done already. */ 868fb6bd596SCristiano Giuffrida return OK; 869fb6bd596SCristiano Giuffrida } 870fb6bd596SCristiano Giuffrida if(s != OK) { 871fb6bd596SCristiano Giuffrida return s; 872fb6bd596SCristiano Giuffrida } 873fb6bd596SCristiano Giuffrida 874fb6bd596SCristiano Giuffrida /* Unblock the caller immediately if requested. */ 875fb6bd596SCristiano Giuffrida if(noblock) { 876fb6bd596SCristiano Giuffrida return OK; 877fb6bd596SCristiano Giuffrida } 878fb6bd596SCristiano Giuffrida 879fb6bd596SCristiano Giuffrida /* Otherwise, send a reply when the new version completes initialization. */ 880fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY; 881fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller = m_ptr->m_source; 882fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE; 883433d6423SLionel Sambuc 884433d6423SLionel Sambuc return EDONTREPLY; 885433d6423SLionel Sambuc } 886433d6423SLionel Sambuc 887433d6423SLionel Sambuc /*===========================================================================* 888433d6423SLionel Sambuc * do_upd_ready * 889433d6423SLionel Sambuc *===========================================================================*/ 890433d6423SLionel Sambuc int do_upd_ready(message *m_ptr) 891433d6423SLionel Sambuc { 892fb6bd596SCristiano Giuffrida struct rproc *rp; 893fb6bd596SCristiano Giuffrida struct rprocupd *prev_rpupd, *rpupd; 894433d6423SLionel Sambuc int who_p; 895433d6423SLionel Sambuc int result; 896433d6423SLionel Sambuc int is_rs; 897fb6bd596SCristiano Giuffrida int i; 898433d6423SLionel Sambuc 899433d6423SLionel Sambuc who_p = _ENDPOINT_P(m_ptr->m_source); 900433d6423SLionel Sambuc rp = rproc_ptr[who_p]; 901433d6423SLionel Sambuc result = m_ptr->m_rs_update.result; 902433d6423SLionel Sambuc 903433d6423SLionel Sambuc /* Make sure the originating service was requested to prepare for update. */ 904fb6bd596SCristiano Giuffrida rpupd = rupdate.curr_rpupd; 905fb6bd596SCristiano Giuffrida if(!rpupd || rp != rpupd->rp || RUPDATE_IS_INITIALIZING()) { 906433d6423SLionel Sambuc if(rs_verbose) 907fb6bd596SCristiano Giuffrida printf("RS: %s sent late/unexpected update ready msg\n", 908fb6bd596SCristiano Giuffrida srv_to_string(rp)); 909433d6423SLionel Sambuc return EINVAL; 910433d6423SLionel Sambuc } 911fb6bd596SCristiano Giuffrida rp->r_flags |= RS_PREPARE_DONE; 912433d6423SLionel Sambuc 913433d6423SLionel Sambuc /* Check if something went wrong and the service failed to prepare 914433d6423SLionel Sambuc * for the update. In that case, end the update process. The old version will 915433d6423SLionel Sambuc * be replied to and continue executing. 916433d6423SLionel Sambuc */ 917433d6423SLionel Sambuc if(result != OK) { 918fb6bd596SCristiano Giuffrida printf("RS: update failed: %s\n", lu_strerror(result)); 919433d6423SLionel Sambuc end_update(result, RS_REPLY); 920433d6423SLionel Sambuc 921433d6423SLionel Sambuc return EDONTREPLY; 922433d6423SLionel Sambuc } 923433d6423SLionel Sambuc 924fb6bd596SCristiano Giuffrida if(rs_verbose) 925fb6bd596SCristiano Giuffrida printf("RS: %s ready to update\n", srv_to_string(rp)); 926fb6bd596SCristiano Giuffrida 927fb6bd596SCristiano Giuffrida /* If this is a multi-component update and this is not the last service 928fb6bd596SCristiano Giuffrida * in the update, request the next process to update. 929fb6bd596SCristiano Giuffrida */ 930fb6bd596SCristiano Giuffrida if(start_update_prepare_next() != NULL) { 931433d6423SLionel Sambuc return EDONTREPLY; 932433d6423SLionel Sambuc } 933433d6423SLionel Sambuc 934fb6bd596SCristiano Giuffrida /* Now perform the update and request each new instance to initialize. */ 935fb6bd596SCristiano Giuffrida start_update(); 936fb6bd596SCristiano Giuffrida 937433d6423SLionel Sambuc return EDONTREPLY; 938433d6423SLionel Sambuc } 939433d6423SLionel Sambuc 940433d6423SLionel Sambuc /*===========================================================================* 941433d6423SLionel Sambuc * do_period * 942433d6423SLionel Sambuc *===========================================================================*/ 943433d6423SLionel Sambuc void do_period(m_ptr) 944433d6423SLionel Sambuc message *m_ptr; 945433d6423SLionel Sambuc { 946433d6423SLionel Sambuc register struct rproc *rp; 947433d6423SLionel Sambuc register struct rprocpub *rpub; 948433d6423SLionel Sambuc clock_t now = m_ptr->m_notify.timestamp; 949433d6423SLionel Sambuc int s; 950433d6423SLionel Sambuc long period; 951433d6423SLionel Sambuc 952433d6423SLionel Sambuc /* If an update is in progress, check its status. */ 953fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPDATING() && !RUPDATE_IS_INITIALIZING()) { 954433d6423SLionel Sambuc update_period(m_ptr); 955433d6423SLionel Sambuc } 956433d6423SLionel Sambuc 957433d6423SLionel Sambuc /* Search system services table. Only check slots that are in use and not 958433d6423SLionel Sambuc * updating. 959433d6423SLionel Sambuc */ 960433d6423SLionel Sambuc for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { 961433d6423SLionel Sambuc rpub = rp->r_pub; 962fb6bd596SCristiano Giuffrida 963fb6bd596SCristiano Giuffrida if ((rp->r_flags & RS_ACTIVE) && (!SRV_IS_UPDATING(rp) || ((rp->r_flags & (RS_INITIALIZING|RS_INIT_DONE|RS_INIT_PENDING)) == RS_INITIALIZING))) { 964433d6423SLionel Sambuc 965433d6423SLionel Sambuc /* Compute period. */ 966433d6423SLionel Sambuc period = rp->r_period; 967433d6423SLionel Sambuc if(rp->r_flags & RS_INITIALIZING) { 968fb6bd596SCristiano Giuffrida period = SRV_IS_UPDATING(rp) ? UPD_INIT_MAXTIME(&rp->r_upd) : RS_INIT_T; 969433d6423SLionel Sambuc } 970433d6423SLionel Sambuc 971433d6423SLionel Sambuc /* If the service is to be revived (because it repeatedly exited, 972433d6423SLionel Sambuc * and was not directly restarted), the binary backoff field is 973433d6423SLionel Sambuc * greater than zero. 974433d6423SLionel Sambuc */ 975433d6423SLionel Sambuc if (rp->r_backoff > 0) { 976433d6423SLionel Sambuc rp->r_backoff -= 1; 977433d6423SLionel Sambuc if (rp->r_backoff == 0) { 978433d6423SLionel Sambuc restart_service(rp); 979433d6423SLionel Sambuc } 980433d6423SLionel Sambuc } 981433d6423SLionel Sambuc 982433d6423SLionel Sambuc /* If the service was signaled with a SIGTERM and fails to respond, 983433d6423SLionel Sambuc * kill the system service with a SIGKILL signal. 984433d6423SLionel Sambuc */ 985433d6423SLionel Sambuc else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T 986433d6423SLionel Sambuc && rp->r_pid > 0) { 987433d6423SLionel Sambuc rp->r_stop_tm = 0; 988433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 989433d6423SLionel Sambuc } 990433d6423SLionel Sambuc 991433d6423SLionel Sambuc /* There seems to be no special conditions. If the service has a 992433d6423SLionel Sambuc * period assigned check its status. 993433d6423SLionel Sambuc */ 994433d6423SLionel Sambuc else if (period > 0) { 995433d6423SLionel Sambuc 996433d6423SLionel Sambuc /* Check if an answer to a status request is still pending. If 997433d6423SLionel Sambuc * the service didn't respond within time, kill it to simulate 998433d6423SLionel Sambuc * a crash. The failure will be detected and the service will 999433d6423SLionel Sambuc * be restarted automatically. Give the service a free pass if 1000433d6423SLionel Sambuc * somebody is initializing. There may be some weird dependencies 1001433d6423SLionel Sambuc * if another service is, for example, restarting at the same 1002433d6423SLionel Sambuc * time. 1003433d6423SLionel Sambuc */ 1004433d6423SLionel Sambuc if (rp->r_alive_tm < rp->r_check_tm) { 1005433d6423SLionel Sambuc if (now - rp->r_alive_tm > 2*period && 1006433d6423SLionel Sambuc rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) { 1007fb6bd596SCristiano Giuffrida struct rproc *rp2; 1008fb6bd596SCristiano Giuffrida int init_flag; 1009433d6423SLionel Sambuc if(rs_verbose) 1010433d6423SLionel Sambuc printf("RS: %s reported late\n", srv_to_string(rp)); 1011fb6bd596SCristiano Giuffrida init_flag = rp->r_flags & RS_INITIALIZING; 1012fb6bd596SCristiano Giuffrida rp->r_flags &= ~RS_INITIALIZING; 1013fb6bd596SCristiano Giuffrida rp2 = lookup_slot_by_flags(RS_INITIALIZING); 1014fb6bd596SCristiano Giuffrida rp->r_flags |= init_flag; 1015fb6bd596SCristiano Giuffrida if(rp2 != NULL && !SRV_IS_UPDATING(rp)) { 1016433d6423SLionel Sambuc /* Skip for now. */ 1017433d6423SLionel Sambuc if(rs_verbose) 1018433d6423SLionel Sambuc printf("RS: %s gets a free pass\n", 1019433d6423SLionel Sambuc srv_to_string(rp)); 1020433d6423SLionel Sambuc rp->r_alive_tm = now; 1021433d6423SLionel Sambuc rp->r_check_tm = now+1; 1022433d6423SLionel Sambuc continue; 1023433d6423SLionel Sambuc } 1024433d6423SLionel Sambuc rp->r_flags |= RS_NOPINGREPLY; 1025433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 1026fb6bd596SCristiano Giuffrida if(rp->r_flags & RS_INITIALIZING) { 1027fb6bd596SCristiano Giuffrida rp->r_init_err = EINTR; 1028fb6bd596SCristiano Giuffrida } 1029433d6423SLionel Sambuc } 1030433d6423SLionel Sambuc } 1031433d6423SLionel Sambuc 1032433d6423SLionel Sambuc /* No answer pending. Check if a period expired since the last 1033433d6423SLionel Sambuc * check and, if so request the system service's status. 1034433d6423SLionel Sambuc */ 1035433d6423SLionel Sambuc else if (now - rp->r_check_tm > rp->r_period) { 1036433d6423SLionel Sambuc ipc_notify(rpub->endpoint); /* request status */ 1037433d6423SLionel Sambuc rp->r_check_tm = now; /* mark time */ 1038433d6423SLionel Sambuc } 1039433d6423SLionel Sambuc } 1040433d6423SLionel Sambuc } 1041433d6423SLionel Sambuc } 1042433d6423SLionel Sambuc 1043433d6423SLionel Sambuc /* Reschedule a synchronous alarm for the next period. */ 1044433d6423SLionel Sambuc if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) 1045433d6423SLionel Sambuc panic("couldn't set alarm: %d", s); 1046433d6423SLionel Sambuc } 1047433d6423SLionel Sambuc 1048433d6423SLionel Sambuc /*===========================================================================* 1049433d6423SLionel Sambuc * do_sigchld * 1050433d6423SLionel Sambuc *===========================================================================*/ 1051433d6423SLionel Sambuc void do_sigchld() 1052433d6423SLionel Sambuc { 1053433d6423SLionel Sambuc /* PM informed us that there are dead children to cleanup. Go get them. */ 1054433d6423SLionel Sambuc pid_t pid; 1055433d6423SLionel Sambuc int status; 1056433d6423SLionel Sambuc struct rproc *rp; 1057433d6423SLionel Sambuc struct rproc **rps; 1058fb6bd596SCristiano Giuffrida int i, nr_rps, found; 1059433d6423SLionel Sambuc 1060433d6423SLionel Sambuc if(rs_verbose) 1061433d6423SLionel Sambuc printf("RS: got SIGCHLD signal, cleaning up dead children\n"); 1062433d6423SLionel Sambuc 1063433d6423SLionel Sambuc while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) { 1064433d6423SLionel Sambuc rp = lookup_slot_by_pid(pid); 1065433d6423SLionel Sambuc if(rp != NULL) { 1066433d6423SLionel Sambuc 1067433d6423SLionel Sambuc if(rs_verbose) 1068433d6423SLionel Sambuc printf("RS: %s exited via another signal manager\n", 1069433d6423SLionel Sambuc srv_to_string(rp)); 1070433d6423SLionel Sambuc 1071433d6423SLionel Sambuc /* The slot is still there. This means RS is not the signal 1072433d6423SLionel Sambuc * manager assigned to the process. Ignore the event but 1073433d6423SLionel Sambuc * free slots for all the service instances and send a late 1074433d6423SLionel Sambuc * reply if necessary. 1075433d6423SLionel Sambuc */ 1076fb6bd596SCristiano Giuffrida found = 0; 1077433d6423SLionel Sambuc get_service_instances(rp, &rps, &nr_rps); 1078433d6423SLionel Sambuc for(i=0;i<nr_rps;i++) { 1079fb6bd596SCristiano Giuffrida if(SRV_IS_UPDATING(rps[i])) { 1080fb6bd596SCristiano Giuffrida rps[i]->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING); 1081fb6bd596SCristiano Giuffrida found = 1; 1082433d6423SLionel Sambuc } 1083433d6423SLionel Sambuc free_slot(rps[i]); 1084433d6423SLionel Sambuc } 1085fb6bd596SCristiano Giuffrida if(found) { 1086fb6bd596SCristiano Giuffrida rupdate_clear_upds(); 1087fb6bd596SCristiano Giuffrida } 1088433d6423SLionel Sambuc } 1089433d6423SLionel Sambuc } 1090433d6423SLionel Sambuc } 1091433d6423SLionel Sambuc 1092433d6423SLionel Sambuc /*===========================================================================* 1093433d6423SLionel Sambuc * do_getsysinfo * 1094433d6423SLionel Sambuc *===========================================================================*/ 1095433d6423SLionel Sambuc int do_getsysinfo(m_ptr) 1096433d6423SLionel Sambuc message *m_ptr; 1097433d6423SLionel Sambuc { 1098433d6423SLionel Sambuc vir_bytes src_addr, dst_addr; 1099433d6423SLionel Sambuc int dst_proc; 11000eabb93cSDavid van Moolenbroek size_t size, len; 1101433d6423SLionel Sambuc int s; 1102433d6423SLionel Sambuc 1103433d6423SLionel Sambuc /* Check if the call can be allowed. */ 1104433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK) 1105433d6423SLionel Sambuc return s; 1106433d6423SLionel Sambuc 11070eabb93cSDavid van Moolenbroek dst_proc = m_ptr->m_source; 11080eabb93cSDavid van Moolenbroek dst_addr = m_ptr->m_lsys_getsysinfo.where; 11090eabb93cSDavid van Moolenbroek size = m_ptr->m_lsys_getsysinfo.size; 11100eabb93cSDavid van Moolenbroek 1111433d6423SLionel Sambuc switch(m_ptr->m_lsys_getsysinfo.what) { 1112433d6423SLionel Sambuc case SI_PROC_TAB: 1113433d6423SLionel Sambuc src_addr = (vir_bytes) rproc; 1114433d6423SLionel Sambuc len = sizeof(struct rproc) * NR_SYS_PROCS; 1115433d6423SLionel Sambuc break; 11160eabb93cSDavid van Moolenbroek case SI_PROCALL_TAB: 11170eabb93cSDavid van Moolenbroek /* Copy out both tables, one after the other. */ 11180eabb93cSDavid van Moolenbroek src_addr = (vir_bytes) rproc; 11190eabb93cSDavid van Moolenbroek len = sizeof(struct rproc) * NR_SYS_PROCS; 11200eabb93cSDavid van Moolenbroek if (len > size) 11210eabb93cSDavid van Moolenbroek return EINVAL; 11220eabb93cSDavid van Moolenbroek if ((s = sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)) != OK) 11230eabb93cSDavid van Moolenbroek return s; 11240eabb93cSDavid van Moolenbroek dst_addr += len; 11250eabb93cSDavid van Moolenbroek size -= len; 11260eabb93cSDavid van Moolenbroek /* FALLTHROUGH */ 1127433d6423SLionel Sambuc case SI_PROCPUB_TAB: 1128433d6423SLionel Sambuc src_addr = (vir_bytes) rprocpub; 1129433d6423SLionel Sambuc len = sizeof(struct rprocpub) * NR_SYS_PROCS; 1130433d6423SLionel Sambuc break; 1131433d6423SLionel Sambuc default: 1132433d6423SLionel Sambuc return(EINVAL); 1133433d6423SLionel Sambuc } 1134433d6423SLionel Sambuc 11350eabb93cSDavid van Moolenbroek if (len != size) 1136433d6423SLionel Sambuc return(EINVAL); 1137433d6423SLionel Sambuc 1138433d6423SLionel Sambuc return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len); 1139433d6423SLionel Sambuc } 1140433d6423SLionel Sambuc 1141433d6423SLionel Sambuc /*===========================================================================* 1142433d6423SLionel Sambuc * do_lookup * 1143433d6423SLionel Sambuc *===========================================================================*/ 1144433d6423SLionel Sambuc int do_lookup(m_ptr) 1145433d6423SLionel Sambuc message *m_ptr; 1146433d6423SLionel Sambuc { 1147433d6423SLionel Sambuc static char namebuf[100]; 1148433d6423SLionel Sambuc int len, r; 1149433d6423SLionel Sambuc struct rproc *rrp; 1150433d6423SLionel Sambuc struct rprocpub *rrpub; 1151433d6423SLionel Sambuc 1152433d6423SLionel Sambuc len = m_ptr->m_rs_req.name_len; 1153433d6423SLionel Sambuc 1154433d6423SLionel Sambuc if(len < 2 || len >= sizeof(namebuf)) { 1155433d6423SLionel Sambuc printf("RS: len too weird (%d)\n", len); 1156433d6423SLionel Sambuc return EINVAL; 1157433d6423SLionel Sambuc } 1158433d6423SLionel Sambuc 1159433d6423SLionel Sambuc if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name, 1160433d6423SLionel Sambuc SELF, (vir_bytes) namebuf, len)) != OK) { 1161433d6423SLionel Sambuc printf("RS: name copy failed\n"); 1162433d6423SLionel Sambuc return r; 1163433d6423SLionel Sambuc 1164433d6423SLionel Sambuc } 1165433d6423SLionel Sambuc 1166433d6423SLionel Sambuc namebuf[len] = '\0'; 1167433d6423SLionel Sambuc 1168433d6423SLionel Sambuc rrp = lookup_slot_by_label(namebuf); 1169433d6423SLionel Sambuc if(!rrp) { 1170433d6423SLionel Sambuc return ESRCH; 1171433d6423SLionel Sambuc } 1172433d6423SLionel Sambuc rrpub = rrp->r_pub; 1173433d6423SLionel Sambuc m_ptr->m_rs_req.endpoint = rrpub->endpoint; 1174433d6423SLionel Sambuc 1175433d6423SLionel Sambuc return OK; 1176433d6423SLionel Sambuc } 1177433d6423SLionel Sambuc 1178433d6423SLionel Sambuc /*===========================================================================* 1179fb6bd596SCristiano Giuffrida * do_sysctl * 1180fb6bd596SCristiano Giuffrida *===========================================================================*/ 1181fb6bd596SCristiano Giuffrida int do_sysctl(message *m_ptr) 1182fb6bd596SCristiano Giuffrida { 1183fb6bd596SCristiano Giuffrida int request_type = m_ptr->m_rs_req.subtype; 1184fb6bd596SCristiano Giuffrida int r, allow_retries = 1; 1185fb6bd596SCristiano Giuffrida switch(request_type) { 1186fb6bd596SCristiano Giuffrida case RS_SYSCTL_SRV_STATUS: 1187fb6bd596SCristiano Giuffrida print_services_status(); 1188fb6bd596SCristiano Giuffrida break; 1189fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_START: 1190fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_RUN: 1191fb6bd596SCristiano Giuffrida r = start_update_prepare(allow_retries); 1192fb6bd596SCristiano Giuffrida print_update_status(); 1193fb6bd596SCristiano Giuffrida if(r != OK) { 1194fb6bd596SCristiano Giuffrida if(r == ESRCH) { 1195fb6bd596SCristiano Giuffrida /* We are done already. */ 1196fb6bd596SCristiano Giuffrida r = OK; 1197fb6bd596SCristiano Giuffrida } 1198fb6bd596SCristiano Giuffrida return r; 1199fb6bd596SCristiano Giuffrida } 1200fb6bd596SCristiano Giuffrida if(request_type == RS_SYSCTL_UPD_START) { 1201fb6bd596SCristiano Giuffrida return OK; 1202fb6bd596SCristiano Giuffrida } 1203fb6bd596SCristiano Giuffrida /* Send a reply when done. */ 1204fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY; 1205fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller = m_ptr->m_source; 1206fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE; 1207fb6bd596SCristiano Giuffrida return EDONTREPLY; 1208fb6bd596SCristiano Giuffrida break; 1209fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_STOP: 1210fb6bd596SCristiano Giuffrida r = abort_update_proc(EINTR); 1211fb6bd596SCristiano Giuffrida print_update_status(); 1212fb6bd596SCristiano Giuffrida return r; 1213fb6bd596SCristiano Giuffrida break; 1214fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_STATUS: 1215fb6bd596SCristiano Giuffrida print_update_status(); 1216fb6bd596SCristiano Giuffrida break; 1217fb6bd596SCristiano Giuffrida default: 1218fb6bd596SCristiano Giuffrida printf("RS: bad sysctl type\n"); 1219fb6bd596SCristiano Giuffrida return EINVAL; 1220fb6bd596SCristiano Giuffrida break; 1221fb6bd596SCristiano Giuffrida } 1222fb6bd596SCristiano Giuffrida 1223fb6bd596SCristiano Giuffrida return OK; 1224fb6bd596SCristiano Giuffrida } 1225fb6bd596SCristiano Giuffrida 1226fb6bd596SCristiano Giuffrida /*===========================================================================* 1227*3837bb5cSCristiano Giuffrida * do_fi * 1228*3837bb5cSCristiano Giuffrida *===========================================================================*/ 1229*3837bb5cSCristiano Giuffrida int do_fi(message *m_ptr) 1230*3837bb5cSCristiano Giuffrida { 1231*3837bb5cSCristiano Giuffrida struct rproc *rp; 1232*3837bb5cSCristiano Giuffrida struct rprocpub *rpub; 1233*3837bb5cSCristiano Giuffrida int s, r; 1234*3837bb5cSCristiano Giuffrida char label[RS_MAX_LABEL_LEN]; 1235*3837bb5cSCristiano Giuffrida 1236*3837bb5cSCristiano Giuffrida /* Copy label. */ 1237*3837bb5cSCristiano Giuffrida s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 1238*3837bb5cSCristiano Giuffrida m_ptr->m_rs_req.len, label, sizeof(label)); 1239*3837bb5cSCristiano Giuffrida if(s != OK) { 1240*3837bb5cSCristiano Giuffrida return s; 1241*3837bb5cSCristiano Giuffrida } 1242*3837bb5cSCristiano Giuffrida 1243*3837bb5cSCristiano Giuffrida /* Lookup slot by label. */ 1244*3837bb5cSCristiano Giuffrida rp = lookup_slot_by_label(label); 1245*3837bb5cSCristiano Giuffrida if(!rp) { 1246*3837bb5cSCristiano Giuffrida if(rs_verbose) 1247*3837bb5cSCristiano Giuffrida printf("RS: do_fi: service '%s' not found\n", label); 1248*3837bb5cSCristiano Giuffrida return(ESRCH); 1249*3837bb5cSCristiano Giuffrida } 1250*3837bb5cSCristiano Giuffrida rpub = rp->r_pub; 1251*3837bb5cSCristiano Giuffrida 1252*3837bb5cSCristiano Giuffrida /* Check if the call can be allowed. */ 1253*3837bb5cSCristiano Giuffrida if((r = check_call_permission(m_ptr->m_source, RS_FI, rp)) != OK) 1254*3837bb5cSCristiano Giuffrida return r; 1255*3837bb5cSCristiano Giuffrida 1256*3837bb5cSCristiano Giuffrida /* Inject fault into the service as requested. */ 1257*3837bb5cSCristiano Giuffrida s = fi_service(rp); 1258*3837bb5cSCristiano Giuffrida 1259*3837bb5cSCristiano Giuffrida return s; 1260*3837bb5cSCristiano Giuffrida } 1261*3837bb5cSCristiano Giuffrida 1262*3837bb5cSCristiano Giuffrida /*===========================================================================* 1263433d6423SLionel Sambuc * check_request * 1264433d6423SLionel Sambuc *===========================================================================*/ 1265433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start) 1266433d6423SLionel Sambuc { 1267433d6423SLionel Sambuc /* Verify scheduling parameters */ 1268433d6423SLionel Sambuc if (rs_start->rss_scheduler != KERNEL && 1269433d6423SLionel Sambuc (rs_start->rss_scheduler < 0 || 1270433d6423SLionel Sambuc rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) { 1271433d6423SLionel Sambuc printf("RS: check_request: invalid scheduler %d\n", 1272433d6423SLionel Sambuc rs_start->rss_scheduler); 1273433d6423SLionel Sambuc return EINVAL; 1274433d6423SLionel Sambuc } 1275433d6423SLionel Sambuc if (rs_start->rss_priority >= NR_SCHED_QUEUES) { 1276433d6423SLionel Sambuc printf("RS: check_request: priority %u out of range\n", 1277433d6423SLionel Sambuc rs_start->rss_priority); 1278433d6423SLionel Sambuc return EINVAL; 1279433d6423SLionel Sambuc } 1280433d6423SLionel Sambuc if (rs_start->rss_quantum <= 0) { 1281433d6423SLionel Sambuc printf("RS: check_request: quantum %u out of range\n", 1282433d6423SLionel Sambuc rs_start->rss_quantum); 1283433d6423SLionel Sambuc return EINVAL; 1284433d6423SLionel Sambuc } 1285433d6423SLionel Sambuc 1286433d6423SLionel Sambuc if (rs_start->rss_cpu == RS_CPU_BSP) 1287433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 1288433d6423SLionel Sambuc else if (rs_start->rss_cpu == RS_CPU_DEFAULT) { 1289433d6423SLionel Sambuc /* keep the default value */ 1290433d6423SLionel Sambuc } else if (rs_start->rss_cpu < 0) 1291433d6423SLionel Sambuc return EINVAL; 1292433d6423SLionel Sambuc else if (rs_start->rss_cpu > machine.processors_count) { 1293433d6423SLionel Sambuc printf("RS: cpu number %d out of range 0-%d, using BSP\n", 1294433d6423SLionel Sambuc rs_start->rss_cpu, machine.processors_count); 1295433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 1296433d6423SLionel Sambuc } 1297433d6423SLionel Sambuc 1298433d6423SLionel Sambuc /* Verify signal manager. */ 1299433d6423SLionel Sambuc if (rs_start->rss_sigmgr != SELF && 1300433d6423SLionel Sambuc (rs_start->rss_sigmgr < 0 || 1301433d6423SLionel Sambuc rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) { 1302433d6423SLionel Sambuc printf("RS: check_request: invalid signal manager %d\n", 1303433d6423SLionel Sambuc rs_start->rss_sigmgr); 1304433d6423SLionel Sambuc return EINVAL; 1305433d6423SLionel Sambuc } 1306433d6423SLionel Sambuc 1307433d6423SLionel Sambuc return OK; 1308433d6423SLionel Sambuc } 1309433d6423SLionel Sambuc 1310