1fb6bd596SCristiano Giuffrida 2fb6bd596SCristiano Giuffrida #include "inc.h" 3fb6bd596SCristiano Giuffrida 4fb6bd596SCristiano Giuffrida /*===========================================================================* 5fb6bd596SCristiano Giuffrida * rupdate_clear_upds * 6fb6bd596SCristiano Giuffrida *===========================================================================*/ 7fb6bd596SCristiano Giuffrida void rupdate_clear_upds() 8fb6bd596SCristiano Giuffrida { 9fb6bd596SCristiano Giuffrida /* Clear the update chain and the global update descriptor. */ 10fb6bd596SCristiano Giuffrida struct rprocupd *prev_rpupd, *rpupd; 11fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 12fb6bd596SCristiano Giuffrida if(prev_rpupd) { 13fb6bd596SCristiano Giuffrida rupdate_upd_clear(prev_rpupd); 14fb6bd596SCristiano Giuffrida } 15fb6bd596SCristiano Giuffrida ); 16fb6bd596SCristiano Giuffrida rupdate_upd_clear(rupdate.last_rpupd); 17fb6bd596SCristiano Giuffrida RUPDATE_CLEAR(); 18fb6bd596SCristiano Giuffrida } 19fb6bd596SCristiano Giuffrida 20fb6bd596SCristiano Giuffrida /*===========================================================================* 21fb6bd596SCristiano Giuffrida * rupdate_add_upd * 22fb6bd596SCristiano Giuffrida *===========================================================================*/ 23fb6bd596SCristiano Giuffrida void rupdate_add_upd(struct rprocupd* rpupd) 24fb6bd596SCristiano Giuffrida { 25fb6bd596SCristiano Giuffrida /* Add an update descriptor to the update chain. */ 26*abf8a7e7SDavid van Moolenbroek struct rprocupd *prev_rpupd, *walk_rpupd; 27*abf8a7e7SDavid van Moolenbroek endpoint_t ep; 28fb6bd596SCristiano Giuffrida int lu_flags; 29fb6bd596SCristiano Giuffrida 30*abf8a7e7SDavid van Moolenbroek /* In order to allow multicomponent-with-VM live updates to be processed 31*abf8a7e7SDavid van Moolenbroek * correctly, we perform partial sorting on the chain: RS is to be last (if 32*abf8a7e7SDavid van Moolenbroek * present), VM is to be right before it (if present), and all the other 33*abf8a7e7SDavid van Moolenbroek * processes are to be at the start of the chain. 34*abf8a7e7SDavid van Moolenbroek */ 35*abf8a7e7SDavid van Moolenbroek 36*abf8a7e7SDavid van Moolenbroek ep = rpupd->rp->r_pub->endpoint; 37*abf8a7e7SDavid van Moolenbroek 38*abf8a7e7SDavid van Moolenbroek assert(rpupd->next_rpupd == NULL); 39*abf8a7e7SDavid van Moolenbroek assert(rpupd->prev_rpupd == NULL); 40*abf8a7e7SDavid van Moolenbroek 41*abf8a7e7SDavid van Moolenbroek /* Determine what element to insert after, if not at the head. */ 42*abf8a7e7SDavid van Moolenbroek prev_rpupd = rupdate.last_rpupd; 43*abf8a7e7SDavid van Moolenbroek if (prev_rpupd != NULL && ep != RS_PROC_NR && 44*abf8a7e7SDavid van Moolenbroek prev_rpupd->rp->r_pub->endpoint == RS_PROC_NR) 45*abf8a7e7SDavid van Moolenbroek prev_rpupd = prev_rpupd->prev_rpupd; 46*abf8a7e7SDavid van Moolenbroek if (prev_rpupd != NULL && ep != RS_PROC_NR && ep != VM_PROC_NR && 47*abf8a7e7SDavid van Moolenbroek prev_rpupd->rp->r_pub->endpoint == VM_PROC_NR) 48*abf8a7e7SDavid van Moolenbroek prev_rpupd = prev_rpupd->prev_rpupd; 49*abf8a7e7SDavid van Moolenbroek 50*abf8a7e7SDavid van Moolenbroek /* Perform the insertion. */ 51*abf8a7e7SDavid van Moolenbroek if (prev_rpupd == NULL) { 52*abf8a7e7SDavid van Moolenbroek rpupd->next_rpupd = rupdate.first_rpupd; 53*abf8a7e7SDavid van Moolenbroek rupdate.first_rpupd = rupdate.curr_rpupd = rpupd; 54*abf8a7e7SDavid van Moolenbroek } else { 55*abf8a7e7SDavid van Moolenbroek rpupd->next_rpupd = prev_rpupd->next_rpupd; 56*abf8a7e7SDavid van Moolenbroek rpupd->prev_rpupd = prev_rpupd; 57*abf8a7e7SDavid van Moolenbroek prev_rpupd->next_rpupd = rpupd; 58fb6bd596SCristiano Giuffrida } 59*abf8a7e7SDavid van Moolenbroek 60*abf8a7e7SDavid van Moolenbroek if (rpupd->next_rpupd != NULL) 61*abf8a7e7SDavid van Moolenbroek rpupd->next_rpupd->prev_rpupd = rpupd; 62*abf8a7e7SDavid van Moolenbroek else 63fb6bd596SCristiano Giuffrida rupdate.last_rpupd = rpupd; 64*abf8a7e7SDavid van Moolenbroek 65fb6bd596SCristiano Giuffrida rupdate.num_rpupds++; 66fb6bd596SCristiano Giuffrida 67fb6bd596SCristiano Giuffrida /* Propagate relevant flags from the new descriptor. */ 68fb6bd596SCristiano Giuffrida lu_flags = rpupd->lu_flags & (SEF_LU_INCLUDES_VM|SEF_LU_INCLUDES_RS|SEF_LU_UNSAFE|SEF_LU_MULTI); 69fb6bd596SCristiano Giuffrida if(lu_flags) { 70*abf8a7e7SDavid van Moolenbroek RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, walk_rpupd, 71*abf8a7e7SDavid van Moolenbroek walk_rpupd->lu_flags |= lu_flags; 72*abf8a7e7SDavid van Moolenbroek walk_rpupd->init_flags |= lu_flags; 73fb6bd596SCristiano Giuffrida ); 74fb6bd596SCristiano Giuffrida } 75fb6bd596SCristiano Giuffrida 76fb6bd596SCristiano Giuffrida /* Set VM/RS update descriptor pointers. */ 77fb6bd596SCristiano Giuffrida if(!rupdate.vm_rpupd && (lu_flags & SEF_LU_INCLUDES_VM)) { 78*abf8a7e7SDavid van Moolenbroek rupdate.vm_rpupd = rpupd; 79fb6bd596SCristiano Giuffrida } 80fb6bd596SCristiano Giuffrida else if(!rupdate.rs_rpupd && (lu_flags & SEF_LU_INCLUDES_RS)) { 81*abf8a7e7SDavid van Moolenbroek rupdate.rs_rpupd = rpupd; 82fb6bd596SCristiano Giuffrida } 83fb6bd596SCristiano Giuffrida } 84fb6bd596SCristiano Giuffrida 85fb6bd596SCristiano Giuffrida /*===========================================================================* 86fb6bd596SCristiano Giuffrida * rupdate_set_new_upd_flags * 87fb6bd596SCristiano Giuffrida *===========================================================================*/ 88fb6bd596SCristiano Giuffrida void rupdate_set_new_upd_flags(struct rprocupd* rpupd) 89fb6bd596SCristiano Giuffrida { 90fb6bd596SCristiano Giuffrida /* Set multi-component update flags. */ 91fb6bd596SCristiano Giuffrida if(rupdate.num_rpupds > 0) { 92fb6bd596SCristiano Giuffrida rpupd->lu_flags |= SEF_LU_MULTI; 93fb6bd596SCristiano Giuffrida rpupd->init_flags |= SEF_LU_MULTI; 94fb6bd596SCristiano Giuffrida } 95fb6bd596SCristiano Giuffrida 96fb6bd596SCristiano Giuffrida /* Propagate relevant flags from last service under update (if any). */ 97fb6bd596SCristiano Giuffrida if(rupdate.last_rpupd) { 98fb6bd596SCristiano Giuffrida int lu_flags = rupdate.last_rpupd->lu_flags & (SEF_LU_INCLUDES_VM|SEF_LU_INCLUDES_RS|SEF_LU_UNSAFE); 99fb6bd596SCristiano Giuffrida rpupd->lu_flags |= lu_flags; 100fb6bd596SCristiano Giuffrida rpupd->init_flags |= lu_flags; 101fb6bd596SCristiano Giuffrida } 102fb6bd596SCristiano Giuffrida 103fb6bd596SCristiano Giuffrida if(UPD_IS_PREPARING_ONLY(rpupd)) { 104fb6bd596SCristiano Giuffrida return; 105fb6bd596SCristiano Giuffrida } 106fb6bd596SCristiano Giuffrida 107fb6bd596SCristiano Giuffrida /* Set VM/RS update flags. */ 108fb6bd596SCristiano Giuffrida if(rpupd->rp->r_pub->endpoint == VM_PROC_NR) { 109fb6bd596SCristiano Giuffrida rpupd->lu_flags |= SEF_LU_INCLUDES_VM; 110fb6bd596SCristiano Giuffrida rpupd->init_flags |= SEF_LU_INCLUDES_VM; 111fb6bd596SCristiano Giuffrida } 112fb6bd596SCristiano Giuffrida else if(rpupd->rp->r_pub->endpoint == RS_PROC_NR) { 113fb6bd596SCristiano Giuffrida rpupd->lu_flags |= SEF_LU_INCLUDES_RS; 114fb6bd596SCristiano Giuffrida rpupd->init_flags |= SEF_LU_INCLUDES_RS; 115fb6bd596SCristiano Giuffrida } 116fb6bd596SCristiano Giuffrida } 117fb6bd596SCristiano Giuffrida 118fb6bd596SCristiano Giuffrida /*===========================================================================* 119fb6bd596SCristiano Giuffrida * rupdate_upd_init * 120fb6bd596SCristiano Giuffrida *===========================================================================*/ 121fb6bd596SCristiano Giuffrida void rupdate_upd_init(struct rprocupd* rpupd, struct rproc *rp) 122fb6bd596SCristiano Giuffrida { 123fb6bd596SCristiano Giuffrida /* Initialize an update descriptor for a given service. */ 124fb6bd596SCristiano Giuffrida memset(rpupd, 0, sizeof(*(rpupd))); 125fb6bd596SCristiano Giuffrida rpupd->prepare_state_data_gid = GRANT_INVALID; 126fb6bd596SCristiano Giuffrida rpupd->prepare_state_data.ipcf_els_gid = GRANT_INVALID; 127fb6bd596SCristiano Giuffrida rpupd->prepare_state_data.eval_gid = GRANT_INVALID; 128fb6bd596SCristiano Giuffrida rpupd->state_endpoint = NONE; 129fb6bd596SCristiano Giuffrida rpupd->rp = rp; 130fb6bd596SCristiano Giuffrida } 131fb6bd596SCristiano Giuffrida 132fb6bd596SCristiano Giuffrida /*===========================================================================* 133fb6bd596SCristiano Giuffrida * rupdate_upd_clear * 134fb6bd596SCristiano Giuffrida *===========================================================================*/ 135fb6bd596SCristiano Giuffrida void rupdate_upd_clear(struct rprocupd* rpupd) 136fb6bd596SCristiano Giuffrida { 137fb6bd596SCristiano Giuffrida /* Clear an update descriptor. */ 138fb6bd596SCristiano Giuffrida if(rpupd->rp->r_new_rp) { 139fb6bd596SCristiano Giuffrida cleanup_service(rpupd->rp->r_new_rp); 140fb6bd596SCristiano Giuffrida } 141fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data_gid != GRANT_INVALID) { 142fb6bd596SCristiano Giuffrida cpf_revoke(rpupd->prepare_state_data_gid); 143fb6bd596SCristiano Giuffrida } 144fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data.size > 0) { 145fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data.ipcf_els_gid != GRANT_INVALID) { 146fb6bd596SCristiano Giuffrida cpf_revoke(rpupd->prepare_state_data.ipcf_els_gid); 147fb6bd596SCristiano Giuffrida } 148fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data.eval_gid != GRANT_INVALID) { 149fb6bd596SCristiano Giuffrida cpf_revoke(rpupd->prepare_state_data.eval_gid); 150fb6bd596SCristiano Giuffrida } 151fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data.ipcf_els) { 152fb6bd596SCristiano Giuffrida free(rpupd->prepare_state_data.ipcf_els); 153fb6bd596SCristiano Giuffrida } 154fb6bd596SCristiano Giuffrida if(rpupd->prepare_state_data.eval_addr) { 155fb6bd596SCristiano Giuffrida free(rpupd->prepare_state_data.eval_addr); 156fb6bd596SCristiano Giuffrida } 157fb6bd596SCristiano Giuffrida } 158fb6bd596SCristiano Giuffrida rupdate_upd_init(rpupd,NULL); 159fb6bd596SCristiano Giuffrida } 160fb6bd596SCristiano Giuffrida 161fb6bd596SCristiano Giuffrida /*===========================================================================* 162fb6bd596SCristiano Giuffrida * rupdate_upd_move * 163fb6bd596SCristiano Giuffrida *===========================================================================*/ 164fb6bd596SCristiano Giuffrida void rupdate_upd_move(struct rproc* src_rp, struct rproc* dst_rp) 165fb6bd596SCristiano Giuffrida { 166fb6bd596SCristiano Giuffrida /* Move an update descriptor from one service instance to another. */ 167fb6bd596SCristiano Giuffrida dst_rp->r_upd = src_rp->r_upd; 168fb6bd596SCristiano Giuffrida dst_rp->r_upd.rp = dst_rp; 169fb6bd596SCristiano Giuffrida if(src_rp->r_new_rp) { 170fb6bd596SCristiano Giuffrida assert(!dst_rp->r_new_rp); 171fb6bd596SCristiano Giuffrida dst_rp->r_new_rp = src_rp->r_new_rp; 172fb6bd596SCristiano Giuffrida dst_rp->r_new_rp->r_old_rp = dst_rp; 173fb6bd596SCristiano Giuffrida } 174fb6bd596SCristiano Giuffrida if(dst_rp->r_upd.prev_rpupd) dst_rp->r_upd.prev_rpupd->next_rpupd = &dst_rp->r_upd; 175fb6bd596SCristiano Giuffrida if(dst_rp->r_upd.next_rpupd) dst_rp->r_upd.next_rpupd->prev_rpupd = &dst_rp->r_upd; 176fb6bd596SCristiano Giuffrida if(rupdate.first_rpupd == &src_rp->r_upd) rupdate.first_rpupd = &dst_rp->r_upd; 177fb6bd596SCristiano Giuffrida if(rupdate.last_rpupd == &src_rp->r_upd) rupdate.last_rpupd = &dst_rp->r_upd; 178fb6bd596SCristiano Giuffrida rupdate_upd_init(&src_rp->r_upd, NULL); 179fb6bd596SCristiano Giuffrida src_rp->r_new_rp = NULL; 180fb6bd596SCristiano Giuffrida } 181fb6bd596SCristiano Giuffrida 182fb6bd596SCristiano Giuffrida /*===========================================================================* 183fb6bd596SCristiano Giuffrida * request_prepare_update_service_debug * 184fb6bd596SCristiano Giuffrida *===========================================================================*/ 185fb6bd596SCristiano Giuffrida void request_prepare_update_service_debug(char *file, int line, 186fb6bd596SCristiano Giuffrida struct rproc *rp, int state) 187fb6bd596SCristiano Giuffrida { 188fb6bd596SCristiano Giuffrida /* Request a service to prepare/cancel the update. */ 189fb6bd596SCristiano Giuffrida message m; 190fb6bd596SCristiano Giuffrida struct rprocpub *rpub; 191fb6bd596SCristiano Giuffrida int no_reply; 192fb6bd596SCristiano Giuffrida 193fb6bd596SCristiano Giuffrida rpub = rp->r_pub; 194fb6bd596SCristiano Giuffrida 195fb6bd596SCristiano Giuffrida if(state != SEF_LU_STATE_NULL) { 196fb6bd596SCristiano Giuffrida struct rprocupd *rpupd = &rp->r_upd; 197fb6bd596SCristiano Giuffrida getticks(&rpupd->prepare_tm); 198fb6bd596SCristiano Giuffrida if(!UPD_IS_PREPARING_ONLY(rpupd)) { 199fb6bd596SCristiano Giuffrida assert(rp->r_new_rp); 200fb6bd596SCristiano Giuffrida rp->r_flags |= RS_UPDATING; 201fb6bd596SCristiano Giuffrida rp->r_new_rp->r_flags |= RS_UPDATING; 202fb6bd596SCristiano Giuffrida } 203fb6bd596SCristiano Giuffrida else { 204fb6bd596SCristiano Giuffrida assert(!rp->r_new_rp); 205fb6bd596SCristiano Giuffrida } 206fb6bd596SCristiano Giuffrida 207fb6bd596SCristiano Giuffrida m.m_rs_update.flags = rpupd->lu_flags; 208fb6bd596SCristiano Giuffrida m.m_rs_update.state_data_gid = rpupd->prepare_state_data_gid; 209fb6bd596SCristiano Giuffrida 210fb6bd596SCristiano Giuffrida if(rs_verbose) 211fb6bd596SCristiano Giuffrida printf("RS: %s being requested to prepare for the %s at %s:%d\n", 212fb6bd596SCristiano Giuffrida srv_to_string(rp), srv_upd_to_string(rpupd), file, line); 213fb6bd596SCristiano Giuffrida } 214fb6bd596SCristiano Giuffrida else { 215fb6bd596SCristiano Giuffrida if(rs_verbose) 216fb6bd596SCristiano Giuffrida printf("RS: %s being requested to cancel the update at %s:%d\n", 217fb6bd596SCristiano Giuffrida srv_to_string(rp), file, line); 218fb6bd596SCristiano Giuffrida } 219fb6bd596SCristiano Giuffrida 220fb6bd596SCristiano Giuffrida /* Request to prepare for the update or cancel the update. */ 221fb6bd596SCristiano Giuffrida m.m_type = RS_LU_PREPARE; 222fb6bd596SCristiano Giuffrida m.m_rs_update.state = state; 223fb6bd596SCristiano Giuffrida no_reply = !(rp->r_flags & RS_PREPARE_DONE); 224fb6bd596SCristiano Giuffrida rs_asynsend(rp, &m, no_reply); 225fb6bd596SCristiano Giuffrida } 226fb6bd596SCristiano Giuffrida 227fb6bd596SCristiano Giuffrida /*===========================================================================* 228fb6bd596SCristiano Giuffrida * srv_update * 229fb6bd596SCristiano Giuffrida *===========================================================================*/ 230fb6bd596SCristiano Giuffrida int srv_update(endpoint_t src_e, endpoint_t dst_e, int sys_upd_flags) 231fb6bd596SCristiano Giuffrida { 232fb6bd596SCristiano Giuffrida int r = OK; 233fb6bd596SCristiano Giuffrida 234fb6bd596SCristiano Giuffrida /* Ask VM to swap the slots of the two processes and tell the kernel to 235fb6bd596SCristiano Giuffrida * do the same. If VM is being updated, only perform the kernel 236fb6bd596SCristiano Giuffrida * part of the call. The new instance of VM will do the rest at 237fb6bd596SCristiano Giuffrida * initialization time. If a multi-component update includes VM, let VM 238fb6bd596SCristiano Giuffrida * handle updates at state transfer time and rollbacks afterwards. 239fb6bd596SCristiano Giuffrida */ 240fb6bd596SCristiano Giuffrida if(src_e == VM_PROC_NR) { 241fb6bd596SCristiano Giuffrida if(rs_verbose) 242fb6bd596SCristiano Giuffrida printf("RS: executing sys_update(%d, %d)\n", src_e, dst_e); 243fb6bd596SCristiano Giuffrida r = sys_update(src_e, dst_e, 244fb6bd596SCristiano Giuffrida sys_upd_flags & SF_VM_ROLLBACK ? SYS_UPD_ROLLBACK : 0); 245fb6bd596SCristiano Giuffrida } 246fb6bd596SCristiano Giuffrida else if(!RUPDATE_IS_UPD_VM_MULTI() || RUPDATE_IS_VM_INIT_DONE()) { 247fb6bd596SCristiano Giuffrida if(rs_verbose) 248fb6bd596SCristiano Giuffrida printf("RS: executing vm_update(%d, %d)\n", src_e, dst_e); 249fb6bd596SCristiano Giuffrida r = vm_update(src_e, dst_e, sys_upd_flags); 250fb6bd596SCristiano Giuffrida } 251fb6bd596SCristiano Giuffrida else { 252fb6bd596SCristiano Giuffrida if(rs_verbose) 253fb6bd596SCristiano Giuffrida printf("RS: skipping srv_update(%d, %d)\n", src_e, dst_e); 254fb6bd596SCristiano Giuffrida } 255fb6bd596SCristiano Giuffrida 256fb6bd596SCristiano Giuffrida return r; 257fb6bd596SCristiano Giuffrida } 258fb6bd596SCristiano Giuffrida 259fb6bd596SCristiano Giuffrida /*===========================================================================* 260fb6bd596SCristiano Giuffrida * update_service * 261fb6bd596SCristiano Giuffrida *===========================================================================*/ 262fb6bd596SCristiano Giuffrida int update_service(src_rpp, dst_rpp, swap_flag, sys_upd_flags) 263fb6bd596SCristiano Giuffrida struct rproc **src_rpp; 264fb6bd596SCristiano Giuffrida struct rproc **dst_rpp; 265fb6bd596SCristiano Giuffrida int swap_flag; 266fb6bd596SCristiano Giuffrida int sys_upd_flags; 267fb6bd596SCristiano Giuffrida { 268fb6bd596SCristiano Giuffrida /* Update an existing service. */ 269fb6bd596SCristiano Giuffrida int r; 270fb6bd596SCristiano Giuffrida struct rproc *src_rp; 271fb6bd596SCristiano Giuffrida struct rproc *dst_rp; 272fb6bd596SCristiano Giuffrida struct rprocpub *src_rpub; 273fb6bd596SCristiano Giuffrida struct rprocpub *dst_rpub; 274fb6bd596SCristiano Giuffrida int pid; 275fb6bd596SCristiano Giuffrida endpoint_t endpoint; 276fb6bd596SCristiano Giuffrida 277fb6bd596SCristiano Giuffrida src_rp = *src_rpp; 278fb6bd596SCristiano Giuffrida dst_rp = *dst_rpp; 279fb6bd596SCristiano Giuffrida src_rpub = src_rp->r_pub; 280fb6bd596SCristiano Giuffrida dst_rpub = dst_rp->r_pub; 281fb6bd596SCristiano Giuffrida 282fb6bd596SCristiano Giuffrida if(rs_verbose) 283fb6bd596SCristiano Giuffrida printf("RS: %s updating into %s\n", 284fb6bd596SCristiano Giuffrida srv_to_string(src_rp), srv_to_string(dst_rp)); 285fb6bd596SCristiano Giuffrida 286fb6bd596SCristiano Giuffrida /* Swap the slots of the two processes when asked to. */ 287fb6bd596SCristiano Giuffrida if(swap_flag == RS_SWAP) { 288fb6bd596SCristiano Giuffrida if((r = srv_update(src_rpub->endpoint, dst_rpub->endpoint, sys_upd_flags)) != OK) { 289fb6bd596SCristiano Giuffrida return r; 290fb6bd596SCristiano Giuffrida } 291fb6bd596SCristiano Giuffrida } 292fb6bd596SCristiano Giuffrida 293fb6bd596SCristiano Giuffrida /* Swap slots here as well. */ 294fb6bd596SCristiano Giuffrida pid = src_rp->r_pid; 295fb6bd596SCristiano Giuffrida endpoint = src_rpub->endpoint; 2968f4f859bSBen Gras 297fb6bd596SCristiano Giuffrida swap_slot(&src_rp, &dst_rp); 298fb6bd596SCristiano Giuffrida 299fb6bd596SCristiano Giuffrida /* Reassign pids and endpoints. */ 300fb6bd596SCristiano Giuffrida src_rp->r_pid = dst_rp->r_pid; 301fb6bd596SCristiano Giuffrida src_rp->r_pub->endpoint = dst_rp->r_pub->endpoint; 302fb6bd596SCristiano Giuffrida rproc_ptr[_ENDPOINT_P(src_rp->r_pub->endpoint)] = src_rp; 303fb6bd596SCristiano Giuffrida dst_rp->r_pid = pid; 304fb6bd596SCristiano Giuffrida dst_rp->r_pub->endpoint = endpoint; 305fb6bd596SCristiano Giuffrida rproc_ptr[_ENDPOINT_P(dst_rp->r_pub->endpoint)] = dst_rp; 306fb6bd596SCristiano Giuffrida 3078f4f859bSBen Gras /* Update in-RS priv structs */ 3088f4f859bSBen Gras if ((r = sys_getpriv(&src_rp->r_priv, src_rp->r_pub->endpoint)) != OK) 3098f4f859bSBen Gras panic("RS: update: could not update RS copies of priv of src: %d\n", r); 3108f4f859bSBen Gras if ((r = sys_getpriv(&dst_rp->r_priv, dst_rp->r_pub->endpoint)) != OK) 3118f4f859bSBen Gras panic("RS: update: could not update RS copies of priv of dst: %d\n", r); 3128f4f859bSBen Gras 313fb6bd596SCristiano Giuffrida /* Adjust input pointers. */ 314fb6bd596SCristiano Giuffrida *src_rpp = src_rp; 315fb6bd596SCristiano Giuffrida *dst_rpp = dst_rp; 316fb6bd596SCristiano Giuffrida 317fb6bd596SCristiano Giuffrida /* Make the new version active. */ 318fb6bd596SCristiano Giuffrida activate_service(dst_rp, src_rp); 319fb6bd596SCristiano Giuffrida 320fb6bd596SCristiano Giuffrida if(rs_verbose) 321fb6bd596SCristiano Giuffrida printf("RS: %s updated into %s\n", 322fb6bd596SCristiano Giuffrida srv_to_string(src_rp), srv_to_string(dst_rp)); 323fb6bd596SCristiano Giuffrida 324fb6bd596SCristiano Giuffrida return OK; 325fb6bd596SCristiano Giuffrida } 326fb6bd596SCristiano Giuffrida 327fb6bd596SCristiano Giuffrida /*===========================================================================* 328fb6bd596SCristiano Giuffrida * rollback_service * 329fb6bd596SCristiano Giuffrida *===========================================================================*/ 330fb6bd596SCristiano Giuffrida void rollback_service(struct rproc **new_rpp, struct rproc **old_rpp) 331fb6bd596SCristiano Giuffrida { 332fb6bd596SCristiano Giuffrida /* Rollback an updated service. */ 3331aa4eb6aSDavid van Moolenbroek struct rproc *rp; 334fb6bd596SCristiano Giuffrida int r = OK; 335fb6bd596SCristiano Giuffrida 336fb6bd596SCristiano Giuffrida /* RS is special, we may only need to swap the slots to rollback. */ 337fb6bd596SCristiano Giuffrida if((*old_rpp)->r_pub->endpoint == RS_PROC_NR) { 338fb6bd596SCristiano Giuffrida endpoint_t me = NONE; 339fb6bd596SCristiano Giuffrida char name[20]; 340fb6bd596SCristiano Giuffrida int priv_flags, init_flags; 341fb6bd596SCristiano Giuffrida 342fb6bd596SCristiano Giuffrida r = sys_whoami(&me, name, sizeof(name), &priv_flags, &init_flags); 343fb6bd596SCristiano Giuffrida assert(r == OK); 344fb6bd596SCristiano Giuffrida if(me != RS_PROC_NR) { 345fb6bd596SCristiano Giuffrida r = vm_update((*new_rpp)->r_pub->endpoint, (*old_rpp)->r_pub->endpoint, SF_VM_ROLLBACK); 346fb6bd596SCristiano Giuffrida if(rs_verbose) 347fb6bd596SCristiano Giuffrida printf("RS: %s performed rollback\n", srv_to_string(*new_rpp)); 348fb6bd596SCristiano Giuffrida } 3491aa4eb6aSDavid van Moolenbroek /* Since we may now have missed heartbeat replies, resend requests. */ 3501aa4eb6aSDavid van Moolenbroek for (rp = BEG_RPROC_ADDR; rp < END_RPROC_ADDR; rp++) 3511aa4eb6aSDavid van Moolenbroek if (rp->r_flags & RS_ACTIVE) 3521aa4eb6aSDavid van Moolenbroek rp->r_check_tm = 0; 353fb6bd596SCristiano Giuffrida } 354fb6bd596SCristiano Giuffrida else { 355fb6bd596SCristiano Giuffrida int swap_flag = ((*new_rpp)->r_flags & RS_INIT_PENDING ? RS_DONTSWAP : RS_SWAP); 356fb6bd596SCristiano Giuffrida if(rs_verbose) 357fb6bd596SCristiano Giuffrida printf("RS: %s performs rollback\n", srv_to_string(*new_rpp)); 358fb6bd596SCristiano Giuffrida if(swap_flag == RS_SWAP) { 359fb6bd596SCristiano Giuffrida /* Freeze the new instance to rollback safely. */ 360fb6bd596SCristiano Giuffrida sys_privctl((*new_rpp)->r_pub->endpoint, SYS_PRIV_DISALLOW, NULL); 361fb6bd596SCristiano Giuffrida } 362fb6bd596SCristiano Giuffrida r = update_service(new_rpp, old_rpp, swap_flag, SF_VM_ROLLBACK); 363fb6bd596SCristiano Giuffrida } 364fb6bd596SCristiano Giuffrida 365fb6bd596SCristiano Giuffrida assert(r == OK); /* can't fail */ 366fb6bd596SCristiano Giuffrida } 367fb6bd596SCristiano Giuffrida 368fb6bd596SCristiano Giuffrida /*===========================================================================* 369fb6bd596SCristiano Giuffrida * update_period * 370fb6bd596SCristiano Giuffrida *===========================================================================*/ 371fb6bd596SCristiano Giuffrida void update_period(message *m_ptr) 372fb6bd596SCristiano Giuffrida { 373fb6bd596SCristiano Giuffrida /* Periodically check the status of the update (preparation phase). */ 374fb6bd596SCristiano Giuffrida clock_t now = m_ptr->m_notify.timestamp; 375fb6bd596SCristiano Giuffrida short has_update_timed_out; 376fb6bd596SCristiano Giuffrida message m; 377fb6bd596SCristiano Giuffrida struct rprocupd *rpupd; 378fb6bd596SCristiano Giuffrida struct rproc *rp; 379fb6bd596SCristiano Giuffrida struct rprocpub *rpub; 380fb6bd596SCristiano Giuffrida 381fb6bd596SCristiano Giuffrida rpupd = rupdate.curr_rpupd; 382fb6bd596SCristiano Giuffrida rp = rpupd->rp; 383fb6bd596SCristiano Giuffrida rpub = rp->r_pub; 384fb6bd596SCristiano Giuffrida 385fb6bd596SCristiano Giuffrida /* See if a timeout has occurred. */ 386fb6bd596SCristiano Giuffrida has_update_timed_out = (rpupd->prepare_maxtime > 0) && (now - rpupd->prepare_tm > rpupd->prepare_maxtime); 387fb6bd596SCristiano Giuffrida 388fb6bd596SCristiano Giuffrida /* If an update timed out, end the update process and notify 389fb6bd596SCristiano Giuffrida * the old version that the update has been canceled. From now on, the old 390fb6bd596SCristiano Giuffrida * version will continue executing. 391fb6bd596SCristiano Giuffrida */ 392fb6bd596SCristiano Giuffrida if(has_update_timed_out) { 393fb6bd596SCristiano Giuffrida printf("RS: update failed: maximum prepare time reached\n"); 394fb6bd596SCristiano Giuffrida end_update(EINTR, RS_CANCEL); 395fb6bd596SCristiano Giuffrida } 396fb6bd596SCristiano Giuffrida } 397fb6bd596SCristiano Giuffrida 398fb6bd596SCristiano Giuffrida /*===========================================================================* 399fb6bd596SCristiano Giuffrida * start_update_prepare * 400fb6bd596SCristiano Giuffrida *===========================================================================*/ 401fb6bd596SCristiano Giuffrida int start_update_prepare(int allow_retries) 402fb6bd596SCristiano Giuffrida { 403fb6bd596SCristiano Giuffrida /* Start the preparation phase of the update process. */ 404fb6bd596SCristiano Giuffrida struct rprocupd *prev_rpupd, *rpupd; 405fb6bd596SCristiano Giuffrida struct rproc *rp, *new_rp; 406fb6bd596SCristiano Giuffrida int r; 407fb6bd596SCristiano Giuffrida 408fb6bd596SCristiano Giuffrida if(!RUPDATE_IS_UPD_SCHEDULED()) { 409fb6bd596SCristiano Giuffrida return EINVAL; 410fb6bd596SCristiano Giuffrida } 411fb6bd596SCristiano Giuffrida if(!rs_is_idle()) { 412fb6bd596SCristiano Giuffrida printf("RS: not idle now, try again\n"); 413fb6bd596SCristiano Giuffrida if(!allow_retries) { 414fb6bd596SCristiano Giuffrida abort_update_proc(EAGAIN); 415fb6bd596SCristiano Giuffrida } 416fb6bd596SCristiano Giuffrida return EAGAIN; 417fb6bd596SCristiano Giuffrida } 418fb6bd596SCristiano Giuffrida 419fb6bd596SCristiano Giuffrida if(rs_verbose) 420fb6bd596SCristiano Giuffrida printf("RS: starting the preparation phase of the update process\n"); 421fb6bd596SCristiano Giuffrida 422fb6bd596SCristiano Giuffrida if(rupdate.rs_rpupd) { 423fb6bd596SCristiano Giuffrida assert(rupdate.rs_rpupd == rupdate.last_rpupd); 424fb6bd596SCristiano Giuffrida assert(rupdate.rs_rpupd->rp->r_pub->endpoint == RS_PROC_NR); 425fb6bd596SCristiano Giuffrida assert(!UPD_IS_PREPARING_ONLY(rupdate.rs_rpupd)); 426fb6bd596SCristiano Giuffrida } 427fb6bd596SCristiano Giuffrida if(rupdate.vm_rpupd) { 428fb6bd596SCristiano Giuffrida assert(rupdate.vm_rpupd->rp->r_pub->endpoint == VM_PROC_NR); 429fb6bd596SCristiano Giuffrida assert(!UPD_IS_PREPARING_ONLY(rupdate.vm_rpupd)); 430fb6bd596SCristiano Giuffrida } 431fb6bd596SCristiano Giuffrida 432fb6bd596SCristiano Giuffrida /* If a multi-component update includes VM, fill information about old 433fb6bd596SCristiano Giuffrida * and new endpoints, as well as update flags. VM needs this to complete 434fb6bd596SCristiano Giuffrida * the update internally at state transfer time. 435fb6bd596SCristiano Giuffrida */ 436fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPD_VM_MULTI()) { 437fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 438fb6bd596SCristiano Giuffrida if(!UPD_IS_PREPARING_ONLY(rpupd)) { 439fb6bd596SCristiano Giuffrida rp = rpupd->rp; 440fb6bd596SCristiano Giuffrida new_rp = rp->r_new_rp; 441fb6bd596SCristiano Giuffrida assert(rp && new_rp); 442fb6bd596SCristiano Giuffrida rp->r_pub->old_endpoint = rpupd->state_endpoint; 443fb6bd596SCristiano Giuffrida rp->r_pub->new_endpoint = rp->r_pub->endpoint; 444fb6bd596SCristiano Giuffrida if(rpupd != rupdate.vm_rpupd && rpupd != rupdate.rs_rpupd) { 445fb6bd596SCristiano Giuffrida rp->r_pub->sys_flags |= SF_VM_UPDATE; 446fb6bd596SCristiano Giuffrida if(rpupd->lu_flags & SEF_LU_NOMMAP) { 447fb6bd596SCristiano Giuffrida rp->r_pub->sys_flags |= SF_VM_NOMMAP; 448fb6bd596SCristiano Giuffrida } 449fb6bd596SCristiano Giuffrida } 450fb6bd596SCristiano Giuffrida } 451fb6bd596SCristiano Giuffrida ); 452fb6bd596SCristiano Giuffrida } 453fb6bd596SCristiano Giuffrida 454fb6bd596SCristiano Giuffrida /* Request the first service to prepare for the update. */ 455fb6bd596SCristiano Giuffrida if(start_update_prepare_next() == NULL) { 456fb6bd596SCristiano Giuffrida /* If we are done already, end the update now. */ 457fb6bd596SCristiano Giuffrida end_update(OK, RS_REPLY); 458fb6bd596SCristiano Giuffrida return ESRCH; 459fb6bd596SCristiano Giuffrida } 460fb6bd596SCristiano Giuffrida 461fb6bd596SCristiano Giuffrida return OK; 462fb6bd596SCristiano Giuffrida } 463fb6bd596SCristiano Giuffrida 464fb6bd596SCristiano Giuffrida /*===========================================================================* 465fb6bd596SCristiano Giuffrida * start_update_prepare_next * 466fb6bd596SCristiano Giuffrida *===========================================================================*/ 467fb6bd596SCristiano Giuffrida struct rprocupd* start_update_prepare_next() 468fb6bd596SCristiano Giuffrida { 469fb6bd596SCristiano Giuffrida /* Request the next service in the update chain to prepare for the update. */ 470*abf8a7e7SDavid van Moolenbroek struct rprocupd *rpupd, *prev_rpupd, *walk_rpupd; 471*abf8a7e7SDavid van Moolenbroek struct rproc *rp, *new_rp; 472*abf8a7e7SDavid van Moolenbroek 473fb6bd596SCristiano Giuffrida if(!RUPDATE_IS_UPDATING()) { 474fb6bd596SCristiano Giuffrida rpupd = rupdate.first_rpupd; 475fb6bd596SCristiano Giuffrida } 476fb6bd596SCristiano Giuffrida else { 477fb6bd596SCristiano Giuffrida rpupd = rupdate.curr_rpupd->next_rpupd; 478fb6bd596SCristiano Giuffrida } 479fb6bd596SCristiano Giuffrida if(!rpupd) { 480fb6bd596SCristiano Giuffrida return NULL; 481fb6bd596SCristiano Giuffrida } 482*abf8a7e7SDavid van Moolenbroek 483*abf8a7e7SDavid van Moolenbroek if (RUPDATE_IS_UPD_VM_MULTI() && rpupd == rupdate.vm_rpupd) { 484*abf8a7e7SDavid van Moolenbroek /* We are doing a multicomponent live update that includes VM, and all 485*abf8a7e7SDavid van Moolenbroek * services are now ready (and thereby stopped) except VM and possibly 486*abf8a7e7SDavid van Moolenbroek * RS. This is the last point in time, and therefore also the best, that 487*abf8a7e7SDavid van Moolenbroek * we can ask the (old) VM instance to do stuff for us, before we ask it 488*abf8a7e7SDavid van Moolenbroek * to get ready as well: preallocate and pin memory, and copy over 489*abf8a7e7SDavid van Moolenbroek * memory-mapped regions. Do this now, for all services except VM 490*abf8a7e7SDavid van Moolenbroek * itself. In particular, also do it for RS, as we know that RS (yes, 491*abf8a7e7SDavid van Moolenbroek * this service) is not going to create problems from here on. 492*abf8a7e7SDavid van Moolenbroek */ 493*abf8a7e7SDavid van Moolenbroek RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, walk_rpupd, 494*abf8a7e7SDavid van Moolenbroek if (UPD_IS_PREPARING_ONLY(walk_rpupd)) 495*abf8a7e7SDavid van Moolenbroek continue; /* skip prepare-only processes */ 496*abf8a7e7SDavid van Moolenbroek if (walk_rpupd == rupdate.vm_rpupd) 497*abf8a7e7SDavid van Moolenbroek continue; /* skip VM */ 498*abf8a7e7SDavid van Moolenbroek rp = walk_rpupd->rp; 499*abf8a7e7SDavid van Moolenbroek new_rp = rp->r_new_rp; 500*abf8a7e7SDavid van Moolenbroek assert(rp && new_rp); 501*abf8a7e7SDavid van Moolenbroek if (rs_verbose) 502*abf8a7e7SDavid van Moolenbroek printf("RS: preparing VM for %s -> %s\n", srv_to_string(rp), 503*abf8a7e7SDavid van Moolenbroek srv_to_string(new_rp)); 504*abf8a7e7SDavid van Moolenbroek /* Ask VM to prepare the new instance based on the old instance. */ 505*abf8a7e7SDavid van Moolenbroek vm_prepare(rp->r_pub->new_endpoint, new_rp->r_pub->endpoint, 506*abf8a7e7SDavid van Moolenbroek rp->r_pub->sys_flags); 507*abf8a7e7SDavid van Moolenbroek ); 508*abf8a7e7SDavid van Moolenbroek } 509*abf8a7e7SDavid van Moolenbroek 510fb6bd596SCristiano Giuffrida rupdate.flags |= RS_UPDATING; 511fb6bd596SCristiano Giuffrida 512fb6bd596SCristiano Giuffrida while(1) { 513fb6bd596SCristiano Giuffrida rupdate.curr_rpupd = rpupd; 514fb6bd596SCristiano Giuffrida request_prepare_update_service(rupdate.curr_rpupd->rp, rupdate.curr_rpupd->prepare_state); 515fb6bd596SCristiano Giuffrida if(!UPD_IS_PREPARING_ONLY(rpupd)) { 516fb6bd596SCristiano Giuffrida /* Continue only if the current service requires a prepare-only update. */ 517fb6bd596SCristiano Giuffrida break; 518fb6bd596SCristiano Giuffrida } 519fb6bd596SCristiano Giuffrida if(!rupdate.curr_rpupd->next_rpupd) { 520fb6bd596SCristiano Giuffrida /* Continue only if there are services left. */ 521fb6bd596SCristiano Giuffrida break; 522fb6bd596SCristiano Giuffrida } 523fb6bd596SCristiano Giuffrida rpupd = rupdate.curr_rpupd->next_rpupd; 524fb6bd596SCristiano Giuffrida } 525fb6bd596SCristiano Giuffrida 526fb6bd596SCristiano Giuffrida return rpupd; 527fb6bd596SCristiano Giuffrida } 528fb6bd596SCristiano Giuffrida 529fb6bd596SCristiano Giuffrida /*===========================================================================* 530fb6bd596SCristiano Giuffrida * start_update * 531fb6bd596SCristiano Giuffrida *===========================================================================*/ 532fb6bd596SCristiano Giuffrida int start_update() 533fb6bd596SCristiano Giuffrida { 534fb6bd596SCristiano Giuffrida /* Start the update phase of the update process. */ 535fb6bd596SCristiano Giuffrida struct rprocupd *prev_rpupd, *rpupd; 536fb6bd596SCristiano Giuffrida int r, init_ready_pending=0; 537fb6bd596SCristiano Giuffrida 538fb6bd596SCristiano Giuffrida if(rs_verbose) 539fb6bd596SCristiano Giuffrida printf("RS: starting a %s-component update process\n", 540fb6bd596SCristiano Giuffrida RUPDATE_IS_UPD_MULTI() ? "multi" : "single"); 541fb6bd596SCristiano Giuffrida 542fb6bd596SCristiano Giuffrida assert(RUPDATE_IS_UPDATING()); 543fb6bd596SCristiano Giuffrida assert(rupdate.num_rpupds > 0); 544fb6bd596SCristiano Giuffrida assert(rupdate.num_init_ready_pending == 0); 545fb6bd596SCristiano Giuffrida assert(rupdate.first_rpupd); 546fb6bd596SCristiano Giuffrida assert(rupdate.last_rpupd); 547fb6bd596SCristiano Giuffrida assert(rupdate.curr_rpupd == rupdate.last_rpupd); 548fb6bd596SCristiano Giuffrida rupdate.flags |= RS_INITIALIZING; 549fb6bd596SCristiano Giuffrida 550fb6bd596SCristiano Giuffrida /* Cancel the update for the prepare-only services now. */ 551fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 552fb6bd596SCristiano Giuffrida if(UPD_IS_PREPARING_ONLY(rpupd)) { 553fb6bd596SCristiano Giuffrida request_prepare_update_service(rpupd->rp, SEF_LU_STATE_NULL); 554fb6bd596SCristiano Giuffrida } 555fb6bd596SCristiano Giuffrida ); 556fb6bd596SCristiano Giuffrida 557fb6bd596SCristiano Giuffrida /* Iterate over all the processes scheduled for the update. Update each 558fb6bd596SCristiano Giuffrida * service and initialize the new instance. If VM is part of a 559fb6bd596SCristiano Giuffrida * multi-component live update, initialize VM first. 560fb6bd596SCristiano Giuffrida */ 561fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 562fb6bd596SCristiano Giuffrida rupdate.curr_rpupd = rpupd; 563fb6bd596SCristiano Giuffrida if(!UPD_IS_PREPARING_ONLY(rpupd)) { 564fb6bd596SCristiano Giuffrida init_ready_pending=1; 565fb6bd596SCristiano Giuffrida r = start_srv_update(rpupd); 566fb6bd596SCristiano Giuffrida if(r != OK) { 567fb6bd596SCristiano Giuffrida return r; 568fb6bd596SCristiano Giuffrida } 569fb6bd596SCristiano Giuffrida if(!RUPDATE_IS_UPD_VM_MULTI() || rpupd == rupdate.vm_rpupd) { 570fb6bd596SCristiano Giuffrida r = complete_srv_update(rpupd); 571fb6bd596SCristiano Giuffrida if(r != OK) { 572fb6bd596SCristiano Giuffrida return r; 573fb6bd596SCristiano Giuffrida } 574fb6bd596SCristiano Giuffrida } 575fb6bd596SCristiano Giuffrida } 576fb6bd596SCristiano Giuffrida ); 577fb6bd596SCristiano Giuffrida 578fb6bd596SCristiano Giuffrida /* End update if there is nothing more to do. */ 579fb6bd596SCristiano Giuffrida if (!init_ready_pending) { 580fb6bd596SCristiano Giuffrida end_update(OK, 0); 581fb6bd596SCristiano Giuffrida return OK; 582fb6bd596SCristiano Giuffrida } 583fb6bd596SCristiano Giuffrida 584fb6bd596SCristiano Giuffrida /* Handle multi-component live updates including VM. */ 585fb6bd596SCristiano Giuffrida if(RUPDATE_IS_UPD_VM_MULTI()) { 586fb6bd596SCristiano Giuffrida message m; 587fb6bd596SCristiano Giuffrida /* Check VM initialization, assume failure after timeout. */ 588fb6bd596SCristiano Giuffrida if (rs_verbose) 589fb6bd596SCristiano Giuffrida printf("RS: waiting for VM to initialize...\n"); 590fb6bd596SCristiano Giuffrida r = rs_receive_ticks(VM_PROC_NR, &m, NULL, UPD_INIT_MAXTIME(rupdate.vm_rpupd)); 591fb6bd596SCristiano Giuffrida if(r != OK || m.m_type != RS_INIT || m.m_rs_init.result != OK) { 592fb6bd596SCristiano Giuffrida r = (r == OK && m.m_type == RS_INIT ? m.m_rs_init.result : EINTR); 593fb6bd596SCristiano Giuffrida m.m_source = VM_PROC_NR; 594fb6bd596SCristiano Giuffrida m.m_type = RS_INIT; 595fb6bd596SCristiano Giuffrida m.m_rs_init.result = r; 596fb6bd596SCristiano Giuffrida } 597fb6bd596SCristiano Giuffrida do_init_ready(&m); 598fb6bd596SCristiano Giuffrida /* If initialization was successfull, complete the update. */ 599fb6bd596SCristiano Giuffrida if(r == OK) { 600fb6bd596SCristiano Giuffrida /* Reply and unblock VM immediately. */ 601fb6bd596SCristiano Giuffrida m.m_type = OK; 602fb6bd596SCristiano Giuffrida reply(VM_PROC_NR, NULL, &m); 603fb6bd596SCristiano Giuffrida /* Initialize other services. */ 604fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 605fb6bd596SCristiano Giuffrida if(!UPD_IS_PREPARING_ONLY(rpupd) && rpupd != rupdate.vm_rpupd) { 606fb6bd596SCristiano Giuffrida r = complete_srv_update(rpupd); 607fb6bd596SCristiano Giuffrida if(r != OK) { 608fb6bd596SCristiano Giuffrida return r; 609fb6bd596SCristiano Giuffrida } 610fb6bd596SCristiano Giuffrida } 611fb6bd596SCristiano Giuffrida ); 612fb6bd596SCristiano Giuffrida } 613fb6bd596SCristiano Giuffrida } 614fb6bd596SCristiano Giuffrida 615fb6bd596SCristiano Giuffrida return OK; 616fb6bd596SCristiano Giuffrida } 617fb6bd596SCristiano Giuffrida 618fb6bd596SCristiano Giuffrida /*===========================================================================* 619fb6bd596SCristiano Giuffrida * start_srv_update * 620fb6bd596SCristiano Giuffrida *===========================================================================*/ 621fb6bd596SCristiano Giuffrida int start_srv_update(struct rprocupd *rpupd) 622fb6bd596SCristiano Giuffrida { 623fb6bd596SCristiano Giuffrida /* Start updating a single service given its update descriptor. */ 624fb6bd596SCristiano Giuffrida struct rproc *old_rp, *new_rp; 625fb6bd596SCristiano Giuffrida int r, sys_upd_flags = 0; 626fb6bd596SCristiano Giuffrida 627fb6bd596SCristiano Giuffrida old_rp = rpupd->rp; 628fb6bd596SCristiano Giuffrida new_rp = old_rp->r_new_rp; 629fb6bd596SCristiano Giuffrida assert(old_rp && new_rp); 630fb6bd596SCristiano Giuffrida 631fb6bd596SCristiano Giuffrida if(rs_verbose) 632fb6bd596SCristiano Giuffrida printf("RS: %s starting the %s\n", srv_to_string(old_rp), srv_upd_to_string(rpupd)); 633fb6bd596SCristiano Giuffrida 634fb6bd596SCristiano Giuffrida rupdate.num_init_ready_pending++; 635fb6bd596SCristiano Giuffrida new_rp->r_flags |= RS_INITIALIZING; 636fb6bd596SCristiano Giuffrida new_rp->r_flags |= RS_INIT_PENDING; 637fb6bd596SCristiano Giuffrida if(rpupd->lu_flags & SEF_LU_NOMMAP) { 638fb6bd596SCristiano Giuffrida sys_upd_flags |= SF_VM_NOMMAP; 639fb6bd596SCristiano Giuffrida } 640fb6bd596SCristiano Giuffrida 641fb6bd596SCristiano Giuffrida /* Perform the update, skip for RS. */ 642fb6bd596SCristiano Giuffrida if(old_rp->r_pub->endpoint != RS_PROC_NR) { 643fb6bd596SCristiano Giuffrida r = update_service(&old_rp, &new_rp, RS_SWAP, sys_upd_flags); 644fb6bd596SCristiano Giuffrida if(r != OK) { 645fb6bd596SCristiano Giuffrida end_update(r, RS_REPLY); 646fb6bd596SCristiano Giuffrida printf("RS: update failed: error %d\n", r); 647fb6bd596SCristiano Giuffrida return r; 648fb6bd596SCristiano Giuffrida } 649fb6bd596SCristiano Giuffrida } 650fb6bd596SCristiano Giuffrida 651fb6bd596SCristiano Giuffrida return OK; 652fb6bd596SCristiano Giuffrida } 653fb6bd596SCristiano Giuffrida 654fb6bd596SCristiano Giuffrida /*===========================================================================* 655fb6bd596SCristiano Giuffrida * complete_srv_update * 656fb6bd596SCristiano Giuffrida *===========================================================================*/ 657fb6bd596SCristiano Giuffrida int complete_srv_update(struct rprocupd *rpupd) 658fb6bd596SCristiano Giuffrida { 659fb6bd596SCristiano Giuffrida /* Complete update of a service given its update descriptor. */ 660fb6bd596SCristiano Giuffrida struct rproc *old_rp, *new_rp; 661fb6bd596SCristiano Giuffrida int r; 662fb6bd596SCristiano Giuffrida 663fb6bd596SCristiano Giuffrida old_rp = rpupd->rp; 664fb6bd596SCristiano Giuffrida new_rp = old_rp->r_new_rp; 665fb6bd596SCristiano Giuffrida assert(old_rp && new_rp); 666fb6bd596SCristiano Giuffrida 667fb6bd596SCristiano Giuffrida if(rs_verbose) 668fb6bd596SCristiano Giuffrida printf("RS: %s completing the %s\n", srv_to_string(old_rp), srv_upd_to_string(rpupd)); 669fb6bd596SCristiano Giuffrida 670fb6bd596SCristiano Giuffrida new_rp->r_flags &= ~RS_INIT_PENDING; 671fb6bd596SCristiano Giuffrida 672fb6bd596SCristiano Giuffrida /* If RS itself is updating, yield control to the new version immediately. */ 673fb6bd596SCristiano Giuffrida if(old_rp->r_pub->endpoint == RS_PROC_NR) { 674fb6bd596SCristiano Giuffrida r = init_service(new_rp, SEF_INIT_LU, rpupd->init_flags); 675fb6bd596SCristiano Giuffrida if(r != OK) { 676fb6bd596SCristiano Giuffrida panic("unable to initialize the new RS instance: %d", r); 677fb6bd596SCristiano Giuffrida } 678fb6bd596SCristiano Giuffrida if(rs_verbose) 679fb6bd596SCristiano Giuffrida printf("RS: %s is the new RS instance we'll yield control to\n", srv_to_string(new_rp)); 680fb6bd596SCristiano Giuffrida r = sys_privctl(new_rp->r_pub->endpoint, SYS_PRIV_YIELD, NULL); 681fb6bd596SCristiano Giuffrida if(r != OK) { 682fb6bd596SCristiano Giuffrida panic("unable to yield control to the new RS instance: %d", r); 683fb6bd596SCristiano Giuffrida } 684fb6bd596SCristiano Giuffrida /* If we get this far, the new version failed to initialize. Rollback. */ 685fb6bd596SCristiano Giuffrida rollback_service(&new_rp, &old_rp); 686fb6bd596SCristiano Giuffrida end_update(ERESTART, RS_REPLY); 687fb6bd596SCristiano Giuffrida printf("RS: update failed: state transfer failed for the new RS instance\n"); 688fb6bd596SCristiano Giuffrida return ERESTART; 689fb6bd596SCristiano Giuffrida } 690fb6bd596SCristiano Giuffrida 691fb6bd596SCristiano Giuffrida /* Let the new version run. */ 692fb6bd596SCristiano Giuffrida r = run_service(new_rp, SEF_INIT_LU, rpupd->init_flags); 693fb6bd596SCristiano Giuffrida if(r != OK) { 694fb6bd596SCristiano Giuffrida /* Something went wrong. Rollback. */ 695fb6bd596SCristiano Giuffrida rollback_service(&new_rp, &old_rp); 696fb6bd596SCristiano Giuffrida end_update(r, RS_REPLY); 697fb6bd596SCristiano Giuffrida printf("RS: update failed: error %d\n", r); 698fb6bd596SCristiano Giuffrida return r; 699fb6bd596SCristiano Giuffrida } 700fb6bd596SCristiano Giuffrida 701fb6bd596SCristiano Giuffrida return OK; 702fb6bd596SCristiano Giuffrida } 703fb6bd596SCristiano Giuffrida 704fb6bd596SCristiano Giuffrida /*===========================================================================* 705fb6bd596SCristiano Giuffrida * abort_update_proc * 706fb6bd596SCristiano Giuffrida *===========================================================================*/ 707fb6bd596SCristiano Giuffrida int abort_update_proc(int reason) 708fb6bd596SCristiano Giuffrida { 709fb6bd596SCristiano Giuffrida /* This function is called to abort a scheduled/in-progress update process 710fb6bd596SCristiano Giuffrida * indiscriminately. If the update is in progress, simply pretend the 711fb6bd596SCristiano Giuffrida * current service is causing premature termination of the update. 712fb6bd596SCristiano Giuffrida */ 713fb6bd596SCristiano Giuffrida int is_updating = RUPDATE_IS_UPDATING(); 714fb6bd596SCristiano Giuffrida assert(reason != OK); 715fb6bd596SCristiano Giuffrida 716fb6bd596SCristiano Giuffrida if(!is_updating && !RUPDATE_IS_UPD_SCHEDULED()) { 717fb6bd596SCristiano Giuffrida return EINVAL; 718fb6bd596SCristiano Giuffrida } 719fb6bd596SCristiano Giuffrida 720fb6bd596SCristiano Giuffrida if(rs_verbose) 721fb6bd596SCristiano Giuffrida printf("RS: aborting the %s update process prematurely\n", 722fb6bd596SCristiano Giuffrida is_updating ? "in-progress" : "scheduled"); 723fb6bd596SCristiano Giuffrida 724fb6bd596SCristiano Giuffrida if(!is_updating) { 725fb6bd596SCristiano Giuffrida rupdate_clear_upds(); 726fb6bd596SCristiano Giuffrida return OK; 727fb6bd596SCristiano Giuffrida } 728fb6bd596SCristiano Giuffrida 729fb6bd596SCristiano Giuffrida if(rupdate.flags & RS_INITIALIZING) { 730fb6bd596SCristiano Giuffrida /* Pretend the current service under update failed to initialize. */ 731fb6bd596SCristiano Giuffrida end_update(reason, RS_REPLY); 732fb6bd596SCristiano Giuffrida } 733fb6bd596SCristiano Giuffrida else { 734fb6bd596SCristiano Giuffrida /* Pretend the current service under update failed to prepare. */ 735fb6bd596SCristiano Giuffrida end_update(reason, RS_CANCEL); 736fb6bd596SCristiano Giuffrida } 737fb6bd596SCristiano Giuffrida 738fb6bd596SCristiano Giuffrida return OK; 739fb6bd596SCristiano Giuffrida } 740fb6bd596SCristiano Giuffrida 741fb6bd596SCristiano Giuffrida /*===========================================================================* 742fb6bd596SCristiano Giuffrida * end_update_curr * 743fb6bd596SCristiano Giuffrida *===========================================================================*/ 744fb6bd596SCristiano Giuffrida static void end_update_curr(struct rprocupd *rpupd, int result, int reply_flag) 745fb6bd596SCristiano Giuffrida { 746fb6bd596SCristiano Giuffrida /* Execute the requested action on the current service under update. */ 747fb6bd596SCristiano Giuffrida struct rproc *old_rp, *new_rp; 748fb6bd596SCristiano Giuffrida assert(rpupd == rupdate.curr_rpupd); 749fb6bd596SCristiano Giuffrida 750fb6bd596SCristiano Giuffrida old_rp = rpupd->rp; 751fb6bd596SCristiano Giuffrida new_rp = old_rp->r_new_rp; 752fb6bd596SCristiano Giuffrida assert(old_rp && new_rp); 753fb6bd596SCristiano Giuffrida if(result != OK && SRV_IS_UPDATING_AND_INITIALIZING(new_rp) && rpupd != rupdate.rs_rpupd) { 754fb6bd596SCristiano Giuffrida /* Rollback in case of failures at initialization time. */ 755fb6bd596SCristiano Giuffrida rollback_service(&new_rp, &old_rp); 756fb6bd596SCristiano Giuffrida } 757fb6bd596SCristiano Giuffrida end_srv_update(rpupd, result, reply_flag); 758fb6bd596SCristiano Giuffrida } 759fb6bd596SCristiano Giuffrida 760fb6bd596SCristiano Giuffrida /*===========================================================================* 761fb6bd596SCristiano Giuffrida * end_update_before_prepare * 762fb6bd596SCristiano Giuffrida *===========================================================================*/ 763fb6bd596SCristiano Giuffrida static void end_update_before_prepare(struct rprocupd *rpupd, int result) 764fb6bd596SCristiano Giuffrida { 765fb6bd596SCristiano Giuffrida /* The service is still waiting for the update. Cleanup the new version and 766fb6bd596SCristiano Giuffrida * keep the old version running. 767fb6bd596SCristiano Giuffrida */ 768fb6bd596SCristiano Giuffrida struct rproc *old_rp, *new_rp; 769fb6bd596SCristiano Giuffrida assert(result != OK); 770fb6bd596SCristiano Giuffrida 771fb6bd596SCristiano Giuffrida old_rp = rpupd->rp; 772fb6bd596SCristiano Giuffrida new_rp = old_rp->r_new_rp; 773fb6bd596SCristiano Giuffrida assert(old_rp && new_rp); 774fb6bd596SCristiano Giuffrida cleanup_service(new_rp); 775fb6bd596SCristiano Giuffrida } 776fb6bd596SCristiano Giuffrida 777fb6bd596SCristiano Giuffrida /*===========================================================================* 778fb6bd596SCristiano Giuffrida * end_update_prepare_done * 779fb6bd596SCristiano Giuffrida *===========================================================================*/ 780fb6bd596SCristiano Giuffrida static void end_update_prepare_done(struct rprocupd *rpupd, int result) 781fb6bd596SCristiano Giuffrida { 782fb6bd596SCristiano Giuffrida /* The service is blocked after preparing for the update. Unblock it 783fb6bd596SCristiano Giuffrida * and cleanup the new version. 784fb6bd596SCristiano Giuffrida */ 785fb6bd596SCristiano Giuffrida assert(!RUPDATE_IS_INITIALIZING()); 786fb6bd596SCristiano Giuffrida assert(result != OK); 787fb6bd596SCristiano Giuffrida assert(!(rpupd->rp->r_flags & RS_INITIALIZING)); 788fb6bd596SCristiano Giuffrida 789fb6bd596SCristiano Giuffrida end_srv_update(rpupd, result, RS_REPLY); 790fb6bd596SCristiano Giuffrida } 791fb6bd596SCristiano Giuffrida 792fb6bd596SCristiano Giuffrida /*===========================================================================* 793fb6bd596SCristiano Giuffrida * end_update_initializing * 794fb6bd596SCristiano Giuffrida *===========================================================================*/ 795fb6bd596SCristiano Giuffrida static void end_update_initializing(struct rprocupd *rpupd, int result) 796fb6bd596SCristiano Giuffrida { 797fb6bd596SCristiano Giuffrida /* The service is initializing after a live udate. Cleanup the version that 798fb6bd596SCristiano Giuffrida * has to die out and let the other version run. 799fb6bd596SCristiano Giuffrida */ 800fb6bd596SCristiano Giuffrida struct rproc *old_rp, *new_rp; 801fb6bd596SCristiano Giuffrida 802fb6bd596SCristiano Giuffrida old_rp = rpupd->rp; 803fb6bd596SCristiano Giuffrida new_rp = old_rp->r_new_rp; 804fb6bd596SCristiano Giuffrida assert(old_rp && new_rp); 805fb6bd596SCristiano Giuffrida assert(SRV_IS_UPDATING_AND_INITIALIZING(new_rp)); 806fb6bd596SCristiano Giuffrida if(result != OK && rpupd != rupdate.rs_rpupd) { 807fb6bd596SCristiano Giuffrida /* Rollback in case of failures at initialization time. */ 808fb6bd596SCristiano Giuffrida rollback_service(&new_rp, &old_rp); 809fb6bd596SCristiano Giuffrida } 810fb6bd596SCristiano Giuffrida end_srv_update(rpupd, result, RS_REPLY); 811fb6bd596SCristiano Giuffrida } 812fb6bd596SCristiano Giuffrida 813fb6bd596SCristiano Giuffrida /*===========================================================================* 814fb6bd596SCristiano Giuffrida * end_update_rev_iter * 815fb6bd596SCristiano Giuffrida *===========================================================================*/ 816fb6bd596SCristiano Giuffrida static void end_update_rev_iter(int result, int reply_flag, 817fb6bd596SCristiano Giuffrida struct rprocupd *skip_rpupd, struct rprocupd *only_rpupd) 818fb6bd596SCristiano Giuffrida { 819fb6bd596SCristiano Giuffrida /* End the update for all the requested services. */ 820fb6bd596SCristiano Giuffrida struct rprocupd *prev_rpupd, *rpupd; 821fb6bd596SCristiano Giuffrida short is_curr, is_before_curr, is_after_curr; 822fb6bd596SCristiano Giuffrida 823fb6bd596SCristiano Giuffrida is_after_curr = 1; 824fb6bd596SCristiano Giuffrida RUPDATE_REV_ITER(rupdate.last_rpupd, prev_rpupd, rpupd, 825fb6bd596SCristiano Giuffrida is_curr = (rupdate.curr_rpupd == rpupd); 826fb6bd596SCristiano Giuffrida is_after_curr = is_after_curr && !is_curr; 827fb6bd596SCristiano Giuffrida if(!UPD_IS_PREPARING_ONLY(rpupd)) { 828fb6bd596SCristiano Giuffrida short is_before_prepare; 829fb6bd596SCristiano Giuffrida short is_prepare_done; 830fb6bd596SCristiano Giuffrida short is_initializing; 831fb6bd596SCristiano Giuffrida is_before_curr = !is_curr && !is_after_curr; 832fb6bd596SCristiano Giuffrida if(RUPDATE_IS_INITIALIZING()) { 833fb6bd596SCristiano Giuffrida is_before_prepare = 0; 834fb6bd596SCristiano Giuffrida is_prepare_done = is_after_curr; 835fb6bd596SCristiano Giuffrida is_initializing = is_before_curr; 836fb6bd596SCristiano Giuffrida } 837fb6bd596SCristiano Giuffrida else { 838fb6bd596SCristiano Giuffrida is_before_prepare = is_after_curr; 839fb6bd596SCristiano Giuffrida is_prepare_done = is_before_curr; 840fb6bd596SCristiano Giuffrida is_initializing = 0; 841fb6bd596SCristiano Giuffrida } 842fb6bd596SCristiano Giuffrida if((!skip_rpupd || rpupd != skip_rpupd) && (!only_rpupd || rpupd == only_rpupd)) { 843fb6bd596SCristiano Giuffrida /* Analyze different cases. */ 844fb6bd596SCristiano Giuffrida if(is_curr) { 845fb6bd596SCristiano Giuffrida end_update_curr(rpupd, result, reply_flag); 846fb6bd596SCristiano Giuffrida } 847fb6bd596SCristiano Giuffrida else if(is_before_prepare) { 848fb6bd596SCristiano Giuffrida end_update_before_prepare(rpupd, result); 849fb6bd596SCristiano Giuffrida } 850fb6bd596SCristiano Giuffrida else if(is_prepare_done) { 851fb6bd596SCristiano Giuffrida end_update_prepare_done(rpupd, result); 852fb6bd596SCristiano Giuffrida } 853fb6bd596SCristiano Giuffrida else { 854fb6bd596SCristiano Giuffrida assert(is_initializing); 855fb6bd596SCristiano Giuffrida end_update_initializing(rpupd, result); 856fb6bd596SCristiano Giuffrida } 857fb6bd596SCristiano Giuffrida } 858fb6bd596SCristiano Giuffrida } 859fb6bd596SCristiano Giuffrida ); 860fb6bd596SCristiano Giuffrida } 861fb6bd596SCristiano Giuffrida 862fb6bd596SCristiano Giuffrida /*===========================================================================* 863fb6bd596SCristiano Giuffrida * end_update_debug * 864fb6bd596SCristiano Giuffrida *===========================================================================*/ 865fb6bd596SCristiano Giuffrida void end_update_debug(char *file, int line, 866fb6bd596SCristiano Giuffrida int result, int reply_flag) 867fb6bd596SCristiano Giuffrida { 868fb6bd596SCristiano Giuffrida /* End an in-progress update process. */ 869fb6bd596SCristiano Giuffrida struct rprocupd *prev_rpupd, *rpupd, *rpupd_it; 870fb6bd596SCristiano Giuffrida struct rproc *rp, *old_rp, *new_rp; 871fb6bd596SCristiano Giuffrida int i, r, slot_nr; 872fb6bd596SCristiano Giuffrida 873fb6bd596SCristiano Giuffrida assert(RUPDATE_IS_UPDATING()); 874fb6bd596SCristiano Giuffrida 875fb6bd596SCristiano Giuffrida if(rs_verbose) 876fb6bd596SCristiano Giuffrida printf("RS: %s ending the update: result=%d, reply=%d at %s:%d\n", 877fb6bd596SCristiano Giuffrida srv_to_string(rupdate.curr_rpupd->rp), result, (reply_flag==RS_REPLY), 878fb6bd596SCristiano Giuffrida file, line); 879fb6bd596SCristiano Giuffrida 880fb6bd596SCristiano Giuffrida /* If the new instance of RS is active and the update failed, ending 881fb6bd596SCristiano Giuffrida * the update couldn't be any easier. 882fb6bd596SCristiano Giuffrida */ 883fb6bd596SCristiano Giuffrida if(result != OK && RUPDATE_IS_RS_INIT_DONE()) { 884fb6bd596SCristiano Giuffrida if(rs_verbose) 885fb6bd596SCristiano Giuffrida printf("RS: update failed, new RS instance will now exit\n"); 886fb6bd596SCristiano Giuffrida exit(1); 887fb6bd596SCristiano Giuffrida } 888fb6bd596SCristiano Giuffrida 889fb6bd596SCristiano Giuffrida /* If VM is updated as part of a multi-component live update and something 890fb6bd596SCristiano Giuffrida * goes wrong after VM has completed initialization, rollback is only 891fb6bd596SCristiano Giuffrida * supported in a best-effort way in unsafe mode. The new VM instance might 892fb6bd596SCristiano Giuffrida * have important state changes that won't be reflected in the old version 893fb6bd596SCristiano Giuffrida * once we rollback. 894fb6bd596SCristiano Giuffrida */ 895fb6bd596SCristiano Giuffrida if(result != OK && RUPDATE_IS_UPD_VM_MULTI() && RUPDATE_IS_VM_INIT_DONE() && (rupdate.vm_rpupd->lu_flags & SEF_LU_UNSAFE)) { 896fb6bd596SCristiano Giuffrida printf("RS: Warning rollbacking in unsafe multi-component update including VM!\n"); 897fb6bd596SCristiano Giuffrida } 898fb6bd596SCristiano Giuffrida 899fb6bd596SCristiano Giuffrida /* Handle prepare-only services first: simply cancel the update. */ 900fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 901fb6bd596SCristiano Giuffrida if(UPD_IS_PREPARING_ONLY(rpupd)) { 902fb6bd596SCristiano Giuffrida if(!RUPDATE_IS_INITIALIZING()) { 903fb6bd596SCristiano Giuffrida request_prepare_update_service(rpupd->rp, SEF_LU_STATE_NULL); 904fb6bd596SCristiano Giuffrida } 905fb6bd596SCristiano Giuffrida rpupd->rp->r_flags &= ~RS_PREPARE_DONE; 906fb6bd596SCristiano Giuffrida } 907fb6bd596SCristiano Giuffrida ); 908fb6bd596SCristiano Giuffrida 909fb6bd596SCristiano Giuffrida /* Handle all the other services now, VM always last to support rollback. */ 910fb6bd596SCristiano Giuffrida end_update_rev_iter(result, reply_flag, rupdate.vm_rpupd, NULL); 911fb6bd596SCristiano Giuffrida if(rupdate.vm_rpupd) { 912fb6bd596SCristiano Giuffrida end_update_rev_iter(result, reply_flag, NULL, rupdate.vm_rpupd); 913fb6bd596SCristiano Giuffrida } 914fb6bd596SCristiano Giuffrida 915fb6bd596SCristiano Giuffrida /* End the update and complete initialization in case of success. */ 916fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd, 917fb6bd596SCristiano Giuffrida if(prev_rpupd) { 918fb6bd596SCristiano Giuffrida rupdate_upd_clear(prev_rpupd); 919fb6bd596SCristiano Giuffrida } 920fb6bd596SCristiano Giuffrida if(result == OK && !UPD_IS_PREPARING_ONLY(rpupd)) { 921fb6bd596SCristiano Giuffrida /* The rp pointer points to the new instance in this case. */ 922fb6bd596SCristiano Giuffrida new_rp = rpupd->rp; 923fb6bd596SCristiano Giuffrida end_srv_init(new_rp); 924fb6bd596SCristiano Giuffrida } 925fb6bd596SCristiano Giuffrida ); 926fb6bd596SCristiano Giuffrida late_reply(rupdate.last_rpupd->rp, result); 927fb6bd596SCristiano Giuffrida rupdate_upd_clear(rupdate.last_rpupd); 928fb6bd596SCristiano Giuffrida RUPDATE_CLEAR(); 929fb6bd596SCristiano Giuffrida 930fb6bd596SCristiano Giuffrida /* Clear all the old/new endpoints and update flags in the public entries. */ 931fb6bd596SCristiano Giuffrida for(slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { 932fb6bd596SCristiano Giuffrida rp = &rproc[slot_nr]; 933fb6bd596SCristiano Giuffrida rp->r_pub->old_endpoint = NONE; 934fb6bd596SCristiano Giuffrida rp->r_pub->new_endpoint = NONE; 935fb6bd596SCristiano Giuffrida rp->r_pub->sys_flags &= ~(SF_VM_UPDATE|SF_VM_ROLLBACK|SF_VM_NOMMAP); 936fb6bd596SCristiano Giuffrida } 937fb6bd596SCristiano Giuffrida } 938fb6bd596SCristiano Giuffrida 939fb6bd596SCristiano Giuffrida /*===========================================================================* 940fb6bd596SCristiano Giuffrida * end_srv_update * 941fb6bd596SCristiano Giuffrida *===========================================================================*/ 942fb6bd596SCristiano Giuffrida void end_srv_update(struct rprocupd *rpupd, int result, int reply_flag) 943fb6bd596SCristiano Giuffrida { 944fb6bd596SCristiano Giuffrida /* End the update for the given service. There are two possibilities: 945fb6bd596SCristiano Giuffrida * 1) the update succeeded. In that case, cleanup the old version and mark the 946fb6bd596SCristiano Giuffrida * new version as no longer under update. 947fb6bd596SCristiano Giuffrida * 2) the update failed. In that case, cleanup the new version and mark the old 948fb6bd596SCristiano Giuffrida * version as no longer under update. Eventual late ready to update 949fb6bd596SCristiano Giuffrida * messages (if any) will simply be ignored and the service can 950fb6bd596SCristiano Giuffrida * continue executing. In addition, reset the check timestamp, so that if the 951fb6bd596SCristiano Giuffrida * service has a period, a status request will be forced in the next period. 952fb6bd596SCristiano Giuffrida */ 953fb6bd596SCristiano Giuffrida struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp; 954fb6bd596SCristiano Giuffrida struct rproc **rps; 955fb6bd596SCristiano Giuffrida 956fb6bd596SCristiano Giuffrida struct rprocpub *rpub; 957fb6bd596SCristiano Giuffrida int nr_rps, i; 958fb6bd596SCristiano Giuffrida 959fb6bd596SCristiano Giuffrida old_rp = rpupd->rp; 960fb6bd596SCristiano Giuffrida new_rp = old_rp->r_new_rp; 961fb6bd596SCristiano Giuffrida assert(old_rp && new_rp); 962fb6bd596SCristiano Giuffrida if(result == OK && new_rp->r_pub->endpoint == VM_PROC_NR && RUPDATE_IS_UPD_MULTI()) { 963fb6bd596SCristiano Giuffrida /* VM has already been replied to in case of multi-component live update. 964fb6bd596SCristiano Giuffrida * Send an update cancel message to trigger cleanup. 965fb6bd596SCristiano Giuffrida */ 966fb6bd596SCristiano Giuffrida reply_flag = RS_CANCEL; 967fb6bd596SCristiano Giuffrida } 968fb6bd596SCristiano Giuffrida 969fb6bd596SCristiano Giuffrida if(rs_verbose) 970fb6bd596SCristiano Giuffrida printf("RS: ending update from %s to %s with result=%d, reply=%d\n", 971fb6bd596SCristiano Giuffrida srv_to_string(old_rp), srv_to_string(new_rp), result, (reply_flag==RS_REPLY)); 972fb6bd596SCristiano Giuffrida 973fb6bd596SCristiano Giuffrida /* Decide which version has to die out and which version has to survive. */ 974fb6bd596SCristiano Giuffrida surviving_rp = (result == OK ? new_rp : old_rp); 975fb6bd596SCristiano Giuffrida exiting_rp = (result == OK ? old_rp : new_rp); 976fb6bd596SCristiano Giuffrida surviving_rp->r_flags &= ~RS_INITIALIZING; 977fb6bd596SCristiano Giuffrida surviving_rp->r_check_tm = 0; 978fb6bd596SCristiano Giuffrida getticks(&surviving_rp->r_alive_tm); 979fb6bd596SCristiano Giuffrida 980fb6bd596SCristiano Giuffrida /* Keep track of the surviving process in the update descriptor from now on. */ 981fb6bd596SCristiano Giuffrida rpupd->rp = surviving_rp; 982fb6bd596SCristiano Giuffrida 983fb6bd596SCristiano Giuffrida /* Unlink the two versions. */ 984fb6bd596SCristiano Giuffrida old_rp->r_new_rp = NULL; 985fb6bd596SCristiano Giuffrida new_rp->r_old_rp = NULL; 986fb6bd596SCristiano Giuffrida 987fb6bd596SCristiano Giuffrida /* Mark the version that has to survive as no longer updating and 988fb6bd596SCristiano Giuffrida * reply when asked to. 989fb6bd596SCristiano Giuffrida */ 990fb6bd596SCristiano Giuffrida surviving_rp->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING); 991fb6bd596SCristiano Giuffrida if(reply_flag == RS_REPLY) { 992fb6bd596SCristiano Giuffrida message m; 993fb6bd596SCristiano Giuffrida m.m_type = result; 994fb6bd596SCristiano Giuffrida reply(surviving_rp->r_pub->endpoint, surviving_rp, &m); 995fb6bd596SCristiano Giuffrida } 996fb6bd596SCristiano Giuffrida else if(reply_flag == RS_CANCEL) { 997fb6bd596SCristiano Giuffrida if(!(surviving_rp->r_flags & RS_TERMINATED)) { 998fb6bd596SCristiano Giuffrida request_prepare_update_service(surviving_rp, SEF_LU_STATE_NULL); 999fb6bd596SCristiano Giuffrida } 1000fb6bd596SCristiano Giuffrida } 1001fb6bd596SCristiano Giuffrida 1002fb6bd596SCristiano Giuffrida /* Cleanup or detach the version that has to die out. */ 1003fb6bd596SCristiano Giuffrida get_service_instances(exiting_rp, &rps, &nr_rps); 1004fb6bd596SCristiano Giuffrida for(i=0;i<nr_rps;i++) { 1005fb6bd596SCristiano Giuffrida if(rps[i] == old_rp && (rpupd->lu_flags & SEF_LU_DETACHED)) { 1006fb6bd596SCristiano Giuffrida message m; 1007fb6bd596SCristiano Giuffrida m.m_type = EDEADEPT; 1008fb6bd596SCristiano Giuffrida rps[i]->r_flags |= RS_CLEANUP_DETACH; 1009fb6bd596SCristiano Giuffrida cleanup_service(rps[i]); 1010fb6bd596SCristiano Giuffrida reply(rps[i]->r_pub->endpoint, rps[i], &m); 1011fb6bd596SCristiano Giuffrida } 1012fb6bd596SCristiano Giuffrida else { 1013fb6bd596SCristiano Giuffrida cleanup_service(rps[i]); 1014fb6bd596SCristiano Giuffrida } 1015fb6bd596SCristiano Giuffrida } 1016fb6bd596SCristiano Giuffrida 1017fb6bd596SCristiano Giuffrida if(rs_verbose) 1018fb6bd596SCristiano Giuffrida printf("RS: %s ended the %s\n", srv_to_string(surviving_rp), 1019fb6bd596SCristiano Giuffrida srv_upd_to_string(rpupd)); 1020fb6bd596SCristiano Giuffrida } 1021fb6bd596SCristiano Giuffrida 1022