1fb6bd596SCristiano Giuffrida
2fb6bd596SCristiano Giuffrida #include "inc.h"
3fb6bd596SCristiano Giuffrida
4fb6bd596SCristiano Giuffrida /*===========================================================================*
5fb6bd596SCristiano Giuffrida * rupdate_clear_upds *
6fb6bd596SCristiano Giuffrida *===========================================================================*/
rupdate_clear_upds()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 *===========================================================================*/
rupdate_add_upd(struct rprocupd * rpupd)23fb6bd596SCristiano Giuffrida void rupdate_add_upd(struct rprocupd* rpupd)
24fb6bd596SCristiano Giuffrida {
25fb6bd596SCristiano Giuffrida /* Add an update descriptor to the update chain. */
26abf8a7e7SDavid van Moolenbroek struct rprocupd *prev_rpupd, *walk_rpupd;
27abf8a7e7SDavid van Moolenbroek endpoint_t ep;
28fb6bd596SCristiano Giuffrida int lu_flags;
29fb6bd596SCristiano Giuffrida
30abf8a7e7SDavid van Moolenbroek /* In order to allow multicomponent-with-VM live updates to be processed
31abf8a7e7SDavid van Moolenbroek * correctly, we perform partial sorting on the chain: RS is to be last (if
32abf8a7e7SDavid van Moolenbroek * present), VM is to be right before it (if present), and all the other
33abf8a7e7SDavid van Moolenbroek * processes are to be at the start of the chain.
34abf8a7e7SDavid van Moolenbroek */
35abf8a7e7SDavid van Moolenbroek
36abf8a7e7SDavid van Moolenbroek ep = rpupd->rp->r_pub->endpoint;
37abf8a7e7SDavid van Moolenbroek
38abf8a7e7SDavid van Moolenbroek assert(rpupd->next_rpupd == NULL);
39abf8a7e7SDavid van Moolenbroek assert(rpupd->prev_rpupd == NULL);
40abf8a7e7SDavid van Moolenbroek
41abf8a7e7SDavid van Moolenbroek /* Determine what element to insert after, if not at the head. */
42abf8a7e7SDavid van Moolenbroek prev_rpupd = rupdate.last_rpupd;
43abf8a7e7SDavid van Moolenbroek if (prev_rpupd != NULL && ep != RS_PROC_NR &&
44abf8a7e7SDavid van Moolenbroek prev_rpupd->rp->r_pub->endpoint == RS_PROC_NR)
45abf8a7e7SDavid van Moolenbroek prev_rpupd = prev_rpupd->prev_rpupd;
46abf8a7e7SDavid van Moolenbroek if (prev_rpupd != NULL && ep != RS_PROC_NR && ep != VM_PROC_NR &&
47abf8a7e7SDavid van Moolenbroek prev_rpupd->rp->r_pub->endpoint == VM_PROC_NR)
48abf8a7e7SDavid van Moolenbroek prev_rpupd = prev_rpupd->prev_rpupd;
49abf8a7e7SDavid van Moolenbroek
50abf8a7e7SDavid van Moolenbroek /* Perform the insertion. */
51abf8a7e7SDavid van Moolenbroek if (prev_rpupd == NULL) {
52abf8a7e7SDavid van Moolenbroek rpupd->next_rpupd = rupdate.first_rpupd;
53abf8a7e7SDavid van Moolenbroek rupdate.first_rpupd = rupdate.curr_rpupd = rpupd;
54abf8a7e7SDavid van Moolenbroek } else {
55abf8a7e7SDavid van Moolenbroek rpupd->next_rpupd = prev_rpupd->next_rpupd;
56abf8a7e7SDavid van Moolenbroek rpupd->prev_rpupd = prev_rpupd;
57abf8a7e7SDavid van Moolenbroek prev_rpupd->next_rpupd = rpupd;
58fb6bd596SCristiano Giuffrida }
59abf8a7e7SDavid van Moolenbroek
60abf8a7e7SDavid van Moolenbroek if (rpupd->next_rpupd != NULL)
61abf8a7e7SDavid van Moolenbroek rpupd->next_rpupd->prev_rpupd = rpupd;
62abf8a7e7SDavid van Moolenbroek else
63fb6bd596SCristiano Giuffrida rupdate.last_rpupd = rpupd;
64abf8a7e7SDavid van Moolenbroek
65fb6bd596SCristiano Giuffrida rupdate.num_rpupds++;
66fb6bd596SCristiano Giuffrida
67fb6bd596SCristiano Giuffrida /* Propagate relevant flags from the new descriptor. */
68c0df94ecSDavid van Moolenbroek lu_flags = rpupd->lu_flags & (SEF_LU_INCLUDES_VM|SEF_LU_INCLUDES_RS|SEF_LU_MULTI);
69fb6bd596SCristiano Giuffrida if(lu_flags) {
70abf8a7e7SDavid van Moolenbroek RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, walk_rpupd,
71abf8a7e7SDavid van Moolenbroek walk_rpupd->lu_flags |= lu_flags;
72abf8a7e7SDavid 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)) {
78abf8a7e7SDavid van Moolenbroek rupdate.vm_rpupd = rpupd;
79fb6bd596SCristiano Giuffrida }
80fb6bd596SCristiano Giuffrida else if(!rupdate.rs_rpupd && (lu_flags & SEF_LU_INCLUDES_RS)) {
81abf8a7e7SDavid van Moolenbroek rupdate.rs_rpupd = rpupd;
82fb6bd596SCristiano Giuffrida }
83fb6bd596SCristiano Giuffrida }
84fb6bd596SCristiano Giuffrida
85fb6bd596SCristiano Giuffrida /*===========================================================================*
86fb6bd596SCristiano Giuffrida * rupdate_set_new_upd_flags *
87fb6bd596SCristiano Giuffrida *===========================================================================*/
rupdate_set_new_upd_flags(struct rprocupd * rpupd)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) {
98c0df94ecSDavid van Moolenbroek int lu_flags = rupdate.last_rpupd->lu_flags & (SEF_LU_INCLUDES_VM|SEF_LU_INCLUDES_RS);
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 *===========================================================================*/
rupdate_upd_init(struct rprocupd * rpupd,struct rproc * rp)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 *===========================================================================*/
rupdate_upd_clear(struct rprocupd * rpupd)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 *===========================================================================*/
rupdate_upd_move(struct rproc * src_rp,struct rproc * dst_rp)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 *===========================================================================*/
request_prepare_update_service_debug(char * file,int line,struct rproc * rp,int state)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;
197*d91f738bSDavid van Moolenbroek rpupd->prepare_tm = getticks();
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 *===========================================================================*/
srv_update(endpoint_t src_e,endpoint_t dst_e,int sys_upd_flags)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 *===========================================================================*/
update_service(src_rpp,dst_rpp,swap_flag,sys_upd_flags)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 *===========================================================================*/
rollback_service(struct rproc ** new_rpp,struct rproc ** old_rpp)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 *===========================================================================*/
update_period(message * m_ptr)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 *===========================================================================*/
start_update_prepare(int allow_retries)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 *===========================================================================*/
start_update_prepare_next()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. */
470abf8a7e7SDavid van Moolenbroek struct rprocupd *rpupd, *prev_rpupd, *walk_rpupd;
471abf8a7e7SDavid van Moolenbroek struct rproc *rp, *new_rp;
472abf8a7e7SDavid 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 }
482abf8a7e7SDavid van Moolenbroek
483abf8a7e7SDavid van Moolenbroek if (RUPDATE_IS_UPD_VM_MULTI() && rpupd == rupdate.vm_rpupd) {
484abf8a7e7SDavid van Moolenbroek /* We are doing a multicomponent live update that includes VM, and all
485abf8a7e7SDavid van Moolenbroek * services are now ready (and thereby stopped) except VM and possibly
486abf8a7e7SDavid van Moolenbroek * RS. This is the last point in time, and therefore also the best, that
487abf8a7e7SDavid van Moolenbroek * we can ask the (old) VM instance to do stuff for us, before we ask it
488abf8a7e7SDavid van Moolenbroek * to get ready as well: preallocate and pin memory, and copy over
489abf8a7e7SDavid van Moolenbroek * memory-mapped regions. Do this now, for all services except VM
490abf8a7e7SDavid van Moolenbroek * itself. In particular, also do it for RS, as we know that RS (yes,
491abf8a7e7SDavid van Moolenbroek * this service) is not going to create problems from here on.
492abf8a7e7SDavid van Moolenbroek */
493abf8a7e7SDavid van Moolenbroek RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, walk_rpupd,
494abf8a7e7SDavid van Moolenbroek if (UPD_IS_PREPARING_ONLY(walk_rpupd))
495abf8a7e7SDavid van Moolenbroek continue; /* skip prepare-only processes */
496abf8a7e7SDavid van Moolenbroek if (walk_rpupd == rupdate.vm_rpupd)
497abf8a7e7SDavid van Moolenbroek continue; /* skip VM */
498abf8a7e7SDavid van Moolenbroek rp = walk_rpupd->rp;
499abf8a7e7SDavid van Moolenbroek new_rp = rp->r_new_rp;
500abf8a7e7SDavid van Moolenbroek assert(rp && new_rp);
501abf8a7e7SDavid van Moolenbroek if (rs_verbose)
502abf8a7e7SDavid van Moolenbroek printf("RS: preparing VM for %s -> %s\n", srv_to_string(rp),
503abf8a7e7SDavid van Moolenbroek srv_to_string(new_rp));
504abf8a7e7SDavid van Moolenbroek /* Ask VM to prepare the new instance based on the old instance. */
505abf8a7e7SDavid van Moolenbroek vm_prepare(rp->r_pub->new_endpoint, new_rp->r_pub->endpoint,
506abf8a7e7SDavid van Moolenbroek rp->r_pub->sys_flags);
507abf8a7e7SDavid van Moolenbroek );
508abf8a7e7SDavid van Moolenbroek }
509abf8a7e7SDavid 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 *===========================================================================*/
start_update()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 *===========================================================================*/
start_srv_update(struct rprocupd * rpupd)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 *===========================================================================*/
complete_srv_update(struct rprocupd * rpupd)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 *===========================================================================*/
abort_update_proc(int reason)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 *===========================================================================*/
end_update_curr(struct rprocupd * rpupd,int result,int reply_flag)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 *===========================================================================*/
end_update_before_prepare(struct rprocupd * rpupd,int result)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 *===========================================================================*/
end_update_prepare_done(struct rprocupd * rpupd,int result)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 *===========================================================================*/
end_update_initializing(struct rprocupd * rpupd,int result)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 *===========================================================================*/
end_update_rev_iter(int result,int reply_flag,struct rprocupd * skip_rpupd,struct rprocupd * only_rpupd)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 *===========================================================================*/
end_update_debug(char * file,int line,int result,int reply_flag)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 /* Handle prepare-only services first: simply cancel the update. */
890fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd,
891fb6bd596SCristiano Giuffrida if(UPD_IS_PREPARING_ONLY(rpupd)) {
892fb6bd596SCristiano Giuffrida if(!RUPDATE_IS_INITIALIZING()) {
893fb6bd596SCristiano Giuffrida request_prepare_update_service(rpupd->rp, SEF_LU_STATE_NULL);
894fb6bd596SCristiano Giuffrida }
895fb6bd596SCristiano Giuffrida rpupd->rp->r_flags &= ~RS_PREPARE_DONE;
896fb6bd596SCristiano Giuffrida }
897fb6bd596SCristiano Giuffrida );
898fb6bd596SCristiano Giuffrida
899fb6bd596SCristiano Giuffrida /* Handle all the other services now, VM always last to support rollback. */
900fb6bd596SCristiano Giuffrida end_update_rev_iter(result, reply_flag, rupdate.vm_rpupd, NULL);
901fb6bd596SCristiano Giuffrida if(rupdate.vm_rpupd) {
902fb6bd596SCristiano Giuffrida end_update_rev_iter(result, reply_flag, NULL, rupdate.vm_rpupd);
903fb6bd596SCristiano Giuffrida }
904fb6bd596SCristiano Giuffrida
905fb6bd596SCristiano Giuffrida /* End the update and complete initialization in case of success. */
906fb6bd596SCristiano Giuffrida RUPDATE_ITER(rupdate.first_rpupd, prev_rpupd, rpupd,
907fb6bd596SCristiano Giuffrida if(prev_rpupd) {
908fb6bd596SCristiano Giuffrida rupdate_upd_clear(prev_rpupd);
909fb6bd596SCristiano Giuffrida }
910fb6bd596SCristiano Giuffrida if(result == OK && !UPD_IS_PREPARING_ONLY(rpupd)) {
911fb6bd596SCristiano Giuffrida /* The rp pointer points to the new instance in this case. */
912fb6bd596SCristiano Giuffrida new_rp = rpupd->rp;
913fb6bd596SCristiano Giuffrida end_srv_init(new_rp);
914fb6bd596SCristiano Giuffrida }
915fb6bd596SCristiano Giuffrida );
916fb6bd596SCristiano Giuffrida late_reply(rupdate.last_rpupd->rp, result);
917fb6bd596SCristiano Giuffrida rupdate_upd_clear(rupdate.last_rpupd);
918fb6bd596SCristiano Giuffrida RUPDATE_CLEAR();
919fb6bd596SCristiano Giuffrida
920fb6bd596SCristiano Giuffrida /* Clear all the old/new endpoints and update flags in the public entries. */
921fb6bd596SCristiano Giuffrida for(slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
922fb6bd596SCristiano Giuffrida rp = &rproc[slot_nr];
923fb6bd596SCristiano Giuffrida rp->r_pub->old_endpoint = NONE;
924fb6bd596SCristiano Giuffrida rp->r_pub->new_endpoint = NONE;
925fb6bd596SCristiano Giuffrida rp->r_pub->sys_flags &= ~(SF_VM_UPDATE|SF_VM_ROLLBACK|SF_VM_NOMMAP);
926fb6bd596SCristiano Giuffrida }
927fb6bd596SCristiano Giuffrida }
928fb6bd596SCristiano Giuffrida
929fb6bd596SCristiano Giuffrida /*===========================================================================*
930fb6bd596SCristiano Giuffrida * end_srv_update *
931fb6bd596SCristiano Giuffrida *===========================================================================*/
end_srv_update(struct rprocupd * rpupd,int result,int reply_flag)932fb6bd596SCristiano Giuffrida void end_srv_update(struct rprocupd *rpupd, int result, int reply_flag)
933fb6bd596SCristiano Giuffrida {
934fb6bd596SCristiano Giuffrida /* End the update for the given service. There are two possibilities:
935fb6bd596SCristiano Giuffrida * 1) the update succeeded. In that case, cleanup the old version and mark the
936fb6bd596SCristiano Giuffrida * new version as no longer under update.
937fb6bd596SCristiano Giuffrida * 2) the update failed. In that case, cleanup the new version and mark the old
938fb6bd596SCristiano Giuffrida * version as no longer under update. Eventual late ready to update
939fb6bd596SCristiano Giuffrida * messages (if any) will simply be ignored and the service can
940fb6bd596SCristiano Giuffrida * continue executing. In addition, reset the check timestamp, so that if the
941fb6bd596SCristiano Giuffrida * service has a period, a status request will be forced in the next period.
942fb6bd596SCristiano Giuffrida */
943fb6bd596SCristiano Giuffrida struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp;
944fb6bd596SCristiano Giuffrida struct rproc **rps;
945fb6bd596SCristiano Giuffrida
946fb6bd596SCristiano Giuffrida struct rprocpub *rpub;
947fb6bd596SCristiano Giuffrida int nr_rps, i;
948fb6bd596SCristiano Giuffrida
949fb6bd596SCristiano Giuffrida old_rp = rpupd->rp;
950fb6bd596SCristiano Giuffrida new_rp = old_rp->r_new_rp;
951fb6bd596SCristiano Giuffrida assert(old_rp && new_rp);
952fb6bd596SCristiano Giuffrida if(result == OK && new_rp->r_pub->endpoint == VM_PROC_NR && RUPDATE_IS_UPD_MULTI()) {
953fb6bd596SCristiano Giuffrida /* VM has already been replied to in case of multi-component live update.
954fb6bd596SCristiano Giuffrida * Send an update cancel message to trigger cleanup.
955fb6bd596SCristiano Giuffrida */
956fb6bd596SCristiano Giuffrida reply_flag = RS_CANCEL;
957fb6bd596SCristiano Giuffrida }
958fb6bd596SCristiano Giuffrida
959fb6bd596SCristiano Giuffrida if(rs_verbose)
960fb6bd596SCristiano Giuffrida printf("RS: ending update from %s to %s with result=%d, reply=%d\n",
961fb6bd596SCristiano Giuffrida srv_to_string(old_rp), srv_to_string(new_rp), result, (reply_flag==RS_REPLY));
962fb6bd596SCristiano Giuffrida
963fb6bd596SCristiano Giuffrida /* Decide which version has to die out and which version has to survive. */
964fb6bd596SCristiano Giuffrida surviving_rp = (result == OK ? new_rp : old_rp);
965fb6bd596SCristiano Giuffrida exiting_rp = (result == OK ? old_rp : new_rp);
966fb6bd596SCristiano Giuffrida surviving_rp->r_flags &= ~RS_INITIALIZING;
967fb6bd596SCristiano Giuffrida surviving_rp->r_check_tm = 0;
968*d91f738bSDavid van Moolenbroek surviving_rp->r_alive_tm = getticks();
969fb6bd596SCristiano Giuffrida
970fb6bd596SCristiano Giuffrida /* Keep track of the surviving process in the update descriptor from now on. */
971fb6bd596SCristiano Giuffrida rpupd->rp = surviving_rp;
972fb6bd596SCristiano Giuffrida
973fb6bd596SCristiano Giuffrida /* Unlink the two versions. */
974fb6bd596SCristiano Giuffrida old_rp->r_new_rp = NULL;
975fb6bd596SCristiano Giuffrida new_rp->r_old_rp = NULL;
976fb6bd596SCristiano Giuffrida
977fb6bd596SCristiano Giuffrida /* Mark the version that has to survive as no longer updating and
978fb6bd596SCristiano Giuffrida * reply when asked to.
979fb6bd596SCristiano Giuffrida */
980fb6bd596SCristiano Giuffrida surviving_rp->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING);
981fb6bd596SCristiano Giuffrida if(reply_flag == RS_REPLY) {
982fb6bd596SCristiano Giuffrida message m;
983fb6bd596SCristiano Giuffrida m.m_type = result;
984fb6bd596SCristiano Giuffrida reply(surviving_rp->r_pub->endpoint, surviving_rp, &m);
985fb6bd596SCristiano Giuffrida }
986fb6bd596SCristiano Giuffrida else if(reply_flag == RS_CANCEL) {
987fb6bd596SCristiano Giuffrida if(!(surviving_rp->r_flags & RS_TERMINATED)) {
988fb6bd596SCristiano Giuffrida request_prepare_update_service(surviving_rp, SEF_LU_STATE_NULL);
989fb6bd596SCristiano Giuffrida }
990fb6bd596SCristiano Giuffrida }
991fb6bd596SCristiano Giuffrida
992fb6bd596SCristiano Giuffrida /* Cleanup or detach the version that has to die out. */
993fb6bd596SCristiano Giuffrida get_service_instances(exiting_rp, &rps, &nr_rps);
994fb6bd596SCristiano Giuffrida for(i=0;i<nr_rps;i++) {
995fb6bd596SCristiano Giuffrida if(rps[i] == old_rp && (rpupd->lu_flags & SEF_LU_DETACHED)) {
996fb6bd596SCristiano Giuffrida message m;
997fb6bd596SCristiano Giuffrida m.m_type = EDEADEPT;
998fb6bd596SCristiano Giuffrida rps[i]->r_flags |= RS_CLEANUP_DETACH;
999fb6bd596SCristiano Giuffrida cleanup_service(rps[i]);
1000fb6bd596SCristiano Giuffrida reply(rps[i]->r_pub->endpoint, rps[i], &m);
1001fb6bd596SCristiano Giuffrida }
1002fb6bd596SCristiano Giuffrida else {
1003fb6bd596SCristiano Giuffrida cleanup_service(rps[i]);
1004fb6bd596SCristiano Giuffrida }
1005fb6bd596SCristiano Giuffrida }
1006fb6bd596SCristiano Giuffrida
1007fb6bd596SCristiano Giuffrida if(rs_verbose)
1008fb6bd596SCristiano Giuffrida printf("RS: %s ended the %s\n", srv_to_string(surviving_rp),
1009fb6bd596SCristiano Giuffrida srv_upd_to_string(rpupd));
1010fb6bd596SCristiano Giuffrida }
1011fb6bd596SCristiano Giuffrida
1012