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