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; 511*d91f738bSDavid van Moolenbroek rp->r_alive_tm = getticks(); 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(!prepare_only && (rs_start.rss_flags & RSS_DETACH)) { 582fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_DETACHED; 583fb6bd596SCristiano Giuffrida } 584fb6bd596SCristiano Giuffrida if(rs_start.rss_map_prealloc_bytes <= 0 585fb6bd596SCristiano Giuffrida && rpub->endpoint == VM_PROC_NR 586fb6bd596SCristiano Giuffrida && (((lu_flags & (SEF_LU_SELF|SEF_LU_ASR)) != SEF_LU_SELF) || rs_start.rss_flags & RSS_FORCE_INIT_ST) 587fb6bd596SCristiano Giuffrida && RS_VM_DEFAULT_MAP_PREALLOC_LEN > 0) { 588fb6bd596SCristiano Giuffrida /* Give VM some mmapped regions by default on non-identical updates.*/ 589fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes = RS_VM_DEFAULT_MAP_PREALLOC_LEN; 590fb6bd596SCristiano Giuffrida if(rs_verbose) 591fb6bd596SCristiano Giuffrida printf("RS: %s gets %ld default mmap bytes\n", srv_to_string(rp), 592fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes); 593fb6bd596SCristiano Giuffrida } 594fb6bd596SCristiano Giuffrida if((rs_start.rss_flags & RSS_NOMMAP_LU) || rs_start.rss_map_prealloc_bytes) { 595fb6bd596SCristiano Giuffrida /* Don't inherit mmapped regions at update time if requested or if 596fb6bd596SCristiano Giuffrida * mmap preallocation is used. 597fb6bd596SCristiano Giuffrida */ 598fb6bd596SCristiano Giuffrida lu_flags |= SEF_LU_NOMMAP; 599fb6bd596SCristiano Giuffrida } 600fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) { 601fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_CRASH; 602fb6bd596SCristiano Giuffrida } 603fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) { 604fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_FAIL; 605fb6bd596SCristiano Giuffrida } 606fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) { 607fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_TIMEOUT; 608fb6bd596SCristiano Giuffrida } 609fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) { 610fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_DEFCB; 611fb6bd596SCristiano Giuffrida } 612fb6bd596SCristiano Giuffrida if(rs_start.rss_flags & RSS_FORCE_INIT_ST) { 613fb6bd596SCristiano Giuffrida init_flags |= SEF_INIT_ST; 614fb6bd596SCristiano Giuffrida } 615fb6bd596SCristiano Giuffrida init_flags |= lu_flags; 616fb6bd596SCristiano Giuffrida 617fb6bd596SCristiano Giuffrida /* Lookup target label (if any). */ 618fb6bd596SCristiano Giuffrida trg_rp = NULL; 619fb6bd596SCristiano Giuffrida state_endpoint = NONE; 620fb6bd596SCristiano Giuffrida if(rs_start.rss_trg_label.l_len > 0) { 621fb6bd596SCristiano Giuffrida s = copy_label(m_ptr->m_source, rs_start.rss_trg_label.l_addr, 622fb6bd596SCristiano Giuffrida rs_start.rss_trg_label.l_len, label, sizeof(label)); 623fb6bd596SCristiano Giuffrida if(s != OK) { 624fb6bd596SCristiano Giuffrida return s; 625fb6bd596SCristiano Giuffrida } 626fb6bd596SCristiano Giuffrida trg_rp = lookup_slot_by_label(label); 627fb6bd596SCristiano Giuffrida if(!trg_rp) { 628fb6bd596SCristiano Giuffrida if(rs_verbose) 629fb6bd596SCristiano Giuffrida printf("RS: do_update: target service '%s' not found\n", label); 630fb6bd596SCristiano Giuffrida return ESRCH; 631fb6bd596SCristiano Giuffrida } 632fb6bd596SCristiano Giuffrida state_endpoint = trg_rp->r_pub->endpoint; 633fb6bd596SCristiano Giuffrida } 634fb6bd596SCristiano Giuffrida 635433d6423SLionel Sambuc /* Check if the call can be allowed. */ 636433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK) 637433d6423SLionel Sambuc return s; 638433d6423SLionel Sambuc 639433d6423SLionel Sambuc /* Retrieve live update state. */ 640fb6bd596SCristiano Giuffrida prepare_state = m_ptr->m_rs_update.state; 641fb6bd596SCristiano Giuffrida if(prepare_state == SEF_LU_STATE_NULL) { 642433d6423SLionel Sambuc return(EINVAL); 643433d6423SLionel Sambuc } 644433d6423SLionel Sambuc 645433d6423SLionel Sambuc /* Retrieve prepare max time. */ 646433d6423SLionel Sambuc prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime; 647fb6bd596SCristiano Giuffrida if(prepare_maxtime == 0) { 648433d6423SLionel Sambuc prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME; 649433d6423SLionel Sambuc } 650433d6423SLionel Sambuc 651433d6423SLionel Sambuc /* Make sure we are not already updating. */ 652fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPDATING()) { 653fb6bd596SCristiano Giuffrida printf("RS: an update is already in progress\n"); 654433d6423SLionel Sambuc return EBUSY; 655433d6423SLionel Sambuc } 656433d6423SLionel Sambuc 657fb6bd596SCristiano Giuffrida /* If an update is already scheduled, check constraints. */ 658fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPD_SCHEDULED()) { 659fb6bd596SCristiano Giuffrida if(!batch_mode) { 660fb6bd596SCristiano Giuffrida printf("RS: an update is already scheduled, cannot start a new one\n"); 661fb6bd596SCristiano Giuffrida return EBUSY; 662fb6bd596SCristiano Giuffrida } 663fb6bd596SCristiano Giuffrida if(SRV_IS_UPD_SCHEDULED(rp)) { 664fb6bd596SCristiano Giuffrida printf("RS: the specified process is already part of the currently scheduled update\n"); 665fb6bd596SCristiano Giuffrida return EINVAL; 666fb6bd596SCristiano Giuffrida } 667fb6bd596SCristiano Giuffrida } 668fb6bd596SCristiano Giuffrida 669fb6bd596SCristiano Giuffrida /* Prepare-only update for VM, PM, and VFS is only supported with an unreachable state. */ 670fb6bd596SCristiano Giuffrida if(prepare_only 671fb6bd596SCristiano Giuffrida && (rp->r_pub->endpoint == VM_PROC_NR || rp->r_pub->endpoint == PM_PROC_NR || rp->r_pub->endpoint == VFS_PROC_NR)) { 672fb6bd596SCristiano Giuffrida if(prepare_state != SEF_LU_STATE_UNREACHABLE) { 673fb6bd596SCristiano Giuffrida printf("RS: prepare-only update for VM, PM and VFS is only supported with state %d\n", SEF_LU_STATE_UNREACHABLE); 674fb6bd596SCristiano Giuffrida return EINVAL; 675fb6bd596SCristiano Giuffrida } 676fb6bd596SCristiano Giuffrida } 677fb6bd596SCristiano Giuffrida 678fb6bd596SCristiano Giuffrida /* Prepare-only update for RS is not supported. */ 679fb6bd596SCristiano Giuffrida if(prepare_only && rp->r_pub->endpoint == RS_PROC_NR) { 680fb6bd596SCristiano Giuffrida printf("RS: prepare-only update for RS is not supported\n"); 681fb6bd596SCristiano Giuffrida return EINVAL; 682fb6bd596SCristiano Giuffrida } 683fb6bd596SCristiano Giuffrida 684fb6bd596SCristiano Giuffrida /* Initialize update descriptor. */ 685fb6bd596SCristiano Giuffrida rpupd = &rp->r_upd; 686fb6bd596SCristiano Giuffrida rupdate_upd_init(rpupd, rp); 687fb6bd596SCristiano Giuffrida rpupd->lu_flags |= lu_flags; 688fb6bd596SCristiano Giuffrida rpupd->init_flags |= init_flags; 689fb6bd596SCristiano Giuffrida rupdate_set_new_upd_flags(rpupd); 690fb6bd596SCristiano Giuffrida 691433d6423SLionel Sambuc /* A self update live updates a service instance into a replica, a regular 692433d6423SLionel Sambuc * update live updates a service instance into a new version, as specified 693433d6423SLionel Sambuc * by the given binary. 694433d6423SLionel Sambuc */ 695fb6bd596SCristiano Giuffrida if(!prepare_only) { 696433d6423SLionel Sambuc if(do_self_update) { 697433d6423SLionel Sambuc if(rs_verbose) 698fb6bd596SCristiano Giuffrida printf("RS: %s requested to perform self update\n", srv_to_string(rp)); 699433d6423SLionel Sambuc 700433d6423SLionel Sambuc /* Clone the system service and use the replica as the new version. */ 701fb6bd596SCristiano Giuffrida s = clone_service(rp, LU_SYS_PROC, rpupd->init_flags); 702433d6423SLionel Sambuc if(s != OK) { 703433d6423SLionel Sambuc printf("RS: do_update: unable to clone service: %d\n", s); 704433d6423SLionel Sambuc return s; 705433d6423SLionel Sambuc } 706fb6bd596SCristiano Giuffrida new_rp = rp->r_new_rp; 707433d6423SLionel Sambuc } 708433d6423SLionel Sambuc else { 709433d6423SLionel Sambuc if(rs_verbose) 710fb6bd596SCristiano Giuffrida printf("RS: %s requested to perform %s update\n", srv_to_string(rp), 711fb6bd596SCristiano Giuffrida force_self_update ? "(forced) self" : "regular"); 712433d6423SLionel Sambuc 713433d6423SLionel Sambuc /* Allocate a system service slot for the new version. */ 714433d6423SLionel Sambuc s = alloc_slot(&new_rp); 715433d6423SLionel Sambuc if(s != OK) { 716433d6423SLionel Sambuc printf("RS: do_update: unable to allocate a new slot: %d\n", s); 717433d6423SLionel Sambuc return s; 718433d6423SLionel Sambuc } 719433d6423SLionel Sambuc 720433d6423SLionel Sambuc /* Initialize the slot as requested. */ 721433d6423SLionel Sambuc s = init_slot(new_rp, &rs_start, m_ptr->m_source); 722433d6423SLionel Sambuc if(s != OK) { 723433d6423SLionel Sambuc printf("RS: do_update: unable to init the new slot: %d\n", s); 724433d6423SLionel Sambuc return s; 725433d6423SLionel Sambuc } 726433d6423SLionel Sambuc 727433d6423SLionel Sambuc /* Let the new version inherit defaults from the old one. */ 728433d6423SLionel Sambuc inherit_service_defaults(rp, new_rp); 729433d6423SLionel Sambuc 730433d6423SLionel Sambuc /* Link the two versions. */ 731433d6423SLionel Sambuc rp->r_new_rp = new_rp; 732433d6423SLionel Sambuc new_rp->r_old_rp = rp; 733433d6423SLionel Sambuc 734433d6423SLionel Sambuc /* Create new version of the service but don't let it run. */ 735433d6423SLionel Sambuc new_rp->r_priv.s_flags |= LU_SYS_PROC; 736fb6bd596SCristiano Giuffrida new_rp->r_priv.s_init_flags |= rpupd->init_flags; 737433d6423SLionel Sambuc s = create_service(new_rp); 738433d6423SLionel Sambuc if(s != OK) { 739433d6423SLionel Sambuc printf("RS: do_update: unable to create a new service: %d\n", s); 740433d6423SLionel Sambuc return s; 741433d6423SLionel Sambuc } 742433d6423SLionel Sambuc } 743433d6423SLionel Sambuc 744fb6bd596SCristiano Giuffrida /* Set default state endpoint. */ 745fb6bd596SCristiano Giuffrida if(state_endpoint == NONE) { 746fb6bd596SCristiano Giuffrida state_endpoint = new_rp->r_pub->endpoint; 747fb6bd596SCristiano Giuffrida } 748433d6423SLionel Sambuc 749433d6423SLionel Sambuc /* If RS is updating, set up signal managers for the new instance. 750433d6423SLionel Sambuc * The current RS instance must be made the backup signal manager to 751433d6423SLionel Sambuc * support rollback in case of a crash during initialization. 752433d6423SLionel Sambuc */ 753433d6423SLionel Sambuc if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 754433d6423SLionel Sambuc s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint); 755433d6423SLionel Sambuc if(s != OK) { 756433d6423SLionel Sambuc cleanup_service(new_rp); 757433d6423SLionel Sambuc return s; 758433d6423SLionel Sambuc } 759433d6423SLionel Sambuc } 760433d6423SLionel Sambuc 761fb6bd596SCristiano Giuffrida /* Preallocate heap regions if requested. */ 762fb6bd596SCristiano Giuffrida if(rs_start.rss_heap_prealloc_bytes < 0) { 763fb6bd596SCristiano Giuffrida rs_start.rss_heap_prealloc_bytes = 0; 764433d6423SLionel Sambuc } 765fb6bd596SCristiano Giuffrida if(rs_start.rss_heap_prealloc_bytes) { 766fb6bd596SCristiano Giuffrida size_t len; 767fb6bd596SCristiano Giuffrida if(rs_verbose) 768fb6bd596SCristiano Giuffrida printf("RS: %s preallocating %ld heap bytes\n", srv_to_string(new_rp), 769fb6bd596SCristiano Giuffrida rs_start.rss_heap_prealloc_bytes); 770fb6bd596SCristiano Giuffrida 771fb6bd596SCristiano Giuffrida len = rs_start.rss_heap_prealloc_bytes; 772fb6bd596SCristiano Giuffrida s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_HEAP_PREALLOC, 773fb6bd596SCristiano Giuffrida NULL, &len); 774fb6bd596SCristiano Giuffrida if(s != OK) { 775fb6bd596SCristiano Giuffrida printf("vm_memctl(VM_RS_MEM_HEAP_PREALLOC) failed: %d\n", s); 776fb6bd596SCristiano Giuffrida cleanup_service(new_rp); 777fb6bd596SCristiano Giuffrida return s; 778fb6bd596SCristiano Giuffrida } 779fb6bd596SCristiano Giuffrida if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 780fb6bd596SCristiano Giuffrida vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_PIN, 0, 0); 781fb6bd596SCristiano Giuffrida } 782433d6423SLionel Sambuc } 783433d6423SLionel Sambuc 784fb6bd596SCristiano Giuffrida /* Preallocate mmapped regions if requested. */ 785fb6bd596SCristiano Giuffrida if(rs_start.rss_map_prealloc_bytes < 0) { 786fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes = 0; 787433d6423SLionel Sambuc } 788fb6bd596SCristiano Giuffrida if(rs_start.rss_map_prealloc_bytes) { 789fb6bd596SCristiano Giuffrida void *addr = NULL; 790fb6bd596SCristiano Giuffrida if(rs_verbose) 791fb6bd596SCristiano Giuffrida printf("RS: %s preallocating %ld mmap bytes\n", srv_to_string(new_rp), 792fb6bd596SCristiano Giuffrida rs_start.rss_map_prealloc_bytes); 793fb6bd596SCristiano Giuffrida 794fb6bd596SCristiano Giuffrida new_rp->r_map_prealloc_len = rs_start.rss_map_prealloc_bytes; 795fb6bd596SCristiano Giuffrida s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_MAP_PREALLOC, 796fb6bd596SCristiano Giuffrida &addr, &new_rp->r_map_prealloc_len); 797fb6bd596SCristiano Giuffrida if(s != OK) { 798fb6bd596SCristiano Giuffrida printf("vm_memctl(VM_RS_MEM_MAP_PREALLOC) failed: %d\n", s); 799fb6bd596SCristiano Giuffrida cleanup_service(new_rp); 800fb6bd596SCristiano Giuffrida return s; 801433d6423SLionel Sambuc } 802fb6bd596SCristiano Giuffrida new_rp->r_map_prealloc_addr = (vir_bytes) addr; 803fb6bd596SCristiano Giuffrida } 804fb6bd596SCristiano Giuffrida } 805fb6bd596SCristiano Giuffrida 806fb6bd596SCristiano Giuffrida /* Process state data. */ 807fb6bd596SCristiano Giuffrida s = init_state_data(m_ptr->m_source, prepare_state, &rs_start.rss_state_data, &rpupd->prepare_state_data); 808fb6bd596SCristiano Giuffrida if(s != OK) { 809fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 810fb6bd596SCristiano Giuffrida return s; 811fb6bd596SCristiano Giuffrida } 812fb6bd596SCristiano Giuffrida 813fb6bd596SCristiano Giuffrida /* Create update grants. */ 814fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data.size > 0) { 815fb6bd596SCristiano Giuffrida struct rs_state_data *state_data = &rpupd->prepare_state_data; 816fb6bd596SCristiano Giuffrida rpupd->prepare_state_data_gid = cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data, 817fb6bd596SCristiano Giuffrida state_data->size, CPF_READ); 818fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data_gid == GRANT_INVALID) { 819fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 820fb6bd596SCristiano Giuffrida return ENOMEM; 821fb6bd596SCristiano Giuffrida } 822fb6bd596SCristiano Giuffrida state_data->ipcf_els_gid = GRANT_INVALID; 823fb6bd596SCristiano Giuffrida if(state_data->ipcf_els) { 824fb6bd596SCristiano Giuffrida state_data->ipcf_els_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->ipcf_els, 825fb6bd596SCristiano Giuffrida state_data->ipcf_els_size, CPF_READ); 826fb6bd596SCristiano Giuffrida if(state_data->ipcf_els_gid == GRANT_INVALID) { 827fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 828fb6bd596SCristiano Giuffrida return ENOMEM; 829fb6bd596SCristiano Giuffrida } 830fb6bd596SCristiano Giuffrida } 831fb6bd596SCristiano Giuffrida state_data->eval_gid = GRANT_INVALID; 832fb6bd596SCristiano Giuffrida if(state_data->eval_addr) { 833fb6bd596SCristiano Giuffrida state_data->eval_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->eval_addr, 834fb6bd596SCristiano Giuffrida state_data->eval_len, CPF_READ); 835fb6bd596SCristiano Giuffrida if(state_data->eval_gid == GRANT_INVALID) { 836fb6bd596SCristiano Giuffrida rupdate_upd_clear(rpupd); 837fb6bd596SCristiano Giuffrida return ENOMEM; 838fb6bd596SCristiano Giuffrida } 839fb6bd596SCristiano Giuffrida } 840fb6bd596SCristiano Giuffrida } 841fb6bd596SCristiano Giuffrida 842fb6bd596SCristiano Giuffrida /* Fill the new update descriptor and add it to the update chain. */ 843fb6bd596SCristiano Giuffrida rpupd->prepare_state = prepare_state; 844fb6bd596SCristiano Giuffrida rpupd->state_endpoint = state_endpoint; 845*d91f738bSDavid van Moolenbroek rpupd->prepare_tm = getticks(); 846fb6bd596SCristiano Giuffrida rpupd->prepare_maxtime = prepare_maxtime; 847fb6bd596SCristiano Giuffrida rupdate_add_upd(rpupd); 848fb6bd596SCristiano Giuffrida 849fb6bd596SCristiano Giuffrida if(rs_verbose) 850fb6bd596SCristiano Giuffrida printf("RS: %s scheduled for %s\n", srv_to_string(rp), srv_upd_to_string(rpupd)); 851fb6bd596SCristiano Giuffrida 852fb6bd596SCristiano Giuffrida /* If batch mode, reply immediately. More services to update will follow. */ 853fb6bd596SCristiano Giuffrida if(batch_mode) { 854fb6bd596SCristiano Giuffrida return OK; 855fb6bd596SCristiano Giuffrida } 856fb6bd596SCristiano Giuffrida 857fb6bd596SCristiano Giuffrida /* Start preparing for the update process. */ 858fb6bd596SCristiano Giuffrida s = start_update_prepare(allow_retries); 859fb6bd596SCristiano Giuffrida if(s == ESRCH) { 860fb6bd596SCristiano Giuffrida /* No process left in the update chain. We are done already. */ 861fb6bd596SCristiano Giuffrida return OK; 862fb6bd596SCristiano Giuffrida } 863fb6bd596SCristiano Giuffrida if(s != OK) { 864fb6bd596SCristiano Giuffrida return s; 865fb6bd596SCristiano Giuffrida } 866fb6bd596SCristiano Giuffrida 867fb6bd596SCristiano Giuffrida /* Unblock the caller immediately if requested. */ 868fb6bd596SCristiano Giuffrida if(noblock) { 869fb6bd596SCristiano Giuffrida return OK; 870fb6bd596SCristiano Giuffrida } 871fb6bd596SCristiano Giuffrida 872fb6bd596SCristiano Giuffrida /* Otherwise, send a reply when the new version completes initialization. */ 873fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY; 874fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller = m_ptr->m_source; 875fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE; 876433d6423SLionel Sambuc 877433d6423SLionel Sambuc return EDONTREPLY; 878433d6423SLionel Sambuc } 879433d6423SLionel Sambuc 880433d6423SLionel Sambuc /*===========================================================================* 881433d6423SLionel Sambuc * do_upd_ready * 882433d6423SLionel Sambuc *===========================================================================*/ 883433d6423SLionel Sambuc int do_upd_ready(message *m_ptr) 884433d6423SLionel Sambuc { 885fb6bd596SCristiano Giuffrida struct rproc *rp; 886fb6bd596SCristiano Giuffrida struct rprocupd *prev_rpupd, *rpupd; 887433d6423SLionel Sambuc int who_p; 888433d6423SLionel Sambuc int result; 889433d6423SLionel Sambuc int is_rs; 890fb6bd596SCristiano Giuffrida int i; 891433d6423SLionel Sambuc 892433d6423SLionel Sambuc who_p = _ENDPOINT_P(m_ptr->m_source); 893433d6423SLionel Sambuc rp = rproc_ptr[who_p]; 894433d6423SLionel Sambuc result = m_ptr->m_rs_update.result; 895433d6423SLionel Sambuc 896433d6423SLionel Sambuc /* Make sure the originating service was requested to prepare for update. */ 897fb6bd596SCristiano Giuffrida rpupd = rupdate.curr_rpupd; 898fb6bd596SCristiano Giuffrida if(!rpupd || rp != rpupd->rp || RUPDATE_IS_INITIALIZING()) { 899433d6423SLionel Sambuc if(rs_verbose) 900fb6bd596SCristiano Giuffrida printf("RS: %s sent late/unexpected update ready msg\n", 901fb6bd596SCristiano Giuffrida srv_to_string(rp)); 902433d6423SLionel Sambuc return EINVAL; 903433d6423SLionel Sambuc } 904fb6bd596SCristiano Giuffrida rp->r_flags |= RS_PREPARE_DONE; 905433d6423SLionel Sambuc 906433d6423SLionel Sambuc /* Check if something went wrong and the service failed to prepare 907433d6423SLionel Sambuc * for the update. In that case, end the update process. The old version will 908433d6423SLionel Sambuc * be replied to and continue executing. 909433d6423SLionel Sambuc */ 910433d6423SLionel Sambuc if(result != OK) { 911fb6bd596SCristiano Giuffrida printf("RS: update failed: %s\n", lu_strerror(result)); 912433d6423SLionel Sambuc end_update(result, RS_REPLY); 913433d6423SLionel Sambuc 914433d6423SLionel Sambuc return EDONTREPLY; 915433d6423SLionel Sambuc } 916433d6423SLionel Sambuc 917fb6bd596SCristiano Giuffrida if(rs_verbose) 918fb6bd596SCristiano Giuffrida printf("RS: %s ready to update\n", srv_to_string(rp)); 919fb6bd596SCristiano Giuffrida 920fb6bd596SCristiano Giuffrida /* If this is a multi-component update and this is not the last service 921fb6bd596SCristiano Giuffrida * in the update, request the next process to update. 922fb6bd596SCristiano Giuffrida */ 923fb6bd596SCristiano Giuffrida if(start_update_prepare_next() != NULL) { 924433d6423SLionel Sambuc return EDONTREPLY; 925433d6423SLionel Sambuc } 926433d6423SLionel Sambuc 927fb6bd596SCristiano Giuffrida /* Now perform the update and request each new instance to initialize. */ 928fb6bd596SCristiano Giuffrida start_update(); 929fb6bd596SCristiano Giuffrida 930433d6423SLionel Sambuc return EDONTREPLY; 931433d6423SLionel Sambuc } 932433d6423SLionel Sambuc 933433d6423SLionel Sambuc /*===========================================================================* 934433d6423SLionel Sambuc * do_period * 935433d6423SLionel Sambuc *===========================================================================*/ 936433d6423SLionel Sambuc void do_period(m_ptr) 937433d6423SLionel Sambuc message *m_ptr; 938433d6423SLionel Sambuc { 939433d6423SLionel Sambuc register struct rproc *rp; 940433d6423SLionel Sambuc register struct rprocpub *rpub; 941433d6423SLionel Sambuc clock_t now = m_ptr->m_notify.timestamp; 942433d6423SLionel Sambuc int s; 943433d6423SLionel Sambuc long period; 944433d6423SLionel Sambuc 945433d6423SLionel Sambuc /* If an update is in progress, check its status. */ 946fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPDATING() && !RUPDATE_IS_INITIALIZING()) { 947433d6423SLionel Sambuc update_period(m_ptr); 948433d6423SLionel Sambuc } 949433d6423SLionel Sambuc 950433d6423SLionel Sambuc /* Search system services table. Only check slots that are in use and not 951433d6423SLionel Sambuc * updating. 952433d6423SLionel Sambuc */ 953433d6423SLionel Sambuc for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { 954433d6423SLionel Sambuc rpub = rp->r_pub; 955fb6bd596SCristiano Giuffrida 956fb6bd596SCristiano Giuffrida if ((rp->r_flags & RS_ACTIVE) && (!SRV_IS_UPDATING(rp) || ((rp->r_flags & (RS_INITIALIZING|RS_INIT_DONE|RS_INIT_PENDING)) == RS_INITIALIZING))) { 957433d6423SLionel Sambuc 958433d6423SLionel Sambuc /* Compute period. */ 959433d6423SLionel Sambuc period = rp->r_period; 960433d6423SLionel Sambuc if(rp->r_flags & RS_INITIALIZING) { 961fb6bd596SCristiano Giuffrida period = SRV_IS_UPDATING(rp) ? UPD_INIT_MAXTIME(&rp->r_upd) : RS_INIT_T; 962433d6423SLionel Sambuc } 963433d6423SLionel Sambuc 964433d6423SLionel Sambuc /* If the service is to be revived (because it repeatedly exited, 965433d6423SLionel Sambuc * and was not directly restarted), the binary backoff field is 966433d6423SLionel Sambuc * greater than zero. 967433d6423SLionel Sambuc */ 968433d6423SLionel Sambuc if (rp->r_backoff > 0) { 969433d6423SLionel Sambuc rp->r_backoff -= 1; 970433d6423SLionel Sambuc if (rp->r_backoff == 0) { 971433d6423SLionel Sambuc restart_service(rp); 972433d6423SLionel Sambuc } 973433d6423SLionel Sambuc } 974433d6423SLionel Sambuc 975433d6423SLionel Sambuc /* If the service was signaled with a SIGTERM and fails to respond, 976433d6423SLionel Sambuc * kill the system service with a SIGKILL signal. 977433d6423SLionel Sambuc */ 978433d6423SLionel Sambuc else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T 979433d6423SLionel Sambuc && rp->r_pid > 0) { 980433d6423SLionel Sambuc rp->r_stop_tm = 0; 981433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 982433d6423SLionel Sambuc } 983433d6423SLionel Sambuc 984433d6423SLionel Sambuc /* There seems to be no special conditions. If the service has a 985433d6423SLionel Sambuc * period assigned check its status. 986433d6423SLionel Sambuc */ 987433d6423SLionel Sambuc else if (period > 0) { 988433d6423SLionel Sambuc 989433d6423SLionel Sambuc /* Check if an answer to a status request is still pending. If 990433d6423SLionel Sambuc * the service didn't respond within time, kill it to simulate 991433d6423SLionel Sambuc * a crash. The failure will be detected and the service will 992433d6423SLionel Sambuc * be restarted automatically. Give the service a free pass if 993433d6423SLionel Sambuc * somebody is initializing. There may be some weird dependencies 994433d6423SLionel Sambuc * if another service is, for example, restarting at the same 995433d6423SLionel Sambuc * time. 996433d6423SLionel Sambuc */ 997433d6423SLionel Sambuc if (rp->r_alive_tm < rp->r_check_tm) { 998433d6423SLionel Sambuc if (now - rp->r_alive_tm > 2*period && 999433d6423SLionel Sambuc rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) { 1000fb6bd596SCristiano Giuffrida struct rproc *rp2; 1001fb6bd596SCristiano Giuffrida int init_flag; 1002433d6423SLionel Sambuc if(rs_verbose) 1003433d6423SLionel Sambuc printf("RS: %s reported late\n", srv_to_string(rp)); 1004fb6bd596SCristiano Giuffrida init_flag = rp->r_flags & RS_INITIALIZING; 1005fb6bd596SCristiano Giuffrida rp->r_flags &= ~RS_INITIALIZING; 1006fb6bd596SCristiano Giuffrida rp2 = lookup_slot_by_flags(RS_INITIALIZING); 1007fb6bd596SCristiano Giuffrida rp->r_flags |= init_flag; 1008fb6bd596SCristiano Giuffrida if(rp2 != NULL && !SRV_IS_UPDATING(rp)) { 1009433d6423SLionel Sambuc /* Skip for now. */ 1010433d6423SLionel Sambuc if(rs_verbose) 1011433d6423SLionel Sambuc printf("RS: %s gets a free pass\n", 1012433d6423SLionel Sambuc srv_to_string(rp)); 1013433d6423SLionel Sambuc rp->r_alive_tm = now; 1014433d6423SLionel Sambuc rp->r_check_tm = now+1; 1015433d6423SLionel Sambuc continue; 1016433d6423SLionel Sambuc } 1017433d6423SLionel Sambuc rp->r_flags |= RS_NOPINGREPLY; 1018433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 1019fb6bd596SCristiano Giuffrida if(rp->r_flags & RS_INITIALIZING) { 1020fb6bd596SCristiano Giuffrida rp->r_init_err = EINTR; 1021fb6bd596SCristiano Giuffrida } 1022433d6423SLionel Sambuc } 1023433d6423SLionel Sambuc } 1024433d6423SLionel Sambuc 1025433d6423SLionel Sambuc /* No answer pending. Check if a period expired since the last 1026433d6423SLionel Sambuc * check and, if so request the system service's status. 1027433d6423SLionel Sambuc */ 1028433d6423SLionel Sambuc else if (now - rp->r_check_tm > rp->r_period) { 1029433d6423SLionel Sambuc ipc_notify(rpub->endpoint); /* request status */ 1030433d6423SLionel Sambuc rp->r_check_tm = now; /* mark time */ 1031433d6423SLionel Sambuc } 1032433d6423SLionel Sambuc } 1033433d6423SLionel Sambuc } 1034433d6423SLionel Sambuc } 1035433d6423SLionel Sambuc 1036433d6423SLionel Sambuc /* Reschedule a synchronous alarm for the next period. */ 1037433d6423SLionel Sambuc if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) 1038433d6423SLionel Sambuc panic("couldn't set alarm: %d", s); 1039433d6423SLionel Sambuc } 1040433d6423SLionel Sambuc 1041433d6423SLionel Sambuc /*===========================================================================* 1042433d6423SLionel Sambuc * do_sigchld * 1043433d6423SLionel Sambuc *===========================================================================*/ 1044433d6423SLionel Sambuc void do_sigchld() 1045433d6423SLionel Sambuc { 1046433d6423SLionel Sambuc /* PM informed us that there are dead children to cleanup. Go get them. */ 1047433d6423SLionel Sambuc pid_t pid; 1048433d6423SLionel Sambuc int status; 1049433d6423SLionel Sambuc struct rproc *rp; 1050433d6423SLionel Sambuc struct rproc **rps; 1051fb6bd596SCristiano Giuffrida int i, nr_rps, found; 1052433d6423SLionel Sambuc 1053433d6423SLionel Sambuc if(rs_verbose) 1054433d6423SLionel Sambuc printf("RS: got SIGCHLD signal, cleaning up dead children\n"); 1055433d6423SLionel Sambuc 1056433d6423SLionel Sambuc while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) { 1057433d6423SLionel Sambuc rp = lookup_slot_by_pid(pid); 1058433d6423SLionel Sambuc if(rp != NULL) { 1059433d6423SLionel Sambuc 1060433d6423SLionel Sambuc if(rs_verbose) 1061433d6423SLionel Sambuc printf("RS: %s exited via another signal manager\n", 1062433d6423SLionel Sambuc srv_to_string(rp)); 1063433d6423SLionel Sambuc 1064433d6423SLionel Sambuc /* The slot is still there. This means RS is not the signal 1065433d6423SLionel Sambuc * manager assigned to the process. Ignore the event but 1066433d6423SLionel Sambuc * free slots for all the service instances and send a late 1067433d6423SLionel Sambuc * reply if necessary. 1068433d6423SLionel Sambuc */ 1069fb6bd596SCristiano Giuffrida found = 0; 1070433d6423SLionel Sambuc get_service_instances(rp, &rps, &nr_rps); 1071433d6423SLionel Sambuc for(i=0;i<nr_rps;i++) { 1072fb6bd596SCristiano Giuffrida if(SRV_IS_UPDATING(rps[i])) { 1073fb6bd596SCristiano Giuffrida rps[i]->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING); 1074fb6bd596SCristiano Giuffrida found = 1; 1075433d6423SLionel Sambuc } 1076433d6423SLionel Sambuc free_slot(rps[i]); 1077433d6423SLionel Sambuc } 1078fb6bd596SCristiano Giuffrida if(found) { 1079fb6bd596SCristiano Giuffrida rupdate_clear_upds(); 1080fb6bd596SCristiano Giuffrida } 1081433d6423SLionel Sambuc } 1082433d6423SLionel Sambuc } 1083433d6423SLionel Sambuc } 1084433d6423SLionel Sambuc 1085433d6423SLionel Sambuc /*===========================================================================* 1086433d6423SLionel Sambuc * do_getsysinfo * 1087433d6423SLionel Sambuc *===========================================================================*/ 1088433d6423SLionel Sambuc int do_getsysinfo(m_ptr) 1089433d6423SLionel Sambuc message *m_ptr; 1090433d6423SLionel Sambuc { 1091433d6423SLionel Sambuc vir_bytes src_addr, dst_addr; 1092433d6423SLionel Sambuc int dst_proc; 10930eabb93cSDavid van Moolenbroek size_t size, len; 1094433d6423SLionel Sambuc int s; 1095433d6423SLionel Sambuc 1096433d6423SLionel Sambuc /* Check if the call can be allowed. */ 1097433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK) 1098433d6423SLionel Sambuc return s; 1099433d6423SLionel Sambuc 11000eabb93cSDavid van Moolenbroek dst_proc = m_ptr->m_source; 11010eabb93cSDavid van Moolenbroek dst_addr = m_ptr->m_lsys_getsysinfo.where; 11020eabb93cSDavid van Moolenbroek size = m_ptr->m_lsys_getsysinfo.size; 11030eabb93cSDavid van Moolenbroek 1104433d6423SLionel Sambuc switch(m_ptr->m_lsys_getsysinfo.what) { 1105433d6423SLionel Sambuc case SI_PROC_TAB: 1106433d6423SLionel Sambuc src_addr = (vir_bytes) rproc; 1107433d6423SLionel Sambuc len = sizeof(struct rproc) * NR_SYS_PROCS; 1108433d6423SLionel Sambuc break; 11090eabb93cSDavid van Moolenbroek case SI_PROCALL_TAB: 11100eabb93cSDavid van Moolenbroek /* Copy out both tables, one after the other. */ 11110eabb93cSDavid van Moolenbroek src_addr = (vir_bytes) rproc; 11120eabb93cSDavid van Moolenbroek len = sizeof(struct rproc) * NR_SYS_PROCS; 11130eabb93cSDavid van Moolenbroek if (len > size) 11140eabb93cSDavid van Moolenbroek return EINVAL; 11150eabb93cSDavid van Moolenbroek if ((s = sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)) != OK) 11160eabb93cSDavid van Moolenbroek return s; 11170eabb93cSDavid van Moolenbroek dst_addr += len; 11180eabb93cSDavid van Moolenbroek size -= len; 11190eabb93cSDavid van Moolenbroek /* FALLTHROUGH */ 1120433d6423SLionel Sambuc case SI_PROCPUB_TAB: 1121433d6423SLionel Sambuc src_addr = (vir_bytes) rprocpub; 1122433d6423SLionel Sambuc len = sizeof(struct rprocpub) * NR_SYS_PROCS; 1123433d6423SLionel Sambuc break; 1124433d6423SLionel Sambuc default: 1125433d6423SLionel Sambuc return(EINVAL); 1126433d6423SLionel Sambuc } 1127433d6423SLionel Sambuc 11280eabb93cSDavid van Moolenbroek if (len != size) 1129433d6423SLionel Sambuc return(EINVAL); 1130433d6423SLionel Sambuc 1131433d6423SLionel Sambuc return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len); 1132433d6423SLionel Sambuc } 1133433d6423SLionel Sambuc 1134433d6423SLionel Sambuc /*===========================================================================* 1135433d6423SLionel Sambuc * do_lookup * 1136433d6423SLionel Sambuc *===========================================================================*/ 1137433d6423SLionel Sambuc int do_lookup(m_ptr) 1138433d6423SLionel Sambuc message *m_ptr; 1139433d6423SLionel Sambuc { 1140433d6423SLionel Sambuc static char namebuf[100]; 1141433d6423SLionel Sambuc int len, r; 1142433d6423SLionel Sambuc struct rproc *rrp; 1143433d6423SLionel Sambuc struct rprocpub *rrpub; 1144433d6423SLionel Sambuc 1145433d6423SLionel Sambuc len = m_ptr->m_rs_req.name_len; 1146433d6423SLionel Sambuc 1147433d6423SLionel Sambuc if(len < 2 || len >= sizeof(namebuf)) { 1148433d6423SLionel Sambuc printf("RS: len too weird (%d)\n", len); 1149433d6423SLionel Sambuc return EINVAL; 1150433d6423SLionel Sambuc } 1151433d6423SLionel Sambuc 1152433d6423SLionel Sambuc if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name, 1153433d6423SLionel Sambuc SELF, (vir_bytes) namebuf, len)) != OK) { 1154433d6423SLionel Sambuc printf("RS: name copy failed\n"); 1155433d6423SLionel Sambuc return r; 1156433d6423SLionel Sambuc 1157433d6423SLionel Sambuc } 1158433d6423SLionel Sambuc 1159433d6423SLionel Sambuc namebuf[len] = '\0'; 1160433d6423SLionel Sambuc 1161433d6423SLionel Sambuc rrp = lookup_slot_by_label(namebuf); 1162433d6423SLionel Sambuc if(!rrp) { 1163433d6423SLionel Sambuc return ESRCH; 1164433d6423SLionel Sambuc } 1165433d6423SLionel Sambuc rrpub = rrp->r_pub; 1166433d6423SLionel Sambuc m_ptr->m_rs_req.endpoint = rrpub->endpoint; 1167433d6423SLionel Sambuc 1168433d6423SLionel Sambuc return OK; 1169433d6423SLionel Sambuc } 1170433d6423SLionel Sambuc 1171433d6423SLionel Sambuc /*===========================================================================* 1172fb6bd596SCristiano Giuffrida * do_sysctl * 1173fb6bd596SCristiano Giuffrida *===========================================================================*/ 1174fb6bd596SCristiano Giuffrida int do_sysctl(message *m_ptr) 1175fb6bd596SCristiano Giuffrida { 1176fb6bd596SCristiano Giuffrida int request_type = m_ptr->m_rs_req.subtype; 1177fb6bd596SCristiano Giuffrida int r, allow_retries = 1; 1178fb6bd596SCristiano Giuffrida switch(request_type) { 1179fb6bd596SCristiano Giuffrida case RS_SYSCTL_SRV_STATUS: 1180fb6bd596SCristiano Giuffrida print_services_status(); 1181fb6bd596SCristiano Giuffrida break; 1182fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_START: 1183fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_RUN: 1184fb6bd596SCristiano Giuffrida r = start_update_prepare(allow_retries); 1185fb6bd596SCristiano Giuffrida print_update_status(); 1186fb6bd596SCristiano Giuffrida if(r != OK) { 1187fb6bd596SCristiano Giuffrida if(r == ESRCH) { 1188fb6bd596SCristiano Giuffrida /* We are done already. */ 1189fb6bd596SCristiano Giuffrida r = OK; 1190fb6bd596SCristiano Giuffrida } 1191fb6bd596SCristiano Giuffrida return r; 1192fb6bd596SCristiano Giuffrida } 1193fb6bd596SCristiano Giuffrida if(request_type == RS_SYSCTL_UPD_START) { 1194fb6bd596SCristiano Giuffrida return OK; 1195fb6bd596SCristiano Giuffrida } 1196fb6bd596SCristiano Giuffrida /* Send a reply when done. */ 1197fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY; 1198fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller = m_ptr->m_source; 1199fb6bd596SCristiano Giuffrida rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE; 1200fb6bd596SCristiano Giuffrida return EDONTREPLY; 1201fb6bd596SCristiano Giuffrida break; 1202fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_STOP: 1203fb6bd596SCristiano Giuffrida r = abort_update_proc(EINTR); 1204fb6bd596SCristiano Giuffrida print_update_status(); 1205fb6bd596SCristiano Giuffrida return r; 1206fb6bd596SCristiano Giuffrida break; 1207fb6bd596SCristiano Giuffrida case RS_SYSCTL_UPD_STATUS: 1208fb6bd596SCristiano Giuffrida print_update_status(); 1209fb6bd596SCristiano Giuffrida break; 1210fb6bd596SCristiano Giuffrida default: 1211fb6bd596SCristiano Giuffrida printf("RS: bad sysctl type\n"); 1212fb6bd596SCristiano Giuffrida return EINVAL; 1213fb6bd596SCristiano Giuffrida break; 1214fb6bd596SCristiano Giuffrida } 1215fb6bd596SCristiano Giuffrida 1216fb6bd596SCristiano Giuffrida return OK; 1217fb6bd596SCristiano Giuffrida } 1218fb6bd596SCristiano Giuffrida 1219fb6bd596SCristiano Giuffrida /*===========================================================================* 12203837bb5cSCristiano Giuffrida * do_fi * 12213837bb5cSCristiano Giuffrida *===========================================================================*/ 12223837bb5cSCristiano Giuffrida int do_fi(message *m_ptr) 12233837bb5cSCristiano Giuffrida { 12243837bb5cSCristiano Giuffrida struct rproc *rp; 12253837bb5cSCristiano Giuffrida struct rprocpub *rpub; 12263837bb5cSCristiano Giuffrida int s, r; 12273837bb5cSCristiano Giuffrida char label[RS_MAX_LABEL_LEN]; 12283837bb5cSCristiano Giuffrida 12293837bb5cSCristiano Giuffrida /* Copy label. */ 12303837bb5cSCristiano Giuffrida s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 12313837bb5cSCristiano Giuffrida m_ptr->m_rs_req.len, label, sizeof(label)); 12323837bb5cSCristiano Giuffrida if(s != OK) { 12333837bb5cSCristiano Giuffrida return s; 12343837bb5cSCristiano Giuffrida } 12353837bb5cSCristiano Giuffrida 12363837bb5cSCristiano Giuffrida /* Lookup slot by label. */ 12373837bb5cSCristiano Giuffrida rp = lookup_slot_by_label(label); 12383837bb5cSCristiano Giuffrida if(!rp) { 12393837bb5cSCristiano Giuffrida if(rs_verbose) 12403837bb5cSCristiano Giuffrida printf("RS: do_fi: service '%s' not found\n", label); 12413837bb5cSCristiano Giuffrida return(ESRCH); 12423837bb5cSCristiano Giuffrida } 12433837bb5cSCristiano Giuffrida rpub = rp->r_pub; 12443837bb5cSCristiano Giuffrida 12453837bb5cSCristiano Giuffrida /* Check if the call can be allowed. */ 12463837bb5cSCristiano Giuffrida if((r = check_call_permission(m_ptr->m_source, RS_FI, rp)) != OK) 12473837bb5cSCristiano Giuffrida return r; 12483837bb5cSCristiano Giuffrida 12493837bb5cSCristiano Giuffrida /* Inject fault into the service as requested. */ 12503837bb5cSCristiano Giuffrida s = fi_service(rp); 12513837bb5cSCristiano Giuffrida 12523837bb5cSCristiano Giuffrida return s; 12533837bb5cSCristiano Giuffrida } 12543837bb5cSCristiano Giuffrida 12553837bb5cSCristiano Giuffrida /*===========================================================================* 1256433d6423SLionel Sambuc * check_request * 1257433d6423SLionel Sambuc *===========================================================================*/ 1258433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start) 1259433d6423SLionel Sambuc { 1260433d6423SLionel Sambuc /* Verify scheduling parameters */ 1261433d6423SLionel Sambuc if (rs_start->rss_scheduler != KERNEL && 1262433d6423SLionel Sambuc (rs_start->rss_scheduler < 0 || 1263433d6423SLionel Sambuc rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) { 1264433d6423SLionel Sambuc printf("RS: check_request: invalid scheduler %d\n", 1265433d6423SLionel Sambuc rs_start->rss_scheduler); 1266433d6423SLionel Sambuc return EINVAL; 1267433d6423SLionel Sambuc } 1268433d6423SLionel Sambuc if (rs_start->rss_priority >= NR_SCHED_QUEUES) { 1269433d6423SLionel Sambuc printf("RS: check_request: priority %u out of range\n", 1270433d6423SLionel Sambuc rs_start->rss_priority); 1271433d6423SLionel Sambuc return EINVAL; 1272433d6423SLionel Sambuc } 1273433d6423SLionel Sambuc if (rs_start->rss_quantum <= 0) { 1274433d6423SLionel Sambuc printf("RS: check_request: quantum %u out of range\n", 1275433d6423SLionel Sambuc rs_start->rss_quantum); 1276433d6423SLionel Sambuc return EINVAL; 1277433d6423SLionel Sambuc } 1278433d6423SLionel Sambuc 1279433d6423SLionel Sambuc if (rs_start->rss_cpu == RS_CPU_BSP) 1280433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 1281433d6423SLionel Sambuc else if (rs_start->rss_cpu == RS_CPU_DEFAULT) { 1282433d6423SLionel Sambuc /* keep the default value */ 1283433d6423SLionel Sambuc } else if (rs_start->rss_cpu < 0) 1284433d6423SLionel Sambuc return EINVAL; 1285433d6423SLionel Sambuc else if (rs_start->rss_cpu > machine.processors_count) { 1286433d6423SLionel Sambuc printf("RS: cpu number %d out of range 0-%d, using BSP\n", 1287433d6423SLionel Sambuc rs_start->rss_cpu, machine.processors_count); 1288433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 1289433d6423SLionel Sambuc } 1290433d6423SLionel Sambuc 1291433d6423SLionel Sambuc /* Verify signal manager. */ 1292433d6423SLionel Sambuc if (rs_start->rss_sigmgr != SELF && 1293433d6423SLionel Sambuc (rs_start->rss_sigmgr < 0 || 1294433d6423SLionel Sambuc rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) { 1295433d6423SLionel Sambuc printf("RS: check_request: invalid signal manager %d\n", 1296433d6423SLionel Sambuc rs_start->rss_sigmgr); 1297433d6423SLionel Sambuc return EINVAL; 1298433d6423SLionel Sambuc } 1299433d6423SLionel Sambuc 1300433d6423SLionel Sambuc return OK; 1301433d6423SLionel Sambuc } 1302433d6423SLionel Sambuc 1303