1*433d6423SLionel Sambuc /* 2*433d6423SLionel Sambuc * Changes: 3*433d6423SLionel Sambuc * Jan 22, 2010: Created (Cristiano Giuffrida) 4*433d6423SLionel Sambuc */ 5*433d6423SLionel Sambuc 6*433d6423SLionel Sambuc #include "inc.h" 7*433d6423SLionel Sambuc 8*433d6423SLionel Sambuc #include "kernel/proc.h" 9*433d6423SLionel Sambuc 10*433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start); 11*433d6423SLionel Sambuc 12*433d6423SLionel Sambuc /*===========================================================================* 13*433d6423SLionel Sambuc * do_up * 14*433d6423SLionel Sambuc *===========================================================================*/ 15*433d6423SLionel Sambuc int do_up(m_ptr) 16*433d6423SLionel Sambuc message *m_ptr; /* request message pointer */ 17*433d6423SLionel Sambuc { 18*433d6423SLionel Sambuc /* A request was made to start a new system service. */ 19*433d6423SLionel Sambuc struct rproc *rp; 20*433d6423SLionel Sambuc struct rprocpub *rpub; 21*433d6423SLionel Sambuc int r; 22*433d6423SLionel Sambuc struct rs_start rs_start; 23*433d6423SLionel Sambuc int noblock; 24*433d6423SLionel Sambuc 25*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 26*433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK) 27*433d6423SLionel Sambuc return r; 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc /* Allocate a new system service slot. */ 30*433d6423SLionel Sambuc r = alloc_slot(&rp); 31*433d6423SLionel Sambuc if(r != OK) { 32*433d6423SLionel Sambuc printf("RS: do_up: unable to allocate a new slot: %d\n", r); 33*433d6423SLionel Sambuc return r; 34*433d6423SLionel Sambuc } 35*433d6423SLionel Sambuc rpub = rp->r_pub; 36*433d6423SLionel Sambuc 37*433d6423SLionel Sambuc /* Copy the request structure. */ 38*433d6423SLionel Sambuc r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 39*433d6423SLionel Sambuc if (r != OK) { 40*433d6423SLionel Sambuc return r; 41*433d6423SLionel Sambuc } 42*433d6423SLionel Sambuc r = check_request(&rs_start); 43*433d6423SLionel Sambuc if (r != OK) { 44*433d6423SLionel Sambuc return r; 45*433d6423SLionel Sambuc } 46*433d6423SLionel Sambuc noblock = (rs_start.rss_flags & RSS_NOBLOCK); 47*433d6423SLionel Sambuc 48*433d6423SLionel Sambuc /* Initialize the slot as requested. */ 49*433d6423SLionel Sambuc r = init_slot(rp, &rs_start, m_ptr->m_source); 50*433d6423SLionel Sambuc if(r != OK) { 51*433d6423SLionel Sambuc printf("RS: do_up: unable to init the new slot: %d\n", r); 52*433d6423SLionel Sambuc return r; 53*433d6423SLionel Sambuc } 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc /* Check for duplicates */ 56*433d6423SLionel Sambuc if(lookup_slot_by_label(rpub->label)) { 57*433d6423SLionel Sambuc printf("RS: service with the same label '%s' already exists\n", 58*433d6423SLionel Sambuc rpub->label); 59*433d6423SLionel Sambuc return EBUSY; 60*433d6423SLionel Sambuc } 61*433d6423SLionel Sambuc if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) { 62*433d6423SLionel Sambuc printf("RS: service with the same device number %d already exists\n", 63*433d6423SLionel Sambuc rpub->dev_nr); 64*433d6423SLionel Sambuc return EBUSY; 65*433d6423SLionel Sambuc } 66*433d6423SLionel Sambuc 67*433d6423SLionel Sambuc /* All information was gathered. Now try to start the system service. */ 68*433d6423SLionel Sambuc r = start_service(rp); 69*433d6423SLionel Sambuc if(r != OK) { 70*433d6423SLionel Sambuc return r; 71*433d6423SLionel Sambuc } 72*433d6423SLionel Sambuc 73*433d6423SLionel Sambuc /* Unblock the caller immediately if requested. */ 74*433d6423SLionel Sambuc if(noblock) { 75*433d6423SLionel Sambuc return OK; 76*433d6423SLionel Sambuc } 77*433d6423SLionel Sambuc 78*433d6423SLionel Sambuc /* Late reply - send a reply when service completes initialization. */ 79*433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 80*433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 81*433d6423SLionel Sambuc rp->r_caller_request = RS_UP; 82*433d6423SLionel Sambuc 83*433d6423SLionel Sambuc return EDONTREPLY; 84*433d6423SLionel Sambuc } 85*433d6423SLionel Sambuc 86*433d6423SLionel Sambuc /*===========================================================================* 87*433d6423SLionel Sambuc * do_down * 88*433d6423SLionel Sambuc *===========================================================================*/ 89*433d6423SLionel Sambuc int do_down(message *m_ptr) 90*433d6423SLionel Sambuc { 91*433d6423SLionel Sambuc register struct rproc *rp; 92*433d6423SLionel Sambuc int s; 93*433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 94*433d6423SLionel Sambuc 95*433d6423SLionel Sambuc /* Copy label. */ 96*433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 97*433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 98*433d6423SLionel Sambuc if(s != OK) { 99*433d6423SLionel Sambuc return s; 100*433d6423SLionel Sambuc } 101*433d6423SLionel Sambuc 102*433d6423SLionel Sambuc /* Lookup slot by label. */ 103*433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 104*433d6423SLionel Sambuc if(!rp) { 105*433d6423SLionel Sambuc if(rs_verbose) 106*433d6423SLionel Sambuc printf("RS: do_down: service '%s' not found\n", label); 107*433d6423SLionel Sambuc return(ESRCH); 108*433d6423SLionel Sambuc } 109*433d6423SLionel Sambuc 110*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 111*433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK) 112*433d6423SLionel Sambuc return s; 113*433d6423SLionel Sambuc 114*433d6423SLionel Sambuc /* Stop service. */ 115*433d6423SLionel Sambuc if (rp->r_flags & RS_TERMINATED) { 116*433d6423SLionel Sambuc /* A recovery script is requesting us to bring down the service. 117*433d6423SLionel Sambuc * The service is already gone, simply perform cleanup. 118*433d6423SLionel Sambuc */ 119*433d6423SLionel Sambuc if(rs_verbose) 120*433d6423SLionel Sambuc printf("RS: recovery script performs service down...\n"); 121*433d6423SLionel Sambuc unpublish_service(rp); 122*433d6423SLionel Sambuc cleanup_service(rp); 123*433d6423SLionel Sambuc return(OK); 124*433d6423SLionel Sambuc } 125*433d6423SLionel Sambuc stop_service(rp,RS_EXITING); 126*433d6423SLionel Sambuc 127*433d6423SLionel Sambuc /* Late reply - send a reply when service dies. */ 128*433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 129*433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 130*433d6423SLionel Sambuc rp->r_caller_request = RS_DOWN; 131*433d6423SLionel Sambuc 132*433d6423SLionel Sambuc return EDONTREPLY; 133*433d6423SLionel Sambuc } 134*433d6423SLionel Sambuc 135*433d6423SLionel Sambuc /*===========================================================================* 136*433d6423SLionel Sambuc * do_restart * 137*433d6423SLionel Sambuc *===========================================================================*/ 138*433d6423SLionel Sambuc int do_restart(message *m_ptr) 139*433d6423SLionel Sambuc { 140*433d6423SLionel Sambuc struct rproc *rp; 141*433d6423SLionel Sambuc int s, r; 142*433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 143*433d6423SLionel Sambuc char script[MAX_SCRIPT_LEN]; 144*433d6423SLionel Sambuc 145*433d6423SLionel Sambuc /* Copy label. */ 146*433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 147*433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 148*433d6423SLionel Sambuc if(s != OK) { 149*433d6423SLionel Sambuc return s; 150*433d6423SLionel Sambuc } 151*433d6423SLionel Sambuc 152*433d6423SLionel Sambuc /* Lookup slot by label. */ 153*433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 154*433d6423SLionel Sambuc if(!rp) { 155*433d6423SLionel Sambuc if(rs_verbose) 156*433d6423SLionel Sambuc printf("RS: do_restart: service '%s' not found\n", label); 157*433d6423SLionel Sambuc return(ESRCH); 158*433d6423SLionel Sambuc } 159*433d6423SLionel Sambuc 160*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 161*433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK) 162*433d6423SLionel Sambuc return r; 163*433d6423SLionel Sambuc 164*433d6423SLionel Sambuc /* We can only be asked to restart a service from a recovery script. */ 165*433d6423SLionel Sambuc if (! (rp->r_flags & RS_TERMINATED) ) { 166*433d6423SLionel Sambuc if(rs_verbose) 167*433d6423SLionel Sambuc printf("RS: %s is still running\n", srv_to_string(rp)); 168*433d6423SLionel Sambuc return EBUSY; 169*433d6423SLionel Sambuc } 170*433d6423SLionel Sambuc 171*433d6423SLionel Sambuc if(rs_verbose) 172*433d6423SLionel Sambuc printf("RS: recovery script performs service restart...\n"); 173*433d6423SLionel Sambuc 174*433d6423SLionel Sambuc /* Restart the service, but make sure we don't call the script again. */ 175*433d6423SLionel Sambuc strcpy(script, rp->r_script); 176*433d6423SLionel Sambuc rp->r_script[0] = '\0'; 177*433d6423SLionel Sambuc restart_service(rp); 178*433d6423SLionel Sambuc strcpy(rp->r_script, script); 179*433d6423SLionel Sambuc 180*433d6423SLionel Sambuc return OK; 181*433d6423SLionel Sambuc } 182*433d6423SLionel Sambuc 183*433d6423SLionel Sambuc /*===========================================================================* 184*433d6423SLionel Sambuc * do_clone * 185*433d6423SLionel Sambuc *===========================================================================*/ 186*433d6423SLionel Sambuc int do_clone(message *m_ptr) 187*433d6423SLionel Sambuc { 188*433d6423SLionel Sambuc struct rproc *rp; 189*433d6423SLionel Sambuc struct rprocpub *rpub; 190*433d6423SLionel Sambuc int s, r; 191*433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 192*433d6423SLionel Sambuc 193*433d6423SLionel Sambuc /* Copy label. */ 194*433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 195*433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 196*433d6423SLionel Sambuc if(s != OK) { 197*433d6423SLionel Sambuc return s; 198*433d6423SLionel Sambuc } 199*433d6423SLionel Sambuc 200*433d6423SLionel Sambuc /* Lookup slot by label. */ 201*433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 202*433d6423SLionel Sambuc if(!rp) { 203*433d6423SLionel Sambuc if(rs_verbose) 204*433d6423SLionel Sambuc printf("RS: do_clone: service '%s' not found\n", label); 205*433d6423SLionel Sambuc return(ESRCH); 206*433d6423SLionel Sambuc } 207*433d6423SLionel Sambuc rpub = rp->r_pub; 208*433d6423SLionel Sambuc 209*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 210*433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK) 211*433d6423SLionel Sambuc return r; 212*433d6423SLionel Sambuc 213*433d6423SLionel Sambuc /* Don't clone if a replica is already available. */ 214*433d6423SLionel Sambuc if(rp->r_next_rp) { 215*433d6423SLionel Sambuc return EEXIST; 216*433d6423SLionel Sambuc } 217*433d6423SLionel Sambuc 218*433d6423SLionel Sambuc /* Clone the service as requested. */ 219*433d6423SLionel Sambuc rpub->sys_flags |= SF_USE_REPL; 220*433d6423SLionel Sambuc if ((r = clone_service(rp, RST_SYS_PROC)) != OK) { 221*433d6423SLionel Sambuc rpub->sys_flags &= ~SF_USE_REPL; 222*433d6423SLionel Sambuc return r; 223*433d6423SLionel Sambuc } 224*433d6423SLionel Sambuc 225*433d6423SLionel Sambuc return OK; 226*433d6423SLionel Sambuc } 227*433d6423SLionel Sambuc 228*433d6423SLionel Sambuc /*===========================================================================* 229*433d6423SLionel Sambuc * do_edit * 230*433d6423SLionel Sambuc *===========================================================================*/ 231*433d6423SLionel Sambuc int do_edit(message *m_ptr) 232*433d6423SLionel Sambuc { 233*433d6423SLionel Sambuc struct rproc *rp; 234*433d6423SLionel Sambuc struct rprocpub *rpub; 235*433d6423SLionel Sambuc struct rs_start rs_start; 236*433d6423SLionel Sambuc int r; 237*433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 238*433d6423SLionel Sambuc 239*433d6423SLionel Sambuc /* Copy the request structure. */ 240*433d6423SLionel Sambuc r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 241*433d6423SLionel Sambuc if (r != OK) { 242*433d6423SLionel Sambuc return r; 243*433d6423SLionel Sambuc } 244*433d6423SLionel Sambuc 245*433d6423SLionel Sambuc /* Copy label. */ 246*433d6423SLionel Sambuc r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 247*433d6423SLionel Sambuc rs_start.rss_label.l_len, label, sizeof(label)); 248*433d6423SLionel Sambuc if(r != OK) { 249*433d6423SLionel Sambuc return r; 250*433d6423SLionel Sambuc } 251*433d6423SLionel Sambuc 252*433d6423SLionel Sambuc /* Lookup slot by label. */ 253*433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 254*433d6423SLionel Sambuc if(!rp) { 255*433d6423SLionel Sambuc if(rs_verbose) 256*433d6423SLionel Sambuc printf("RS: do_edit: service '%s' not found\n", label); 257*433d6423SLionel Sambuc return ESRCH; 258*433d6423SLionel Sambuc } 259*433d6423SLionel Sambuc rpub = rp->r_pub; 260*433d6423SLionel Sambuc 261*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 262*433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK) 263*433d6423SLionel Sambuc return r; 264*433d6423SLionel Sambuc 265*433d6423SLionel Sambuc if(rs_verbose) 266*433d6423SLionel Sambuc printf("RS: %s edits settings\n", srv_to_string(rp)); 267*433d6423SLionel Sambuc 268*433d6423SLionel Sambuc /* Synch the privilege structure with the kernel. */ 269*433d6423SLionel Sambuc if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) { 270*433d6423SLionel Sambuc printf("RS: do_edit: unable to synch privilege structure: %d\n", r); 271*433d6423SLionel Sambuc return r; 272*433d6423SLionel Sambuc } 273*433d6423SLionel Sambuc 274*433d6423SLionel Sambuc /* Tell scheduler this process is finished */ 275*433d6423SLionel Sambuc if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) { 276*433d6423SLionel Sambuc printf("RS: do_edit: scheduler won't give up process: %d\n", r); 277*433d6423SLionel Sambuc return r; 278*433d6423SLionel Sambuc } 279*433d6423SLionel Sambuc 280*433d6423SLionel Sambuc /* Edit the slot as requested. */ 281*433d6423SLionel Sambuc if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) { 282*433d6423SLionel Sambuc printf("RS: do_edit: unable to edit the existing slot: %d\n", r); 283*433d6423SLionel Sambuc return r; 284*433d6423SLionel Sambuc } 285*433d6423SLionel Sambuc 286*433d6423SLionel Sambuc /* Update privilege structure. */ 287*433d6423SLionel Sambuc r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv); 288*433d6423SLionel Sambuc if(r != OK) { 289*433d6423SLionel Sambuc printf("RS: do_edit: unable to update privilege structure: %d\n", r); 290*433d6423SLionel Sambuc return r; 291*433d6423SLionel Sambuc } 292*433d6423SLionel Sambuc 293*433d6423SLionel Sambuc /* Update VM calls. */ 294*433d6423SLionel Sambuc if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0], 295*433d6423SLionel Sambuc !!(rp->r_priv.s_flags & SYS_PROC))) != OK) { 296*433d6423SLionel Sambuc printf("RS: do_edit: failed: %d\n", r); 297*433d6423SLionel Sambuc return r; 298*433d6423SLionel Sambuc } 299*433d6423SLionel Sambuc 300*433d6423SLionel Sambuc /* Reinitialize scheduling. */ 301*433d6423SLionel Sambuc if ((r = sched_init_proc(rp)) != OK) { 302*433d6423SLionel Sambuc printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r); 303*433d6423SLionel Sambuc return r; 304*433d6423SLionel Sambuc } 305*433d6423SLionel Sambuc 306*433d6423SLionel Sambuc /* Cleanup old replicas and create a new one, if necessary. */ 307*433d6423SLionel Sambuc if(rpub->sys_flags & SF_USE_REPL) { 308*433d6423SLionel Sambuc if(rp->r_next_rp) { 309*433d6423SLionel Sambuc cleanup_service(rp->r_next_rp); 310*433d6423SLionel Sambuc rp->r_next_rp = NULL; 311*433d6423SLionel Sambuc } 312*433d6423SLionel Sambuc if ((r = clone_service(rp, RST_SYS_PROC)) != OK) { 313*433d6423SLionel Sambuc printf("RS: warning: unable to clone %s\n", srv_to_string(rp)); 314*433d6423SLionel Sambuc } 315*433d6423SLionel Sambuc } 316*433d6423SLionel Sambuc 317*433d6423SLionel Sambuc return OK; 318*433d6423SLionel Sambuc } 319*433d6423SLionel Sambuc 320*433d6423SLionel Sambuc /*===========================================================================* 321*433d6423SLionel Sambuc * do_refresh * 322*433d6423SLionel Sambuc *===========================================================================*/ 323*433d6423SLionel Sambuc int do_refresh(message *m_ptr) 324*433d6423SLionel Sambuc { 325*433d6423SLionel Sambuc register struct rproc *rp; 326*433d6423SLionel Sambuc int s; 327*433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 328*433d6423SLionel Sambuc 329*433d6423SLionel Sambuc /* Copy label. */ 330*433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr, 331*433d6423SLionel Sambuc m_ptr->m_rs_req.len, label, sizeof(label)); 332*433d6423SLionel Sambuc if(s != OK) { 333*433d6423SLionel Sambuc return s; 334*433d6423SLionel Sambuc } 335*433d6423SLionel Sambuc 336*433d6423SLionel Sambuc /* Lookup slot by label. */ 337*433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 338*433d6423SLionel Sambuc if(!rp) { 339*433d6423SLionel Sambuc if(rs_verbose) 340*433d6423SLionel Sambuc printf("RS: do_refresh: service '%s' not found\n", label); 341*433d6423SLionel Sambuc return(ESRCH); 342*433d6423SLionel Sambuc } 343*433d6423SLionel Sambuc 344*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 345*433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK) 346*433d6423SLionel Sambuc return s; 347*433d6423SLionel Sambuc 348*433d6423SLionel Sambuc /* Refresh service. */ 349*433d6423SLionel Sambuc if(rs_verbose) 350*433d6423SLionel Sambuc printf("RS: %s refreshing\n", srv_to_string(rp)); 351*433d6423SLionel Sambuc stop_service(rp,RS_REFRESHING); 352*433d6423SLionel Sambuc 353*433d6423SLionel Sambuc return OK; 354*433d6423SLionel Sambuc } 355*433d6423SLionel Sambuc 356*433d6423SLionel Sambuc /*===========================================================================* 357*433d6423SLionel Sambuc * do_shutdown * 358*433d6423SLionel Sambuc *===========================================================================*/ 359*433d6423SLionel Sambuc int do_shutdown(message *m_ptr) 360*433d6423SLionel Sambuc { 361*433d6423SLionel Sambuc int slot_nr; 362*433d6423SLionel Sambuc struct rproc *rp; 363*433d6423SLionel Sambuc int r; 364*433d6423SLionel Sambuc 365*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 366*433d6423SLionel Sambuc if (m_ptr != NULL) { 367*433d6423SLionel Sambuc if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK) 368*433d6423SLionel Sambuc return r; 369*433d6423SLionel Sambuc } 370*433d6423SLionel Sambuc 371*433d6423SLionel Sambuc if(rs_verbose) 372*433d6423SLionel Sambuc printf("RS: shutting down...\n"); 373*433d6423SLionel Sambuc 374*433d6423SLionel Sambuc /* Set flag to tell RS we are shutting down. */ 375*433d6423SLionel Sambuc shutting_down = TRUE; 376*433d6423SLionel Sambuc 377*433d6423SLionel Sambuc /* Don't restart dead services. */ 378*433d6423SLionel Sambuc for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { 379*433d6423SLionel Sambuc rp = &rproc[slot_nr]; 380*433d6423SLionel Sambuc if (rp->r_flags & RS_IN_USE) { 381*433d6423SLionel Sambuc rp->r_flags |= RS_EXITING; 382*433d6423SLionel Sambuc } 383*433d6423SLionel Sambuc } 384*433d6423SLionel Sambuc return(OK); 385*433d6423SLionel Sambuc } 386*433d6423SLionel Sambuc 387*433d6423SLionel Sambuc /*===========================================================================* 388*433d6423SLionel Sambuc * do_init_ready * 389*433d6423SLionel Sambuc *===========================================================================*/ 390*433d6423SLionel Sambuc int do_init_ready(message *m_ptr) 391*433d6423SLionel Sambuc { 392*433d6423SLionel Sambuc int who_p; 393*433d6423SLionel Sambuc message m; 394*433d6423SLionel Sambuc struct rproc *rp; 395*433d6423SLionel Sambuc struct rprocpub *rpub; 396*433d6423SLionel Sambuc int result, is_rs; 397*433d6423SLionel Sambuc int r; 398*433d6423SLionel Sambuc 399*433d6423SLionel Sambuc is_rs = (m_ptr->m_source == RS_PROC_NR); 400*433d6423SLionel Sambuc who_p = _ENDPOINT_P(m_ptr->m_source); 401*433d6423SLionel Sambuc result = m_ptr->m_rs_init.result; 402*433d6423SLionel Sambuc 403*433d6423SLionel Sambuc /* Check for RS failing initialization first. */ 404*433d6423SLionel Sambuc if(is_rs && result != OK) { 405*433d6423SLionel Sambuc return result; 406*433d6423SLionel Sambuc } 407*433d6423SLionel Sambuc 408*433d6423SLionel Sambuc rp = rproc_ptr[who_p]; 409*433d6423SLionel Sambuc rpub = rp->r_pub; 410*433d6423SLionel Sambuc 411*433d6423SLionel Sambuc /* Make sure the originating service was requested to initialize. */ 412*433d6423SLionel Sambuc if(! (rp->r_flags & RS_INITIALIZING) ) { 413*433d6423SLionel Sambuc if(rs_verbose) 414*433d6423SLionel Sambuc printf("RS: do_init_ready: got unexpected init ready msg from %d\n", 415*433d6423SLionel Sambuc m_ptr->m_source); 416*433d6423SLionel Sambuc return EINVAL; 417*433d6423SLionel Sambuc } 418*433d6423SLionel Sambuc 419*433d6423SLionel Sambuc /* Check if something went wrong and the service failed to init. 420*433d6423SLionel Sambuc * In that case, kill the service. 421*433d6423SLionel Sambuc */ 422*433d6423SLionel Sambuc if(result != OK) { 423*433d6423SLionel Sambuc if(rs_verbose) 424*433d6423SLionel Sambuc printf("RS: %s initialization error: %s\n", srv_to_string(rp), 425*433d6423SLionel Sambuc init_strerror(result)); 426*433d6423SLionel Sambuc if (result == ERESTART) 427*433d6423SLionel Sambuc rp->r_flags |= RS_REINCARNATE; 428*433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 429*433d6423SLionel Sambuc return EDONTREPLY; 430*433d6423SLionel Sambuc } 431*433d6423SLionel Sambuc 432*433d6423SLionel Sambuc /* Mark the slot as no longer initializing. */ 433*433d6423SLionel Sambuc rp->r_flags &= ~RS_INITIALIZING; 434*433d6423SLionel Sambuc rp->r_check_tm = 0; 435*433d6423SLionel Sambuc getticks(&rp->r_alive_tm); 436*433d6423SLionel Sambuc 437*433d6423SLionel Sambuc /* Reply and unblock the service before doing anything else. */ 438*433d6423SLionel Sambuc m.m_type = OK; 439*433d6423SLionel Sambuc reply(rpub->endpoint, rp, &m); 440*433d6423SLionel Sambuc 441*433d6423SLionel Sambuc /* See if a late reply has to be sent. */ 442*433d6423SLionel Sambuc late_reply(rp, OK); 443*433d6423SLionel Sambuc 444*433d6423SLionel Sambuc if(rs_verbose) 445*433d6423SLionel Sambuc printf("RS: %s initialized\n", srv_to_string(rp)); 446*433d6423SLionel Sambuc 447*433d6423SLionel Sambuc /* If the service has completed initialization after a live 448*433d6423SLionel Sambuc * update, end the update now. 449*433d6423SLionel Sambuc */ 450*433d6423SLionel Sambuc if(rp->r_flags & RS_UPDATING) { 451*433d6423SLionel Sambuc printf("RS: update succeeded\n"); 452*433d6423SLionel Sambuc end_update(OK, RS_DONTREPLY); 453*433d6423SLionel Sambuc } 454*433d6423SLionel Sambuc 455*433d6423SLionel Sambuc /* If the service has completed initialization after a crash 456*433d6423SLionel Sambuc * make the new instance active and cleanup the old replica. 457*433d6423SLionel Sambuc */ 458*433d6423SLionel Sambuc if(rp->r_prev_rp) { 459*433d6423SLionel Sambuc cleanup_service(rp->r_prev_rp); 460*433d6423SLionel Sambuc rp->r_prev_rp = NULL; 461*433d6423SLionel Sambuc rp->r_restarts += 1; 462*433d6423SLionel Sambuc 463*433d6423SLionel Sambuc if(rs_verbose) 464*433d6423SLionel Sambuc printf("RS: %s completed restart\n", srv_to_string(rp)); 465*433d6423SLionel Sambuc } 466*433d6423SLionel Sambuc 467*433d6423SLionel Sambuc /* If we must keep a replica of this system service, create it now. */ 468*433d6423SLionel Sambuc if(rpub->sys_flags & SF_USE_REPL) { 469*433d6423SLionel Sambuc if ((r = clone_service(rp, RST_SYS_PROC)) != OK) { 470*433d6423SLionel Sambuc printf("RS: warning: unable to clone %s\n", srv_to_string(rp)); 471*433d6423SLionel Sambuc } 472*433d6423SLionel Sambuc } 473*433d6423SLionel Sambuc 474*433d6423SLionel Sambuc return is_rs ? OK : EDONTREPLY; /* return what the caller expects */ 475*433d6423SLionel Sambuc } 476*433d6423SLionel Sambuc 477*433d6423SLionel Sambuc /*===========================================================================* 478*433d6423SLionel Sambuc * do_update * 479*433d6423SLionel Sambuc *===========================================================================*/ 480*433d6423SLionel Sambuc int do_update(message *m_ptr) 481*433d6423SLionel Sambuc { 482*433d6423SLionel Sambuc struct rproc *rp; 483*433d6423SLionel Sambuc struct rproc *new_rp; 484*433d6423SLionel Sambuc struct rprocpub *rpub; 485*433d6423SLionel Sambuc struct rs_start rs_start; 486*433d6423SLionel Sambuc int noblock, do_self_update; 487*433d6423SLionel Sambuc int s; 488*433d6423SLionel Sambuc char label[RS_MAX_LABEL_LEN]; 489*433d6423SLionel Sambuc int lu_state; 490*433d6423SLionel Sambuc int prepare_maxtime; 491*433d6423SLionel Sambuc 492*433d6423SLionel Sambuc /* Copy the request structure. */ 493*433d6423SLionel Sambuc s = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start); 494*433d6423SLionel Sambuc if (s != OK) { 495*433d6423SLionel Sambuc return s; 496*433d6423SLionel Sambuc } 497*433d6423SLionel Sambuc noblock = (rs_start.rss_flags & RSS_NOBLOCK); 498*433d6423SLionel Sambuc do_self_update = (rs_start.rss_flags & RSS_SELF_LU); 499*433d6423SLionel Sambuc s = check_request(&rs_start); 500*433d6423SLionel Sambuc if (s != OK) { 501*433d6423SLionel Sambuc return s; 502*433d6423SLionel Sambuc } 503*433d6423SLionel Sambuc 504*433d6423SLionel Sambuc /* Copy label. */ 505*433d6423SLionel Sambuc s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, 506*433d6423SLionel Sambuc rs_start.rss_label.l_len, label, sizeof(label)); 507*433d6423SLionel Sambuc if(s != OK) { 508*433d6423SLionel Sambuc return s; 509*433d6423SLionel Sambuc } 510*433d6423SLionel Sambuc 511*433d6423SLionel Sambuc /* Lookup slot by label. */ 512*433d6423SLionel Sambuc rp = lookup_slot_by_label(label); 513*433d6423SLionel Sambuc if(!rp) { 514*433d6423SLionel Sambuc if(rs_verbose) 515*433d6423SLionel Sambuc printf("RS: do_update: service '%s' not found\n", label); 516*433d6423SLionel Sambuc return ESRCH; 517*433d6423SLionel Sambuc } 518*433d6423SLionel Sambuc rpub = rp->r_pub; 519*433d6423SLionel Sambuc 520*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 521*433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK) 522*433d6423SLionel Sambuc return s; 523*433d6423SLionel Sambuc 524*433d6423SLionel Sambuc /* Retrieve live update state. */ 525*433d6423SLionel Sambuc lu_state = m_ptr->m_rs_update.state; 526*433d6423SLionel Sambuc if(lu_state == SEF_LU_STATE_NULL) { 527*433d6423SLionel Sambuc return(EINVAL); 528*433d6423SLionel Sambuc } 529*433d6423SLionel Sambuc 530*433d6423SLionel Sambuc /* Retrieve prepare max time. */ 531*433d6423SLionel Sambuc prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime; 532*433d6423SLionel Sambuc if(prepare_maxtime) { 533*433d6423SLionel Sambuc if(prepare_maxtime < 0 || prepare_maxtime > RS_MAX_PREPARE_MAXTIME) { 534*433d6423SLionel Sambuc return(EINVAL); 535*433d6423SLionel Sambuc } 536*433d6423SLionel Sambuc } 537*433d6423SLionel Sambuc else { 538*433d6423SLionel Sambuc prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME; 539*433d6423SLionel Sambuc } 540*433d6423SLionel Sambuc 541*433d6423SLionel Sambuc /* Make sure we are not already updating. */ 542*433d6423SLionel Sambuc if(rupdate.flags & RS_UPDATING) { 543*433d6423SLionel Sambuc if(rs_verbose) 544*433d6423SLionel Sambuc printf("RS: do_update: an update is already in progress\n"); 545*433d6423SLionel Sambuc return EBUSY; 546*433d6423SLionel Sambuc } 547*433d6423SLionel Sambuc 548*433d6423SLionel Sambuc /* A self update live updates a service instance into a replica, a regular 549*433d6423SLionel Sambuc * update live updates a service instance into a new version, as specified 550*433d6423SLionel Sambuc * by the given binary. 551*433d6423SLionel Sambuc */ 552*433d6423SLionel Sambuc if(do_self_update) { 553*433d6423SLionel Sambuc if(rs_verbose) 554*433d6423SLionel Sambuc printf("RS: %s performs self update\n", srv_to_string(rp)); 555*433d6423SLionel Sambuc 556*433d6423SLionel Sambuc /* Clone the system service and use the replica as the new version. */ 557*433d6423SLionel Sambuc s = clone_service(rp, LU_SYS_PROC); 558*433d6423SLionel Sambuc if(s != OK) { 559*433d6423SLionel Sambuc printf("RS: do_update: unable to clone service: %d\n", s); 560*433d6423SLionel Sambuc return s; 561*433d6423SLionel Sambuc } 562*433d6423SLionel Sambuc } 563*433d6423SLionel Sambuc else { 564*433d6423SLionel Sambuc if(rs_verbose) 565*433d6423SLionel Sambuc printf("RS: %s performs regular update\n", srv_to_string(rp)); 566*433d6423SLionel Sambuc 567*433d6423SLionel Sambuc /* Allocate a system service slot for the new version. */ 568*433d6423SLionel Sambuc s = alloc_slot(&new_rp); 569*433d6423SLionel Sambuc if(s != OK) { 570*433d6423SLionel Sambuc printf("RS: do_update: unable to allocate a new slot: %d\n", s); 571*433d6423SLionel Sambuc return s; 572*433d6423SLionel Sambuc } 573*433d6423SLionel Sambuc 574*433d6423SLionel Sambuc /* Initialize the slot as requested. */ 575*433d6423SLionel Sambuc s = init_slot(new_rp, &rs_start, m_ptr->m_source); 576*433d6423SLionel Sambuc if(s != OK) { 577*433d6423SLionel Sambuc printf("RS: do_update: unable to init the new slot: %d\n", s); 578*433d6423SLionel Sambuc return s; 579*433d6423SLionel Sambuc } 580*433d6423SLionel Sambuc 581*433d6423SLionel Sambuc /* Let the new version inherit defaults from the old one. */ 582*433d6423SLionel Sambuc inherit_service_defaults(rp, new_rp); 583*433d6423SLionel Sambuc 584*433d6423SLionel Sambuc /* Link the two versions. */ 585*433d6423SLionel Sambuc rp->r_new_rp = new_rp; 586*433d6423SLionel Sambuc new_rp->r_old_rp = rp; 587*433d6423SLionel Sambuc 588*433d6423SLionel Sambuc /* Create new version of the service but don't let it run. */ 589*433d6423SLionel Sambuc new_rp->r_priv.s_flags |= LU_SYS_PROC; 590*433d6423SLionel Sambuc s = create_service(new_rp); 591*433d6423SLionel Sambuc if(s != OK) { 592*433d6423SLionel Sambuc printf("RS: do_update: unable to create a new service: %d\n", s); 593*433d6423SLionel Sambuc return s; 594*433d6423SLionel Sambuc } 595*433d6423SLionel Sambuc } 596*433d6423SLionel Sambuc 597*433d6423SLionel Sambuc /* Mark both versions as updating. */ 598*433d6423SLionel Sambuc rp->r_flags |= RS_UPDATING; 599*433d6423SLionel Sambuc rp->r_new_rp->r_flags |= RS_UPDATING; 600*433d6423SLionel Sambuc rupdate.flags |= RS_UPDATING; 601*433d6423SLionel Sambuc getticks(&rupdate.prepare_tm); 602*433d6423SLionel Sambuc rupdate.prepare_maxtime = prepare_maxtime; 603*433d6423SLionel Sambuc rupdate.rp = rp; 604*433d6423SLionel Sambuc 605*433d6423SLionel Sambuc if(rs_verbose) 606*433d6423SLionel Sambuc printf("RS: %s updating\n", srv_to_string(rp)); 607*433d6423SLionel Sambuc 608*433d6423SLionel Sambuc /* If RS is updating, set up signal managers for the new instance. 609*433d6423SLionel Sambuc * The current RS instance must be made the backup signal manager to 610*433d6423SLionel Sambuc * support rollback in case of a crash during initialization. 611*433d6423SLionel Sambuc */ 612*433d6423SLionel Sambuc if(rp->r_priv.s_flags & ROOT_SYS_PROC) { 613*433d6423SLionel Sambuc new_rp = rp->r_new_rp; 614*433d6423SLionel Sambuc 615*433d6423SLionel Sambuc s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint); 616*433d6423SLionel Sambuc if(s != OK) { 617*433d6423SLionel Sambuc cleanup_service(new_rp); 618*433d6423SLionel Sambuc return s; 619*433d6423SLionel Sambuc } 620*433d6423SLionel Sambuc } 621*433d6423SLionel Sambuc 622*433d6423SLionel Sambuc if(noblock) { 623*433d6423SLionel Sambuc /* Unblock the caller immediately if requested. */ 624*433d6423SLionel Sambuc m_ptr->m_type = OK; 625*433d6423SLionel Sambuc reply(m_ptr->m_source, NULL, m_ptr); 626*433d6423SLionel Sambuc } 627*433d6423SLionel Sambuc else { 628*433d6423SLionel Sambuc /* Send a reply when the new version completes initialization. */ 629*433d6423SLionel Sambuc rp->r_flags |= RS_LATEREPLY; 630*433d6423SLionel Sambuc rp->r_caller = m_ptr->m_source; 631*433d6423SLionel Sambuc rp->r_caller_request = RS_UPDATE; 632*433d6423SLionel Sambuc } 633*433d6423SLionel Sambuc 634*433d6423SLionel Sambuc /* Request to update. */ 635*433d6423SLionel Sambuc m_ptr->m_type = RS_LU_PREPARE; 636*433d6423SLionel Sambuc if(rpub->endpoint == RS_PROC_NR) { 637*433d6423SLionel Sambuc /* RS can process the request directly. */ 638*433d6423SLionel Sambuc do_sef_lu_request(m_ptr); 639*433d6423SLionel Sambuc } 640*433d6423SLionel Sambuc else { 641*433d6423SLionel Sambuc /* Send request message to the system service. */ 642*433d6423SLionel Sambuc asynsend3(rpub->endpoint, m_ptr, AMF_NOREPLY); 643*433d6423SLionel Sambuc } 644*433d6423SLionel Sambuc 645*433d6423SLionel Sambuc return EDONTREPLY; 646*433d6423SLionel Sambuc } 647*433d6423SLionel Sambuc 648*433d6423SLionel Sambuc /*===========================================================================* 649*433d6423SLionel Sambuc * do_upd_ready * 650*433d6423SLionel Sambuc *===========================================================================*/ 651*433d6423SLionel Sambuc int do_upd_ready(message *m_ptr) 652*433d6423SLionel Sambuc { 653*433d6423SLionel Sambuc struct rproc *rp, *old_rp, *new_rp; 654*433d6423SLionel Sambuc int who_p; 655*433d6423SLionel Sambuc int result; 656*433d6423SLionel Sambuc int is_rs; 657*433d6423SLionel Sambuc int r; 658*433d6423SLionel Sambuc 659*433d6423SLionel Sambuc who_p = _ENDPOINT_P(m_ptr->m_source); 660*433d6423SLionel Sambuc rp = rproc_ptr[who_p]; 661*433d6423SLionel Sambuc result = m_ptr->m_rs_update.result; 662*433d6423SLionel Sambuc is_rs = (m_ptr->m_source == RS_PROC_NR); 663*433d6423SLionel Sambuc 664*433d6423SLionel Sambuc /* Make sure the originating service was requested to prepare for update. */ 665*433d6423SLionel Sambuc if(rp != rupdate.rp) { 666*433d6423SLionel Sambuc if(rs_verbose) 667*433d6423SLionel Sambuc printf("RS: do_upd_ready: got unexpected update ready msg from %d\n", 668*433d6423SLionel Sambuc m_ptr->m_source); 669*433d6423SLionel Sambuc return EINVAL; 670*433d6423SLionel Sambuc } 671*433d6423SLionel Sambuc 672*433d6423SLionel Sambuc /* Check if something went wrong and the service failed to prepare 673*433d6423SLionel Sambuc * for the update. In that case, end the update process. The old version will 674*433d6423SLionel Sambuc * be replied to and continue executing. 675*433d6423SLionel Sambuc */ 676*433d6423SLionel Sambuc if(result != OK) { 677*433d6423SLionel Sambuc end_update(result, RS_REPLY); 678*433d6423SLionel Sambuc 679*433d6423SLionel Sambuc printf("RS: update failed: %s\n", lu_strerror(result)); 680*433d6423SLionel Sambuc return is_rs ? result : EDONTREPLY; /* return what the caller expects */ 681*433d6423SLionel Sambuc } 682*433d6423SLionel Sambuc 683*433d6423SLionel Sambuc old_rp = rp; 684*433d6423SLionel Sambuc new_rp = rp->r_new_rp; 685*433d6423SLionel Sambuc 686*433d6423SLionel Sambuc /* If RS itself is updating, yield control to the new version immediately. */ 687*433d6423SLionel Sambuc if(is_rs) { 688*433d6423SLionel Sambuc r = init_service(new_rp, SEF_INIT_LU); 689*433d6423SLionel Sambuc if(r != OK) { 690*433d6423SLionel Sambuc panic("unable to initialize the new RS instance: %d", r); 691*433d6423SLionel Sambuc } 692*433d6423SLionel Sambuc r = sys_privctl(new_rp->r_pub->endpoint, SYS_PRIV_YIELD, NULL); 693*433d6423SLionel Sambuc if(r != OK) { 694*433d6423SLionel Sambuc panic("unable to yield control to the new RS instance: %d", r); 695*433d6423SLionel Sambuc } 696*433d6423SLionel Sambuc /* If we get this far, the new version failed to initialize. Rollback. */ 697*433d6423SLionel Sambuc r = srv_update(RS_PROC_NR, new_rp->r_pub->endpoint); 698*433d6423SLionel Sambuc assert(r == OK); /* can't fail */ 699*433d6423SLionel Sambuc end_update(ERESTART, RS_REPLY); 700*433d6423SLionel Sambuc return ERESTART; 701*433d6423SLionel Sambuc } 702*433d6423SLionel Sambuc 703*433d6423SLionel Sambuc /* Perform the update. */ 704*433d6423SLionel Sambuc r = update_service(&old_rp, &new_rp, RS_SWAP); 705*433d6423SLionel Sambuc if(r != OK) { 706*433d6423SLionel Sambuc end_update(r, RS_REPLY); 707*433d6423SLionel Sambuc printf("RS: update failed: error %d\n", r); 708*433d6423SLionel Sambuc return EDONTREPLY; 709*433d6423SLionel Sambuc } 710*433d6423SLionel Sambuc 711*433d6423SLionel Sambuc /* Let the new version run. */ 712*433d6423SLionel Sambuc r = run_service(new_rp, SEF_INIT_LU); 713*433d6423SLionel Sambuc if(r != OK) { 714*433d6423SLionel Sambuc /* Something went wrong. Rollback. */ 715*433d6423SLionel Sambuc r = update_service(&new_rp, &old_rp, RS_SWAP); 716*433d6423SLionel Sambuc assert(r == OK); /* can't fail */ 717*433d6423SLionel Sambuc end_update(r, RS_REPLY); 718*433d6423SLionel Sambuc printf("RS: update failed: error %d\n", r); 719*433d6423SLionel Sambuc return EDONTREPLY; 720*433d6423SLionel Sambuc } 721*433d6423SLionel Sambuc 722*433d6423SLionel Sambuc return EDONTREPLY; 723*433d6423SLionel Sambuc } 724*433d6423SLionel Sambuc 725*433d6423SLionel Sambuc /*===========================================================================* 726*433d6423SLionel Sambuc * do_period * 727*433d6423SLionel Sambuc *===========================================================================*/ 728*433d6423SLionel Sambuc void do_period(m_ptr) 729*433d6423SLionel Sambuc message *m_ptr; 730*433d6423SLionel Sambuc { 731*433d6423SLionel Sambuc register struct rproc *rp; 732*433d6423SLionel Sambuc register struct rprocpub *rpub; 733*433d6423SLionel Sambuc clock_t now = m_ptr->m_notify.timestamp; 734*433d6423SLionel Sambuc int s; 735*433d6423SLionel Sambuc long period; 736*433d6423SLionel Sambuc 737*433d6423SLionel Sambuc /* If an update is in progress, check its status. */ 738*433d6423SLionel Sambuc if(rupdate.flags & RS_UPDATING) { 739*433d6423SLionel Sambuc update_period(m_ptr); 740*433d6423SLionel Sambuc } 741*433d6423SLionel Sambuc 742*433d6423SLionel Sambuc /* Search system services table. Only check slots that are in use and not 743*433d6423SLionel Sambuc * updating. 744*433d6423SLionel Sambuc */ 745*433d6423SLionel Sambuc for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { 746*433d6423SLionel Sambuc rpub = rp->r_pub; 747*433d6423SLionel Sambuc if ((rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_UPDATING)) { 748*433d6423SLionel Sambuc 749*433d6423SLionel Sambuc /* Compute period. */ 750*433d6423SLionel Sambuc period = rp->r_period; 751*433d6423SLionel Sambuc if(rp->r_flags & RS_INITIALIZING) { 752*433d6423SLionel Sambuc period = RS_INIT_T; 753*433d6423SLionel Sambuc } 754*433d6423SLionel Sambuc 755*433d6423SLionel Sambuc /* If the service is to be revived (because it repeatedly exited, 756*433d6423SLionel Sambuc * and was not directly restarted), the binary backoff field is 757*433d6423SLionel Sambuc * greater than zero. 758*433d6423SLionel Sambuc */ 759*433d6423SLionel Sambuc if (rp->r_backoff > 0) { 760*433d6423SLionel Sambuc rp->r_backoff -= 1; 761*433d6423SLionel Sambuc if (rp->r_backoff == 0) { 762*433d6423SLionel Sambuc restart_service(rp); 763*433d6423SLionel Sambuc } 764*433d6423SLionel Sambuc } 765*433d6423SLionel Sambuc 766*433d6423SLionel Sambuc /* If the service was signaled with a SIGTERM and fails to respond, 767*433d6423SLionel Sambuc * kill the system service with a SIGKILL signal. 768*433d6423SLionel Sambuc */ 769*433d6423SLionel Sambuc else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T 770*433d6423SLionel Sambuc && rp->r_pid > 0) { 771*433d6423SLionel Sambuc rp->r_stop_tm = 0; 772*433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 773*433d6423SLionel Sambuc } 774*433d6423SLionel Sambuc 775*433d6423SLionel Sambuc /* There seems to be no special conditions. If the service has a 776*433d6423SLionel Sambuc * period assigned check its status. 777*433d6423SLionel Sambuc */ 778*433d6423SLionel Sambuc else if (period > 0) { 779*433d6423SLionel Sambuc 780*433d6423SLionel Sambuc /* Check if an answer to a status request is still pending. If 781*433d6423SLionel Sambuc * the service didn't respond within time, kill it to simulate 782*433d6423SLionel Sambuc * a crash. The failure will be detected and the service will 783*433d6423SLionel Sambuc * be restarted automatically. Give the service a free pass if 784*433d6423SLionel Sambuc * somebody is initializing. There may be some weird dependencies 785*433d6423SLionel Sambuc * if another service is, for example, restarting at the same 786*433d6423SLionel Sambuc * time. 787*433d6423SLionel Sambuc */ 788*433d6423SLionel Sambuc if (rp->r_alive_tm < rp->r_check_tm) { 789*433d6423SLionel Sambuc if (now - rp->r_alive_tm > 2*period && 790*433d6423SLionel Sambuc rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) { 791*433d6423SLionel Sambuc if(rs_verbose) 792*433d6423SLionel Sambuc printf("RS: %s reported late\n", srv_to_string(rp)); 793*433d6423SLionel Sambuc if(lookup_slot_by_flags(RS_INITIALIZING)) { 794*433d6423SLionel Sambuc /* Skip for now. */ 795*433d6423SLionel Sambuc if(rs_verbose) 796*433d6423SLionel Sambuc printf("RS: %s gets a free pass\n", 797*433d6423SLionel Sambuc srv_to_string(rp)); 798*433d6423SLionel Sambuc rp->r_alive_tm = now; 799*433d6423SLionel Sambuc rp->r_check_tm = now+1; 800*433d6423SLionel Sambuc continue; 801*433d6423SLionel Sambuc } 802*433d6423SLionel Sambuc rp->r_flags |= RS_NOPINGREPLY; 803*433d6423SLionel Sambuc crash_service(rp); /* simulate crash */ 804*433d6423SLionel Sambuc } 805*433d6423SLionel Sambuc } 806*433d6423SLionel Sambuc 807*433d6423SLionel Sambuc /* No answer pending. Check if a period expired since the last 808*433d6423SLionel Sambuc * check and, if so request the system service's status. 809*433d6423SLionel Sambuc */ 810*433d6423SLionel Sambuc else if (now - rp->r_check_tm > rp->r_period) { 811*433d6423SLionel Sambuc ipc_notify(rpub->endpoint); /* request status */ 812*433d6423SLionel Sambuc rp->r_check_tm = now; /* mark time */ 813*433d6423SLionel Sambuc } 814*433d6423SLionel Sambuc } 815*433d6423SLionel Sambuc } 816*433d6423SLionel Sambuc } 817*433d6423SLionel Sambuc 818*433d6423SLionel Sambuc /* Reschedule a synchronous alarm for the next period. */ 819*433d6423SLionel Sambuc if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) 820*433d6423SLionel Sambuc panic("couldn't set alarm: %d", s); 821*433d6423SLionel Sambuc } 822*433d6423SLionel Sambuc 823*433d6423SLionel Sambuc /*===========================================================================* 824*433d6423SLionel Sambuc * do_sigchld * 825*433d6423SLionel Sambuc *===========================================================================*/ 826*433d6423SLionel Sambuc void do_sigchld() 827*433d6423SLionel Sambuc { 828*433d6423SLionel Sambuc /* PM informed us that there are dead children to cleanup. Go get them. */ 829*433d6423SLionel Sambuc pid_t pid; 830*433d6423SLionel Sambuc int status; 831*433d6423SLionel Sambuc struct rproc *rp; 832*433d6423SLionel Sambuc struct rproc **rps; 833*433d6423SLionel Sambuc int i, nr_rps; 834*433d6423SLionel Sambuc 835*433d6423SLionel Sambuc if(rs_verbose) 836*433d6423SLionel Sambuc printf("RS: got SIGCHLD signal, cleaning up dead children\n"); 837*433d6423SLionel Sambuc 838*433d6423SLionel Sambuc while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) { 839*433d6423SLionel Sambuc rp = lookup_slot_by_pid(pid); 840*433d6423SLionel Sambuc if(rp != NULL) { 841*433d6423SLionel Sambuc 842*433d6423SLionel Sambuc if(rs_verbose) 843*433d6423SLionel Sambuc printf("RS: %s exited via another signal manager\n", 844*433d6423SLionel Sambuc srv_to_string(rp)); 845*433d6423SLionel Sambuc 846*433d6423SLionel Sambuc /* The slot is still there. This means RS is not the signal 847*433d6423SLionel Sambuc * manager assigned to the process. Ignore the event but 848*433d6423SLionel Sambuc * free slots for all the service instances and send a late 849*433d6423SLionel Sambuc * reply if necessary. 850*433d6423SLionel Sambuc */ 851*433d6423SLionel Sambuc get_service_instances(rp, &rps, &nr_rps); 852*433d6423SLionel Sambuc for(i=0;i<nr_rps;i++) { 853*433d6423SLionel Sambuc if(rupdate.flags & RS_UPDATING) { 854*433d6423SLionel Sambuc rupdate.flags &= ~RS_UPDATING; 855*433d6423SLionel Sambuc } 856*433d6423SLionel Sambuc free_slot(rps[i]); 857*433d6423SLionel Sambuc } 858*433d6423SLionel Sambuc } 859*433d6423SLionel Sambuc } 860*433d6423SLionel Sambuc } 861*433d6423SLionel Sambuc 862*433d6423SLionel Sambuc /*===========================================================================* 863*433d6423SLionel Sambuc * do_getsysinfo * 864*433d6423SLionel Sambuc *===========================================================================*/ 865*433d6423SLionel Sambuc int do_getsysinfo(m_ptr) 866*433d6423SLionel Sambuc message *m_ptr; 867*433d6423SLionel Sambuc { 868*433d6423SLionel Sambuc vir_bytes src_addr, dst_addr; 869*433d6423SLionel Sambuc int dst_proc; 870*433d6423SLionel Sambuc size_t len; 871*433d6423SLionel Sambuc int s; 872*433d6423SLionel Sambuc 873*433d6423SLionel Sambuc /* Check if the call can be allowed. */ 874*433d6423SLionel Sambuc if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK) 875*433d6423SLionel Sambuc return s; 876*433d6423SLionel Sambuc 877*433d6423SLionel Sambuc switch(m_ptr->m_lsys_getsysinfo.what) { 878*433d6423SLionel Sambuc case SI_PROC_TAB: 879*433d6423SLionel Sambuc src_addr = (vir_bytes) rproc; 880*433d6423SLionel Sambuc len = sizeof(struct rproc) * NR_SYS_PROCS; 881*433d6423SLionel Sambuc break; 882*433d6423SLionel Sambuc case SI_PROCPUB_TAB: 883*433d6423SLionel Sambuc src_addr = (vir_bytes) rprocpub; 884*433d6423SLionel Sambuc len = sizeof(struct rprocpub) * NR_SYS_PROCS; 885*433d6423SLionel Sambuc break; 886*433d6423SLionel Sambuc default: 887*433d6423SLionel Sambuc return(EINVAL); 888*433d6423SLionel Sambuc } 889*433d6423SLionel Sambuc 890*433d6423SLionel Sambuc if (len != m_ptr->m_lsys_getsysinfo.size) 891*433d6423SLionel Sambuc return(EINVAL); 892*433d6423SLionel Sambuc 893*433d6423SLionel Sambuc dst_proc = m_ptr->m_source; 894*433d6423SLionel Sambuc dst_addr = m_ptr->m_lsys_getsysinfo.where; 895*433d6423SLionel Sambuc return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len); 896*433d6423SLionel Sambuc } 897*433d6423SLionel Sambuc 898*433d6423SLionel Sambuc /*===========================================================================* 899*433d6423SLionel Sambuc * do_lookup * 900*433d6423SLionel Sambuc *===========================================================================*/ 901*433d6423SLionel Sambuc int do_lookup(m_ptr) 902*433d6423SLionel Sambuc message *m_ptr; 903*433d6423SLionel Sambuc { 904*433d6423SLionel Sambuc static char namebuf[100]; 905*433d6423SLionel Sambuc int len, r; 906*433d6423SLionel Sambuc struct rproc *rrp; 907*433d6423SLionel Sambuc struct rprocpub *rrpub; 908*433d6423SLionel Sambuc 909*433d6423SLionel Sambuc len = m_ptr->m_rs_req.name_len; 910*433d6423SLionel Sambuc 911*433d6423SLionel Sambuc if(len < 2 || len >= sizeof(namebuf)) { 912*433d6423SLionel Sambuc printf("RS: len too weird (%d)\n", len); 913*433d6423SLionel Sambuc return EINVAL; 914*433d6423SLionel Sambuc } 915*433d6423SLionel Sambuc 916*433d6423SLionel Sambuc if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name, 917*433d6423SLionel Sambuc SELF, (vir_bytes) namebuf, len)) != OK) { 918*433d6423SLionel Sambuc printf("RS: name copy failed\n"); 919*433d6423SLionel Sambuc return r; 920*433d6423SLionel Sambuc 921*433d6423SLionel Sambuc } 922*433d6423SLionel Sambuc 923*433d6423SLionel Sambuc namebuf[len] = '\0'; 924*433d6423SLionel Sambuc 925*433d6423SLionel Sambuc rrp = lookup_slot_by_label(namebuf); 926*433d6423SLionel Sambuc if(!rrp) { 927*433d6423SLionel Sambuc return ESRCH; 928*433d6423SLionel Sambuc } 929*433d6423SLionel Sambuc rrpub = rrp->r_pub; 930*433d6423SLionel Sambuc m_ptr->m_rs_req.endpoint = rrpub->endpoint; 931*433d6423SLionel Sambuc 932*433d6423SLionel Sambuc return OK; 933*433d6423SLionel Sambuc } 934*433d6423SLionel Sambuc 935*433d6423SLionel Sambuc /*===========================================================================* 936*433d6423SLionel Sambuc * check_request * 937*433d6423SLionel Sambuc *===========================================================================*/ 938*433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start) 939*433d6423SLionel Sambuc { 940*433d6423SLionel Sambuc /* Verify scheduling parameters */ 941*433d6423SLionel Sambuc if (rs_start->rss_scheduler != KERNEL && 942*433d6423SLionel Sambuc (rs_start->rss_scheduler < 0 || 943*433d6423SLionel Sambuc rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) { 944*433d6423SLionel Sambuc printf("RS: check_request: invalid scheduler %d\n", 945*433d6423SLionel Sambuc rs_start->rss_scheduler); 946*433d6423SLionel Sambuc return EINVAL; 947*433d6423SLionel Sambuc } 948*433d6423SLionel Sambuc if (rs_start->rss_priority >= NR_SCHED_QUEUES) { 949*433d6423SLionel Sambuc printf("RS: check_request: priority %u out of range\n", 950*433d6423SLionel Sambuc rs_start->rss_priority); 951*433d6423SLionel Sambuc return EINVAL; 952*433d6423SLionel Sambuc } 953*433d6423SLionel Sambuc if (rs_start->rss_quantum <= 0) { 954*433d6423SLionel Sambuc printf("RS: check_request: quantum %u out of range\n", 955*433d6423SLionel Sambuc rs_start->rss_quantum); 956*433d6423SLionel Sambuc return EINVAL; 957*433d6423SLionel Sambuc } 958*433d6423SLionel Sambuc 959*433d6423SLionel Sambuc if (rs_start->rss_cpu == RS_CPU_BSP) 960*433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 961*433d6423SLionel Sambuc else if (rs_start->rss_cpu == RS_CPU_DEFAULT) { 962*433d6423SLionel Sambuc /* keep the default value */ 963*433d6423SLionel Sambuc } else if (rs_start->rss_cpu < 0) 964*433d6423SLionel Sambuc return EINVAL; 965*433d6423SLionel Sambuc else if (rs_start->rss_cpu > machine.processors_count) { 966*433d6423SLionel Sambuc printf("RS: cpu number %d out of range 0-%d, using BSP\n", 967*433d6423SLionel Sambuc rs_start->rss_cpu, machine.processors_count); 968*433d6423SLionel Sambuc rs_start->rss_cpu = machine.bsp_id; 969*433d6423SLionel Sambuc } 970*433d6423SLionel Sambuc 971*433d6423SLionel Sambuc /* Verify signal manager. */ 972*433d6423SLionel Sambuc if (rs_start->rss_sigmgr != SELF && 973*433d6423SLionel Sambuc (rs_start->rss_sigmgr < 0 || 974*433d6423SLionel Sambuc rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) { 975*433d6423SLionel Sambuc printf("RS: check_request: invalid signal manager %d\n", 976*433d6423SLionel Sambuc rs_start->rss_sigmgr); 977*433d6423SLionel Sambuc return EINVAL; 978*433d6423SLionel Sambuc } 979*433d6423SLionel Sambuc 980*433d6423SLionel Sambuc return OK; 981*433d6423SLionel Sambuc } 982*433d6423SLionel Sambuc 983