xref: /minix3/minix/servers/rs/request.c (revision d91f738bd8d93aa6befa2a8d07581040607a512a)
1433d6423SLionel Sambuc /*
2433d6423SLionel Sambuc  * Changes:
3433d6423SLionel Sambuc  *   Jan 22, 2010:  Created  (Cristiano Giuffrida)
4433d6423SLionel Sambuc  */
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc #include "inc.h"
7433d6423SLionel Sambuc 
8433d6423SLionel Sambuc #include "kernel/proc.h"
9433d6423SLionel Sambuc 
10433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start);
11433d6423SLionel Sambuc 
12433d6423SLionel Sambuc /*===========================================================================*
13433d6423SLionel Sambuc  *				   do_up				     *
14433d6423SLionel Sambuc  *===========================================================================*/
15433d6423SLionel Sambuc int do_up(m_ptr)
16433d6423SLionel Sambuc message *m_ptr;					/* request message pointer */
17433d6423SLionel Sambuc {
18433d6423SLionel Sambuc /* A request was made to start a new system service. */
19433d6423SLionel Sambuc   struct rproc *rp;
20433d6423SLionel Sambuc   struct rprocpub *rpub;
21433d6423SLionel Sambuc   int r;
22433d6423SLionel Sambuc   struct rs_start rs_start;
23433d6423SLionel Sambuc   int noblock;
24fb6bd596SCristiano Giuffrida   int init_flags = 0;
25433d6423SLionel Sambuc 
26433d6423SLionel Sambuc   /* Check if the call can be allowed. */
27433d6423SLionel Sambuc   if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK)
28433d6423SLionel Sambuc       return r;
29433d6423SLionel Sambuc 
30433d6423SLionel Sambuc   /* Allocate a new system service slot. */
31433d6423SLionel Sambuc   r = alloc_slot(&rp);
32433d6423SLionel Sambuc   if(r != OK) {
33433d6423SLionel Sambuc       printf("RS: do_up: unable to allocate a new slot: %d\n", r);
34433d6423SLionel Sambuc       return r;
35433d6423SLionel Sambuc   }
36433d6423SLionel Sambuc   rpub = rp->r_pub;
37433d6423SLionel Sambuc 
38433d6423SLionel Sambuc   /* Copy the request structure. */
39433d6423SLionel Sambuc   r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
40433d6423SLionel Sambuc   if (r != OK) {
41433d6423SLionel Sambuc       return r;
42433d6423SLionel Sambuc   }
43433d6423SLionel Sambuc   r = check_request(&rs_start);
44433d6423SLionel Sambuc   if (r != OK) {
45433d6423SLionel Sambuc       return r;
46433d6423SLionel Sambuc   }
47fb6bd596SCristiano Giuffrida 
48fb6bd596SCristiano Giuffrida   /* Check flags. */
49433d6423SLionel Sambuc   noblock = (rs_start.rss_flags & RSS_NOBLOCK);
50fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) {
51fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_CRASH;
52fb6bd596SCristiano Giuffrida   }
53fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) {
54fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_FAIL;
55fb6bd596SCristiano Giuffrida   }
56fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) {
57fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_TIMEOUT;
58fb6bd596SCristiano Giuffrida   }
59fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) {
60fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_DEFCB;
61fb6bd596SCristiano Giuffrida   }
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc   /* Initialize the slot as requested. */
64433d6423SLionel Sambuc   r = init_slot(rp, &rs_start, m_ptr->m_source);
65433d6423SLionel Sambuc   if(r != OK) {
66433d6423SLionel Sambuc       printf("RS: do_up: unable to init the new slot: %d\n", r);
67433d6423SLionel Sambuc       return r;
68433d6423SLionel Sambuc   }
69433d6423SLionel Sambuc 
70433d6423SLionel Sambuc   /* Check for duplicates */
71433d6423SLionel Sambuc   if(lookup_slot_by_label(rpub->label)) {
72433d6423SLionel Sambuc       printf("RS: service with the same label '%s' already exists\n",
73433d6423SLionel Sambuc           rpub->label);
74433d6423SLionel Sambuc       return EBUSY;
75433d6423SLionel Sambuc   }
76433d6423SLionel Sambuc   if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) {
77433d6423SLionel Sambuc       printf("RS: service with the same device number %d already exists\n",
78433d6423SLionel Sambuc           rpub->dev_nr);
79433d6423SLionel Sambuc       return EBUSY;
80433d6423SLionel Sambuc   }
81433d6423SLionel Sambuc 
82433d6423SLionel Sambuc   /* All information was gathered. Now try to start the system service. */
83fb6bd596SCristiano Giuffrida   r = start_service(rp, init_flags);
84433d6423SLionel Sambuc   if(r != OK) {
85433d6423SLionel Sambuc       return r;
86433d6423SLionel Sambuc   }
87433d6423SLionel Sambuc 
88433d6423SLionel Sambuc   /* Unblock the caller immediately if requested. */
89433d6423SLionel Sambuc   if(noblock) {
90433d6423SLionel Sambuc       return OK;
91433d6423SLionel Sambuc   }
92433d6423SLionel Sambuc 
93433d6423SLionel Sambuc   /* Late reply - send a reply when service completes initialization. */
94433d6423SLionel Sambuc   rp->r_flags |= RS_LATEREPLY;
95433d6423SLionel Sambuc   rp->r_caller = m_ptr->m_source;
96433d6423SLionel Sambuc   rp->r_caller_request = RS_UP;
97433d6423SLionel Sambuc 
98433d6423SLionel Sambuc   return EDONTREPLY;
99433d6423SLionel Sambuc }
100433d6423SLionel Sambuc 
101433d6423SLionel Sambuc /*===========================================================================*
102433d6423SLionel Sambuc  *				do_down					     *
103433d6423SLionel Sambuc  *===========================================================================*/
104433d6423SLionel Sambuc int do_down(message *m_ptr)
105433d6423SLionel Sambuc {
106433d6423SLionel Sambuc   register struct rproc *rp;
107433d6423SLionel Sambuc   int s;
108433d6423SLionel Sambuc   char label[RS_MAX_LABEL_LEN];
109433d6423SLionel Sambuc 
110433d6423SLionel Sambuc   /* Copy label. */
111433d6423SLionel Sambuc   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
112433d6423SLionel Sambuc       m_ptr->m_rs_req.len, label, sizeof(label));
113433d6423SLionel Sambuc   if(s != OK) {
114433d6423SLionel Sambuc       return s;
115433d6423SLionel Sambuc   }
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc   /* Lookup slot by label. */
118433d6423SLionel Sambuc   rp = lookup_slot_by_label(label);
119433d6423SLionel Sambuc   if(!rp) {
120433d6423SLionel Sambuc       if(rs_verbose)
121433d6423SLionel Sambuc           printf("RS: do_down: service '%s' not found\n", label);
122433d6423SLionel Sambuc       return(ESRCH);
123433d6423SLionel Sambuc   }
124433d6423SLionel Sambuc 
125433d6423SLionel Sambuc   /* Check if the call can be allowed. */
126433d6423SLionel Sambuc   if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK)
127433d6423SLionel Sambuc       return s;
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc   /* Stop service. */
130433d6423SLionel Sambuc   if (rp->r_flags & RS_TERMINATED) {
131433d6423SLionel Sambuc         /* A recovery script is requesting us to bring down the service.
132433d6423SLionel Sambuc          * The service is already gone, simply perform cleanup.
133433d6423SLionel Sambuc          */
134433d6423SLionel Sambuc         if(rs_verbose)
135433d6423SLionel Sambuc             printf("RS: recovery script performs service down...\n");
136433d6423SLionel Sambuc   	unpublish_service(rp);
137433d6423SLionel Sambuc   	cleanup_service(rp);
138433d6423SLionel Sambuc     	return(OK);
139433d6423SLionel Sambuc   }
140433d6423SLionel Sambuc   stop_service(rp,RS_EXITING);
141433d6423SLionel Sambuc 
142433d6423SLionel Sambuc   /* Late reply - send a reply when service dies. */
143433d6423SLionel Sambuc   rp->r_flags |= RS_LATEREPLY;
144433d6423SLionel Sambuc   rp->r_caller = m_ptr->m_source;
145433d6423SLionel Sambuc   rp->r_caller_request = RS_DOWN;
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc   return EDONTREPLY;
148433d6423SLionel Sambuc }
149433d6423SLionel Sambuc 
150433d6423SLionel Sambuc /*===========================================================================*
151433d6423SLionel Sambuc  *				do_restart				     *
152433d6423SLionel Sambuc  *===========================================================================*/
153433d6423SLionel Sambuc int do_restart(message *m_ptr)
154433d6423SLionel Sambuc {
155433d6423SLionel Sambuc   struct rproc *rp;
156433d6423SLionel Sambuc   int s, r;
157433d6423SLionel Sambuc   char label[RS_MAX_LABEL_LEN];
158433d6423SLionel Sambuc   char script[MAX_SCRIPT_LEN];
159433d6423SLionel Sambuc 
160433d6423SLionel Sambuc   /* Copy label. */
161433d6423SLionel Sambuc   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
162433d6423SLionel Sambuc       m_ptr->m_rs_req.len, label, sizeof(label));
163433d6423SLionel Sambuc   if(s != OK) {
164433d6423SLionel Sambuc       return s;
165433d6423SLionel Sambuc   }
166433d6423SLionel Sambuc 
167433d6423SLionel Sambuc   /* Lookup slot by label. */
168433d6423SLionel Sambuc   rp = lookup_slot_by_label(label);
169433d6423SLionel Sambuc   if(!rp) {
170433d6423SLionel Sambuc       if(rs_verbose)
171433d6423SLionel Sambuc           printf("RS: do_restart: service '%s' not found\n", label);
172433d6423SLionel Sambuc       return(ESRCH);
173433d6423SLionel Sambuc   }
174433d6423SLionel Sambuc 
175433d6423SLionel Sambuc   /* Check if the call can be allowed. */
176433d6423SLionel Sambuc   if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK)
177433d6423SLionel Sambuc       return r;
178433d6423SLionel Sambuc 
179433d6423SLionel Sambuc   /* We can only be asked to restart a service from a recovery script. */
180433d6423SLionel Sambuc   if (! (rp->r_flags & RS_TERMINATED) ) {
181433d6423SLionel Sambuc       if(rs_verbose)
182433d6423SLionel Sambuc           printf("RS: %s is still running\n", srv_to_string(rp));
183433d6423SLionel Sambuc       return EBUSY;
184433d6423SLionel Sambuc   }
185433d6423SLionel Sambuc 
186433d6423SLionel Sambuc   if(rs_verbose)
187433d6423SLionel Sambuc       printf("RS: recovery script performs service restart...\n");
188433d6423SLionel Sambuc 
189433d6423SLionel Sambuc   /* Restart the service, but make sure we don't call the script again. */
190433d6423SLionel Sambuc   strcpy(script, rp->r_script);
191433d6423SLionel Sambuc   rp->r_script[0] = '\0';
192433d6423SLionel Sambuc   restart_service(rp);
193433d6423SLionel Sambuc   strcpy(rp->r_script, script);
194433d6423SLionel Sambuc 
195433d6423SLionel Sambuc   return OK;
196433d6423SLionel Sambuc }
197433d6423SLionel Sambuc 
198433d6423SLionel Sambuc /*===========================================================================*
199433d6423SLionel Sambuc  *				do_clone				     *
200433d6423SLionel Sambuc  *===========================================================================*/
201433d6423SLionel Sambuc int do_clone(message *m_ptr)
202433d6423SLionel Sambuc {
203433d6423SLionel Sambuc   struct rproc *rp;
204433d6423SLionel Sambuc   struct rprocpub *rpub;
205433d6423SLionel Sambuc   int s, r;
206433d6423SLionel Sambuc   char label[RS_MAX_LABEL_LEN];
207433d6423SLionel Sambuc 
208433d6423SLionel Sambuc   /* Copy label. */
209433d6423SLionel Sambuc   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
210433d6423SLionel Sambuc       m_ptr->m_rs_req.len, label, sizeof(label));
211433d6423SLionel Sambuc   if(s != OK) {
212433d6423SLionel Sambuc       return s;
213433d6423SLionel Sambuc   }
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc   /* Lookup slot by label. */
216433d6423SLionel Sambuc   rp = lookup_slot_by_label(label);
217433d6423SLionel Sambuc   if(!rp) {
218433d6423SLionel Sambuc       if(rs_verbose)
219433d6423SLionel Sambuc           printf("RS: do_clone: service '%s' not found\n", label);
220433d6423SLionel Sambuc       return(ESRCH);
221433d6423SLionel Sambuc   }
222433d6423SLionel Sambuc   rpub = rp->r_pub;
223433d6423SLionel Sambuc 
224433d6423SLionel Sambuc   /* Check if the call can be allowed. */
225433d6423SLionel Sambuc   if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK)
226433d6423SLionel Sambuc       return r;
227433d6423SLionel Sambuc 
228433d6423SLionel Sambuc   /* Don't clone if a replica is already available. */
229433d6423SLionel Sambuc   if(rp->r_next_rp) {
230433d6423SLionel Sambuc       return EEXIST;
231433d6423SLionel Sambuc   }
232433d6423SLionel Sambuc 
233433d6423SLionel Sambuc   /* Clone the service as requested. */
234433d6423SLionel Sambuc   rpub->sys_flags |= SF_USE_REPL;
235fb6bd596SCristiano Giuffrida   if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) {
236433d6423SLionel Sambuc       rpub->sys_flags &= ~SF_USE_REPL;
237433d6423SLionel Sambuc       return r;
238433d6423SLionel Sambuc   }
239433d6423SLionel Sambuc 
240433d6423SLionel Sambuc   return OK;
241433d6423SLionel Sambuc }
242433d6423SLionel Sambuc 
243433d6423SLionel Sambuc /*===========================================================================*
244fb6bd596SCristiano Giuffrida  *				do_unclone				     *
245fb6bd596SCristiano Giuffrida  *===========================================================================*/
246fb6bd596SCristiano Giuffrida int do_unclone(message *m_ptr)
247fb6bd596SCristiano Giuffrida {
248fb6bd596SCristiano Giuffrida   struct rproc *rp;
249fb6bd596SCristiano Giuffrida   struct rprocpub *rpub;
250fb6bd596SCristiano Giuffrida   int s, r;
251fb6bd596SCristiano Giuffrida   char label[RS_MAX_LABEL_LEN];
252fb6bd596SCristiano Giuffrida 
253fb6bd596SCristiano Giuffrida   /* Copy label. */
254fb6bd596SCristiano Giuffrida   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
255fb6bd596SCristiano Giuffrida       m_ptr->m_rs_req.len, label, sizeof(label));
256fb6bd596SCristiano Giuffrida   if(s != OK) {
257fb6bd596SCristiano Giuffrida       return s;
258fb6bd596SCristiano Giuffrida   }
259fb6bd596SCristiano Giuffrida 
260fb6bd596SCristiano Giuffrida   /* Lookup slot by label. */
261fb6bd596SCristiano Giuffrida   rp = lookup_slot_by_label(label);
262fb6bd596SCristiano Giuffrida   if(!rp) {
263fb6bd596SCristiano Giuffrida       if(rs_verbose)
264fb6bd596SCristiano Giuffrida           printf("RS: do_unclone: service '%s' not found\n", label);
265fb6bd596SCristiano Giuffrida       return(ESRCH);
266fb6bd596SCristiano Giuffrida   }
267fb6bd596SCristiano Giuffrida   rpub = rp->r_pub;
268fb6bd596SCristiano Giuffrida 
269fb6bd596SCristiano Giuffrida   /* Check if the call can be allowed. */
270fb6bd596SCristiano Giuffrida   if((r = check_call_permission(m_ptr->m_source, RS_UNCLONE, rp)) != OK)
271fb6bd596SCristiano Giuffrida       return r;
272fb6bd596SCristiano Giuffrida 
273fb6bd596SCristiano Giuffrida   /* Don't unclone if no replica is available. */
274fb6bd596SCristiano Giuffrida   if(!(rpub->sys_flags & SF_USE_REPL)) {
275fb6bd596SCristiano Giuffrida       return ENOENT;
276fb6bd596SCristiano Giuffrida   }
277fb6bd596SCristiano Giuffrida 
278fb6bd596SCristiano Giuffrida   /* Unclone the service as requested. */
279fb6bd596SCristiano Giuffrida   rpub->sys_flags &= ~SF_USE_REPL;
280fb6bd596SCristiano Giuffrida   if(rp->r_next_rp) {
281fb6bd596SCristiano Giuffrida       cleanup_service_now(rp->r_next_rp);
282fb6bd596SCristiano Giuffrida       rp->r_next_rp = NULL;
283fb6bd596SCristiano Giuffrida   }
284fb6bd596SCristiano Giuffrida 
285fb6bd596SCristiano Giuffrida   return OK;
286fb6bd596SCristiano Giuffrida }
287fb6bd596SCristiano Giuffrida 
288fb6bd596SCristiano Giuffrida /*===========================================================================*
289433d6423SLionel Sambuc  *				    do_edit				     *
290433d6423SLionel Sambuc  *===========================================================================*/
291433d6423SLionel Sambuc int do_edit(message *m_ptr)
292433d6423SLionel Sambuc {
293433d6423SLionel Sambuc   struct rproc *rp;
294433d6423SLionel Sambuc   struct rprocpub *rpub;
295433d6423SLionel Sambuc   struct rs_start rs_start;
296433d6423SLionel Sambuc   int r;
297433d6423SLionel Sambuc   char label[RS_MAX_LABEL_LEN];
298433d6423SLionel Sambuc 
299433d6423SLionel Sambuc   /* Copy the request structure. */
300433d6423SLionel Sambuc   r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
301433d6423SLionel Sambuc   if (r != OK) {
302433d6423SLionel Sambuc       return r;
303433d6423SLionel Sambuc   }
304433d6423SLionel Sambuc 
305433d6423SLionel Sambuc   /* Copy label. */
306433d6423SLionel Sambuc   r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
307433d6423SLionel Sambuc       rs_start.rss_label.l_len, label, sizeof(label));
308433d6423SLionel Sambuc   if(r != OK) {
309433d6423SLionel Sambuc       return r;
310433d6423SLionel Sambuc   }
311433d6423SLionel Sambuc 
312433d6423SLionel Sambuc   /* Lookup slot by label. */
313433d6423SLionel Sambuc   rp = lookup_slot_by_label(label);
314433d6423SLionel Sambuc   if(!rp) {
315433d6423SLionel Sambuc       if(rs_verbose)
316433d6423SLionel Sambuc           printf("RS: do_edit: service '%s' not found\n", label);
317433d6423SLionel Sambuc       return ESRCH;
318433d6423SLionel Sambuc   }
319433d6423SLionel Sambuc   rpub = rp->r_pub;
320433d6423SLionel Sambuc 
321433d6423SLionel Sambuc   /* Check if the call can be allowed. */
322433d6423SLionel Sambuc   if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK)
323433d6423SLionel Sambuc       return r;
324433d6423SLionel Sambuc 
325433d6423SLionel Sambuc   if(rs_verbose)
326433d6423SLionel Sambuc       printf("RS: %s edits settings\n", srv_to_string(rp));
327433d6423SLionel Sambuc 
328433d6423SLionel Sambuc   /* Synch the privilege structure with the kernel. */
329433d6423SLionel Sambuc   if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) {
330433d6423SLionel Sambuc       printf("RS: do_edit: unable to synch privilege structure: %d\n", r);
331433d6423SLionel Sambuc       return r;
332433d6423SLionel Sambuc   }
333433d6423SLionel Sambuc 
334433d6423SLionel Sambuc   /* Tell scheduler this process is finished */
335433d6423SLionel Sambuc   if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) {
336433d6423SLionel Sambuc       printf("RS: do_edit: scheduler won't give up process: %d\n", r);
337433d6423SLionel Sambuc       return r;
338433d6423SLionel Sambuc   }
339433d6423SLionel Sambuc 
340433d6423SLionel Sambuc   /* Edit the slot as requested. */
341433d6423SLionel Sambuc   if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) {
342433d6423SLionel Sambuc       printf("RS: do_edit: unable to edit the existing slot: %d\n", r);
343433d6423SLionel Sambuc       return r;
344433d6423SLionel Sambuc   }
345433d6423SLionel Sambuc 
346433d6423SLionel Sambuc   /* Update privilege structure. */
347433d6423SLionel Sambuc   r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv);
348433d6423SLionel Sambuc   if(r != OK) {
349433d6423SLionel Sambuc       printf("RS: do_edit: unable to update privilege structure: %d\n", r);
350433d6423SLionel Sambuc       return r;
351433d6423SLionel Sambuc   }
352433d6423SLionel Sambuc 
353433d6423SLionel Sambuc   /* Update VM calls. */
354433d6423SLionel Sambuc   if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0],
355433d6423SLionel Sambuc     !!(rp->r_priv.s_flags & SYS_PROC))) != OK) {
356433d6423SLionel Sambuc       printf("RS: do_edit: failed: %d\n", r);
357433d6423SLionel Sambuc       return r;
358433d6423SLionel Sambuc   }
359433d6423SLionel Sambuc 
360433d6423SLionel Sambuc   /* Reinitialize scheduling. */
361433d6423SLionel Sambuc   if ((r = sched_init_proc(rp)) != OK) {
362433d6423SLionel Sambuc       printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r);
363433d6423SLionel Sambuc       return r;
364433d6423SLionel Sambuc   }
365433d6423SLionel Sambuc 
366433d6423SLionel Sambuc   /* Cleanup old replicas and create a new one, if necessary. */
367433d6423SLionel Sambuc   if(rpub->sys_flags & SF_USE_REPL) {
368433d6423SLionel Sambuc       if(rp->r_next_rp) {
369433d6423SLionel Sambuc           cleanup_service(rp->r_next_rp);
370433d6423SLionel Sambuc           rp->r_next_rp = NULL;
371433d6423SLionel Sambuc       }
372fb6bd596SCristiano Giuffrida       if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) {
373433d6423SLionel Sambuc           printf("RS: warning: unable to clone %s\n", srv_to_string(rp));
374433d6423SLionel Sambuc       }
375433d6423SLionel Sambuc   }
376433d6423SLionel Sambuc 
377433d6423SLionel Sambuc   return OK;
378433d6423SLionel Sambuc }
379433d6423SLionel Sambuc 
380433d6423SLionel Sambuc /*===========================================================================*
381433d6423SLionel Sambuc  *				do_refresh				     *
382433d6423SLionel Sambuc  *===========================================================================*/
383433d6423SLionel Sambuc int do_refresh(message *m_ptr)
384433d6423SLionel Sambuc {
385433d6423SLionel Sambuc   register struct rproc *rp;
386433d6423SLionel Sambuc   int s;
387433d6423SLionel Sambuc   char label[RS_MAX_LABEL_LEN];
388433d6423SLionel Sambuc 
389433d6423SLionel Sambuc   /* Copy label. */
390433d6423SLionel Sambuc   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
391433d6423SLionel Sambuc       m_ptr->m_rs_req.len, label, sizeof(label));
392433d6423SLionel Sambuc   if(s != OK) {
393433d6423SLionel Sambuc       return s;
394433d6423SLionel Sambuc   }
395433d6423SLionel Sambuc 
396433d6423SLionel Sambuc   /* Lookup slot by label. */
397433d6423SLionel Sambuc   rp = lookup_slot_by_label(label);
398433d6423SLionel Sambuc   if(!rp) {
399433d6423SLionel Sambuc       if(rs_verbose)
400433d6423SLionel Sambuc           printf("RS: do_refresh: service '%s' not found\n", label);
401433d6423SLionel Sambuc       return(ESRCH);
402433d6423SLionel Sambuc   }
403433d6423SLionel Sambuc 
404433d6423SLionel Sambuc   /* Check if the call can be allowed. */
405433d6423SLionel Sambuc   if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK)
406433d6423SLionel Sambuc       return s;
407433d6423SLionel Sambuc 
408433d6423SLionel Sambuc   /* Refresh service. */
409433d6423SLionel Sambuc   if(rs_verbose)
410433d6423SLionel Sambuc       printf("RS: %s refreshing\n", srv_to_string(rp));
411433d6423SLionel Sambuc   stop_service(rp,RS_REFRESHING);
412433d6423SLionel Sambuc 
413fb6bd596SCristiano Giuffrida   /* Late reply - send a reply when refresh completes. */
414fb6bd596SCristiano Giuffrida   rp->r_flags |= RS_LATEREPLY;
415fb6bd596SCristiano Giuffrida   rp->r_caller = m_ptr->m_source;
416fb6bd596SCristiano Giuffrida   rp->r_caller_request = RS_REFRESH;
417fb6bd596SCristiano Giuffrida 
418fb6bd596SCristiano Giuffrida   return EDONTREPLY;
419433d6423SLionel Sambuc }
420433d6423SLionel Sambuc 
421433d6423SLionel Sambuc /*===========================================================================*
422433d6423SLionel Sambuc  *				do_shutdown				     *
423433d6423SLionel Sambuc  *===========================================================================*/
424433d6423SLionel Sambuc int do_shutdown(message *m_ptr)
425433d6423SLionel Sambuc {
426433d6423SLionel Sambuc   int slot_nr;
427433d6423SLionel Sambuc   struct rproc *rp;
428433d6423SLionel Sambuc   int r;
429433d6423SLionel Sambuc 
430433d6423SLionel Sambuc   /* Check if the call can be allowed. */
431433d6423SLionel Sambuc   if (m_ptr != NULL) {
432433d6423SLionel Sambuc       if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK)
433433d6423SLionel Sambuc           return r;
434433d6423SLionel Sambuc   }
435433d6423SLionel Sambuc 
436433d6423SLionel Sambuc   if(rs_verbose)
437433d6423SLionel Sambuc       printf("RS: shutting down...\n");
438433d6423SLionel Sambuc 
439433d6423SLionel Sambuc   /* Set flag to tell RS we are shutting down. */
440433d6423SLionel Sambuc   shutting_down = TRUE;
441433d6423SLionel Sambuc 
442433d6423SLionel Sambuc   /* Don't restart dead services. */
443433d6423SLionel Sambuc   for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
444433d6423SLionel Sambuc       rp = &rproc[slot_nr];
445433d6423SLionel Sambuc       if (rp->r_flags & RS_IN_USE) {
446433d6423SLionel Sambuc           rp->r_flags |= RS_EXITING;
447433d6423SLionel Sambuc       }
448433d6423SLionel Sambuc   }
449433d6423SLionel Sambuc   return(OK);
450433d6423SLionel Sambuc }
451433d6423SLionel Sambuc 
452433d6423SLionel Sambuc /*===========================================================================*
453433d6423SLionel Sambuc  *				do_init_ready				     *
454433d6423SLionel Sambuc  *===========================================================================*/
455433d6423SLionel Sambuc int do_init_ready(message *m_ptr)
456433d6423SLionel Sambuc {
457433d6423SLionel Sambuc   int who_p;
458433d6423SLionel Sambuc   message m;
459fb6bd596SCristiano Giuffrida   struct rproc *rp, *new_rp;
460433d6423SLionel Sambuc   struct rprocpub *rpub;
461fb6bd596SCristiano Giuffrida   int result;
462433d6423SLionel Sambuc   int r;
463433d6423SLionel Sambuc 
464433d6423SLionel Sambuc   who_p = _ENDPOINT_P(m_ptr->m_source);
465433d6423SLionel Sambuc   result = m_ptr->m_rs_init.result;
466433d6423SLionel Sambuc 
467433d6423SLionel Sambuc   rp = rproc_ptr[who_p];
468433d6423SLionel Sambuc   rpub = rp->r_pub;
469433d6423SLionel Sambuc 
470433d6423SLionel Sambuc   /* Make sure the originating service was requested to initialize. */
471433d6423SLionel Sambuc   if(! (rp->r_flags & RS_INITIALIZING) ) {
472433d6423SLionel Sambuc       if(rs_verbose)
473433d6423SLionel Sambuc           printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
474433d6423SLionel Sambuc               m_ptr->m_source);
475433d6423SLionel Sambuc       return EINVAL;
476433d6423SLionel Sambuc   }
477433d6423SLionel Sambuc 
478433d6423SLionel Sambuc   /* Check if something went wrong and the service failed to init.
479433d6423SLionel Sambuc    * In that case, kill the service.
480433d6423SLionel Sambuc    */
481433d6423SLionel Sambuc   if(result != OK) {
482433d6423SLionel Sambuc       if(rs_verbose)
483433d6423SLionel Sambuc           printf("RS: %s initialization error: %s\n", srv_to_string(rp),
484433d6423SLionel Sambuc               init_strerror(result));
485fb6bd596SCristiano Giuffrida       if (result == ERESTART && !SRV_IS_UPDATING(rp))
486433d6423SLionel Sambuc           rp->r_flags |= RS_REINCARNATE;
487433d6423SLionel Sambuc       crash_service(rp); /* simulate crash */
488fb6bd596SCristiano Giuffrida       rp->r_init_err = result;
489433d6423SLionel Sambuc       return EDONTREPLY;
490433d6423SLionel Sambuc   }
491433d6423SLionel Sambuc 
492fb6bd596SCristiano Giuffrida   if(rs_verbose)
493fb6bd596SCristiano Giuffrida       printf("RS: %s initialized\n", srv_to_string(rp));
494fb6bd596SCristiano Giuffrida 
495fb6bd596SCristiano Giuffrida   /* If updating, check if there is no service to update left. In that case,
496fb6bd596SCristiano Giuffrida    * end the update process. If VM has completed initialization as part of
497fb6bd596SCristiano Giuffrida    * multi-component live update, let the other services under update run now.
498fb6bd596SCristiano Giuffrida    */
499fb6bd596SCristiano Giuffrida   if(SRV_IS_UPDATING(rp)) {
500fb6bd596SCristiano Giuffrida       rupdate.num_init_ready_pending--;
501fb6bd596SCristiano Giuffrida       rp->r_flags |= RS_INIT_DONE;
502fb6bd596SCristiano Giuffrida       if(rupdate.num_init_ready_pending == 0) {
503fb6bd596SCristiano Giuffrida           printf("RS: update succeeded\n");
504fb6bd596SCristiano Giuffrida           end_update(OK, RS_REPLY);
505fb6bd596SCristiano Giuffrida       }
506fb6bd596SCristiano Giuffrida   }
507fb6bd596SCristiano Giuffrida   else {
508433d6423SLionel Sambuc       /* Mark the slot as no longer initializing. */
509433d6423SLionel Sambuc       rp->r_flags &= ~RS_INITIALIZING;
510433d6423SLionel Sambuc       rp->r_check_tm = 0;
511*d91f738bSDavid van Moolenbroek       rp->r_alive_tm = getticks();
512433d6423SLionel Sambuc 
513433d6423SLionel Sambuc       /* Reply and unblock the service before doing anything else. */
514433d6423SLionel Sambuc       m.m_type = OK;
515433d6423SLionel Sambuc       reply(rpub->endpoint, rp, &m);
516433d6423SLionel Sambuc 
517fb6bd596SCristiano Giuffrida       /* Finalize initialization. */
518fb6bd596SCristiano Giuffrida       end_srv_init(rp);
519433d6423SLionel Sambuc   }
520433d6423SLionel Sambuc 
521fb6bd596SCristiano Giuffrida   return EDONTREPLY;
522433d6423SLionel Sambuc }
523433d6423SLionel Sambuc 
524433d6423SLionel Sambuc /*===========================================================================*
525433d6423SLionel Sambuc  *				do_update				     *
526433d6423SLionel Sambuc  *===========================================================================*/
527433d6423SLionel Sambuc int do_update(message *m_ptr)
528433d6423SLionel Sambuc {
529433d6423SLionel Sambuc   struct rproc *rp;
530fb6bd596SCristiano Giuffrida   struct rproc *trg_rp;
531433d6423SLionel Sambuc   struct rproc *new_rp;
532433d6423SLionel Sambuc   struct rprocpub *rpub;
533fb6bd596SCristiano Giuffrida   struct rprocupd *rpupd;
534433d6423SLionel Sambuc   struct rs_start rs_start;
535fb6bd596SCristiano Giuffrida   int noblock, do_self_update, force_self_update, batch_mode, prepare_only;
536433d6423SLionel Sambuc   int s;
537433d6423SLionel Sambuc   char label[RS_MAX_LABEL_LEN];
538fb6bd596SCristiano Giuffrida   int prepare_state, prepare_maxtime;
539fb6bd596SCristiano Giuffrida   endpoint_t state_endpoint;
540fb6bd596SCristiano Giuffrida   int lu_flags = 0;
541fb6bd596SCristiano Giuffrida   int init_flags = 0;
542fb6bd596SCristiano Giuffrida   int allow_retries = 0;
543433d6423SLionel Sambuc 
544433d6423SLionel Sambuc   /* Copy the request structure. */
545433d6423SLionel Sambuc   s = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
546433d6423SLionel Sambuc   if (s != OK) {
547433d6423SLionel Sambuc       return s;
548433d6423SLionel Sambuc   }
549433d6423SLionel Sambuc 
550433d6423SLionel Sambuc   /* Copy label. */
551433d6423SLionel Sambuc   s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
552433d6423SLionel Sambuc       rs_start.rss_label.l_len, label, sizeof(label));
553433d6423SLionel Sambuc   if(s != OK) {
554433d6423SLionel Sambuc       return s;
555433d6423SLionel Sambuc   }
556433d6423SLionel Sambuc 
557433d6423SLionel Sambuc   /* Lookup slot by label. */
558433d6423SLionel Sambuc   rp = lookup_slot_by_label(label);
559433d6423SLionel Sambuc   if(!rp) {
560433d6423SLionel Sambuc       if(rs_verbose)
561433d6423SLionel Sambuc           printf("RS: do_update: service '%s' not found\n", label);
562433d6423SLionel Sambuc       return ESRCH;
563433d6423SLionel Sambuc   }
564433d6423SLionel Sambuc   rpub = rp->r_pub;
565433d6423SLionel Sambuc 
566fb6bd596SCristiano Giuffrida   /* Check flags. */
567fb6bd596SCristiano Giuffrida   noblock = (rs_start.rss_flags & RSS_NOBLOCK);
568fb6bd596SCristiano Giuffrida   do_self_update = (rs_start.rss_flags & RSS_SELF_LU);
569fb6bd596SCristiano Giuffrida   force_self_update = (rs_start.rss_flags & RSS_FORCE_SELF_LU);
570fb6bd596SCristiano Giuffrida   batch_mode = (rs_start.rss_flags & RSS_BATCH);
571fb6bd596SCristiano Giuffrida   prepare_only = (rs_start.rss_flags & RSS_PREPARE_ONLY_LU);
572fb6bd596SCristiano Giuffrida   if(do_self_update || force_self_update) {
573fb6bd596SCristiano Giuffrida       lu_flags |= SEF_LU_SELF;
574fb6bd596SCristiano Giuffrida   }
575fb6bd596SCristiano Giuffrida   if(prepare_only) {
576fb6bd596SCristiano Giuffrida       lu_flags |= SEF_LU_PREPARE_ONLY;
577fb6bd596SCristiano Giuffrida   }
578fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_ASR_LU) {
579fb6bd596SCristiano Giuffrida       lu_flags |= SEF_LU_ASR;
580fb6bd596SCristiano Giuffrida   }
581fb6bd596SCristiano Giuffrida   if(!prepare_only && (rs_start.rss_flags & RSS_DETACH)) {
582fb6bd596SCristiano Giuffrida       lu_flags |= SEF_LU_DETACHED;
583fb6bd596SCristiano Giuffrida   }
584fb6bd596SCristiano Giuffrida   if(rs_start.rss_map_prealloc_bytes <= 0
585fb6bd596SCristiano Giuffrida       && rpub->endpoint == VM_PROC_NR
586fb6bd596SCristiano Giuffrida       && (((lu_flags & (SEF_LU_SELF|SEF_LU_ASR)) != SEF_LU_SELF) || rs_start.rss_flags & RSS_FORCE_INIT_ST)
587fb6bd596SCristiano Giuffrida       && RS_VM_DEFAULT_MAP_PREALLOC_LEN > 0) {
588fb6bd596SCristiano Giuffrida       /* Give VM some mmapped regions by default on non-identical updates.*/
589fb6bd596SCristiano Giuffrida       rs_start.rss_map_prealloc_bytes = RS_VM_DEFAULT_MAP_PREALLOC_LEN;
590fb6bd596SCristiano Giuffrida       if(rs_verbose)
591fb6bd596SCristiano Giuffrida           printf("RS: %s gets %ld default mmap bytes\n", srv_to_string(rp),
592fb6bd596SCristiano Giuffrida               rs_start.rss_map_prealloc_bytes);
593fb6bd596SCristiano Giuffrida   }
594fb6bd596SCristiano Giuffrida   if((rs_start.rss_flags & RSS_NOMMAP_LU) || rs_start.rss_map_prealloc_bytes) {
595fb6bd596SCristiano Giuffrida       /* Don't inherit mmapped regions at update time if requested or if
596fb6bd596SCristiano Giuffrida        * mmap preallocation is used.
597fb6bd596SCristiano Giuffrida        */
598fb6bd596SCristiano Giuffrida       lu_flags |= SEF_LU_NOMMAP;
599fb6bd596SCristiano Giuffrida   }
600fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) {
601fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_CRASH;
602fb6bd596SCristiano Giuffrida   }
603fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) {
604fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_FAIL;
605fb6bd596SCristiano Giuffrida   }
606fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) {
607fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_TIMEOUT;
608fb6bd596SCristiano Giuffrida   }
609fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) {
610fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_DEFCB;
611fb6bd596SCristiano Giuffrida   }
612fb6bd596SCristiano Giuffrida   if(rs_start.rss_flags & RSS_FORCE_INIT_ST) {
613fb6bd596SCristiano Giuffrida       init_flags |= SEF_INIT_ST;
614fb6bd596SCristiano Giuffrida   }
615fb6bd596SCristiano Giuffrida   init_flags |= lu_flags;
616fb6bd596SCristiano Giuffrida 
617fb6bd596SCristiano Giuffrida   /* Lookup target label (if any). */
618fb6bd596SCristiano Giuffrida   trg_rp = NULL;
619fb6bd596SCristiano Giuffrida   state_endpoint = NONE;
620fb6bd596SCristiano Giuffrida   if(rs_start.rss_trg_label.l_len > 0) {
621fb6bd596SCristiano Giuffrida       s = copy_label(m_ptr->m_source, rs_start.rss_trg_label.l_addr,
622fb6bd596SCristiano Giuffrida           rs_start.rss_trg_label.l_len, label, sizeof(label));
623fb6bd596SCristiano Giuffrida       if(s != OK) {
624fb6bd596SCristiano Giuffrida           return s;
625fb6bd596SCristiano Giuffrida       }
626fb6bd596SCristiano Giuffrida       trg_rp = lookup_slot_by_label(label);
627fb6bd596SCristiano Giuffrida       if(!trg_rp) {
628fb6bd596SCristiano Giuffrida           if(rs_verbose)
629fb6bd596SCristiano Giuffrida               printf("RS: do_update: target service '%s' not found\n", label);
630fb6bd596SCristiano Giuffrida           return ESRCH;
631fb6bd596SCristiano Giuffrida       }
632fb6bd596SCristiano Giuffrida       state_endpoint = trg_rp->r_pub->endpoint;
633fb6bd596SCristiano Giuffrida   }
634fb6bd596SCristiano Giuffrida 
635433d6423SLionel Sambuc   /* Check if the call can be allowed. */
636433d6423SLionel Sambuc   if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK)
637433d6423SLionel Sambuc       return s;
638433d6423SLionel Sambuc 
639433d6423SLionel Sambuc   /* Retrieve live update state. */
640fb6bd596SCristiano Giuffrida   prepare_state = m_ptr->m_rs_update.state;
641fb6bd596SCristiano Giuffrida   if(prepare_state == SEF_LU_STATE_NULL) {
642433d6423SLionel Sambuc       return(EINVAL);
643433d6423SLionel Sambuc   }
644433d6423SLionel Sambuc 
645433d6423SLionel Sambuc   /* Retrieve prepare max time. */
646433d6423SLionel Sambuc   prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime;
647fb6bd596SCristiano Giuffrida   if(prepare_maxtime == 0) {
648433d6423SLionel Sambuc       prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME;
649433d6423SLionel Sambuc   }
650433d6423SLionel Sambuc 
651433d6423SLionel Sambuc   /* Make sure we are not already updating. */
652fb6bd596SCristiano Giuffrida   if(RUPDATE_IS_UPDATING()) {
653fb6bd596SCristiano Giuffrida       printf("RS: an update is already in progress\n");
654433d6423SLionel Sambuc       return EBUSY;
655433d6423SLionel Sambuc   }
656433d6423SLionel Sambuc 
657fb6bd596SCristiano Giuffrida   /* If an update is already scheduled, check constraints. */
658fb6bd596SCristiano Giuffrida   if(RUPDATE_IS_UPD_SCHEDULED()) {
659fb6bd596SCristiano Giuffrida       if(!batch_mode) {
660fb6bd596SCristiano Giuffrida           printf("RS: an update is already scheduled, cannot start a new one\n");
661fb6bd596SCristiano Giuffrida           return EBUSY;
662fb6bd596SCristiano Giuffrida       }
663fb6bd596SCristiano Giuffrida       if(SRV_IS_UPD_SCHEDULED(rp)) {
664fb6bd596SCristiano Giuffrida           printf("RS: the specified process is already part of the currently scheduled update\n");
665fb6bd596SCristiano Giuffrida           return EINVAL;
666fb6bd596SCristiano Giuffrida       }
667fb6bd596SCristiano Giuffrida   }
668fb6bd596SCristiano Giuffrida 
669fb6bd596SCristiano Giuffrida   /* Prepare-only update for VM, PM, and VFS is only supported with an unreachable state. */
670fb6bd596SCristiano Giuffrida   if(prepare_only
671fb6bd596SCristiano Giuffrida       && (rp->r_pub->endpoint == VM_PROC_NR || rp->r_pub->endpoint == PM_PROC_NR || rp->r_pub->endpoint == VFS_PROC_NR)) {
672fb6bd596SCristiano Giuffrida       if(prepare_state != SEF_LU_STATE_UNREACHABLE) {
673fb6bd596SCristiano Giuffrida           printf("RS: prepare-only update for VM, PM and VFS is only supported with state %d\n", SEF_LU_STATE_UNREACHABLE);
674fb6bd596SCristiano Giuffrida           return EINVAL;
675fb6bd596SCristiano Giuffrida       }
676fb6bd596SCristiano Giuffrida   }
677fb6bd596SCristiano Giuffrida 
678fb6bd596SCristiano Giuffrida   /* Prepare-only update for RS is not supported. */
679fb6bd596SCristiano Giuffrida   if(prepare_only && rp->r_pub->endpoint == RS_PROC_NR) {
680fb6bd596SCristiano Giuffrida       printf("RS: prepare-only update for RS is not supported\n");
681fb6bd596SCristiano Giuffrida       return EINVAL;
682fb6bd596SCristiano Giuffrida   }
683fb6bd596SCristiano Giuffrida 
684fb6bd596SCristiano Giuffrida   /* Initialize update descriptor. */
685fb6bd596SCristiano Giuffrida   rpupd = &rp->r_upd;
686fb6bd596SCristiano Giuffrida   rupdate_upd_init(rpupd, rp);
687fb6bd596SCristiano Giuffrida   rpupd->lu_flags |= lu_flags;
688fb6bd596SCristiano Giuffrida   rpupd->init_flags |= init_flags;
689fb6bd596SCristiano Giuffrida   rupdate_set_new_upd_flags(rpupd);
690fb6bd596SCristiano Giuffrida 
691433d6423SLionel Sambuc   /* A self update live updates a service instance into a replica, a regular
692433d6423SLionel Sambuc    * update live updates a service instance into a new version, as specified
693433d6423SLionel Sambuc    * by the given binary.
694433d6423SLionel Sambuc    */
695fb6bd596SCristiano Giuffrida   if(!prepare_only) {
696433d6423SLionel Sambuc       if(do_self_update) {
697433d6423SLionel Sambuc           if(rs_verbose)
698fb6bd596SCristiano Giuffrida               printf("RS: %s requested to perform self update\n", srv_to_string(rp));
699433d6423SLionel Sambuc 
700433d6423SLionel Sambuc           /* Clone the system service and use the replica as the new version. */
701fb6bd596SCristiano Giuffrida           s = clone_service(rp, LU_SYS_PROC, rpupd->init_flags);
702433d6423SLionel Sambuc           if(s != OK) {
703433d6423SLionel Sambuc               printf("RS: do_update: unable to clone service: %d\n", s);
704433d6423SLionel Sambuc               return s;
705433d6423SLionel Sambuc           }
706fb6bd596SCristiano Giuffrida           new_rp = rp->r_new_rp;
707433d6423SLionel Sambuc       }
708433d6423SLionel Sambuc       else {
709433d6423SLionel Sambuc           if(rs_verbose)
710fb6bd596SCristiano Giuffrida               printf("RS: %s requested to perform %s update\n", srv_to_string(rp),
711fb6bd596SCristiano Giuffrida                   force_self_update ? "(forced) self" : "regular");
712433d6423SLionel Sambuc 
713433d6423SLionel Sambuc           /* Allocate a system service slot for the new version. */
714433d6423SLionel Sambuc           s = alloc_slot(&new_rp);
715433d6423SLionel Sambuc           if(s != OK) {
716433d6423SLionel Sambuc               printf("RS: do_update: unable to allocate a new slot: %d\n", s);
717433d6423SLionel Sambuc               return s;
718433d6423SLionel Sambuc           }
719433d6423SLionel Sambuc 
720433d6423SLionel Sambuc           /* Initialize the slot as requested. */
721433d6423SLionel Sambuc           s = init_slot(new_rp, &rs_start, m_ptr->m_source);
722433d6423SLionel Sambuc           if(s != OK) {
723433d6423SLionel Sambuc               printf("RS: do_update: unable to init the new slot: %d\n", s);
724433d6423SLionel Sambuc               return s;
725433d6423SLionel Sambuc           }
726433d6423SLionel Sambuc 
727433d6423SLionel Sambuc           /* Let the new version inherit defaults from the old one. */
728433d6423SLionel Sambuc           inherit_service_defaults(rp, new_rp);
729433d6423SLionel Sambuc 
730433d6423SLionel Sambuc           /* Link the two versions. */
731433d6423SLionel Sambuc           rp->r_new_rp = new_rp;
732433d6423SLionel Sambuc           new_rp->r_old_rp = rp;
733433d6423SLionel Sambuc 
734433d6423SLionel Sambuc           /* Create new version of the service but don't let it run. */
735433d6423SLionel Sambuc           new_rp->r_priv.s_flags |= LU_SYS_PROC;
736fb6bd596SCristiano Giuffrida           new_rp->r_priv.s_init_flags |= rpupd->init_flags;
737433d6423SLionel Sambuc           s = create_service(new_rp);
738433d6423SLionel Sambuc           if(s != OK) {
739433d6423SLionel Sambuc               printf("RS: do_update: unable to create a new service: %d\n", s);
740433d6423SLionel Sambuc               return s;
741433d6423SLionel Sambuc           }
742433d6423SLionel Sambuc       }
743433d6423SLionel Sambuc 
744fb6bd596SCristiano Giuffrida       /* Set default state endpoint. */
745fb6bd596SCristiano Giuffrida       if(state_endpoint == NONE) {
746fb6bd596SCristiano Giuffrida           state_endpoint = new_rp->r_pub->endpoint;
747fb6bd596SCristiano Giuffrida       }
748433d6423SLionel Sambuc 
749433d6423SLionel Sambuc       /* If RS is updating, set up signal managers for the new instance.
750433d6423SLionel Sambuc        * The current RS instance must be made the backup signal manager to
751433d6423SLionel Sambuc        * support rollback in case of a crash during initialization.
752433d6423SLionel Sambuc        */
753433d6423SLionel Sambuc       if(rp->r_priv.s_flags & ROOT_SYS_PROC) {
754433d6423SLionel Sambuc           s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint);
755433d6423SLionel Sambuc           if(s != OK) {
756433d6423SLionel Sambuc               cleanup_service(new_rp);
757433d6423SLionel Sambuc               return s;
758433d6423SLionel Sambuc           }
759433d6423SLionel Sambuc       }
760433d6423SLionel Sambuc 
761fb6bd596SCristiano Giuffrida       /* Preallocate heap regions if requested. */
762fb6bd596SCristiano Giuffrida       if(rs_start.rss_heap_prealloc_bytes < 0) {
763fb6bd596SCristiano Giuffrida           rs_start.rss_heap_prealloc_bytes = 0;
764433d6423SLionel Sambuc       }
765fb6bd596SCristiano Giuffrida       if(rs_start.rss_heap_prealloc_bytes) {
766fb6bd596SCristiano Giuffrida           size_t len;
767fb6bd596SCristiano Giuffrida           if(rs_verbose)
768fb6bd596SCristiano Giuffrida               printf("RS: %s preallocating %ld heap bytes\n", srv_to_string(new_rp),
769fb6bd596SCristiano Giuffrida                   rs_start.rss_heap_prealloc_bytes);
770fb6bd596SCristiano Giuffrida 
771fb6bd596SCristiano Giuffrida           len = rs_start.rss_heap_prealloc_bytes;
772fb6bd596SCristiano Giuffrida           s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_HEAP_PREALLOC,
773fb6bd596SCristiano Giuffrida               NULL, &len);
774fb6bd596SCristiano Giuffrida           if(s != OK) {
775fb6bd596SCristiano Giuffrida               printf("vm_memctl(VM_RS_MEM_HEAP_PREALLOC) failed: %d\n", s);
776fb6bd596SCristiano Giuffrida               cleanup_service(new_rp);
777fb6bd596SCristiano Giuffrida               return s;
778fb6bd596SCristiano Giuffrida           }
779fb6bd596SCristiano Giuffrida           if(rp->r_priv.s_flags & ROOT_SYS_PROC) {
780fb6bd596SCristiano Giuffrida               vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_PIN, 0, 0);
781fb6bd596SCristiano Giuffrida           }
782433d6423SLionel Sambuc       }
783433d6423SLionel Sambuc 
784fb6bd596SCristiano Giuffrida       /* Preallocate mmapped regions if requested. */
785fb6bd596SCristiano Giuffrida       if(rs_start.rss_map_prealloc_bytes < 0) {
786fb6bd596SCristiano Giuffrida           rs_start.rss_map_prealloc_bytes = 0;
787433d6423SLionel Sambuc       }
788fb6bd596SCristiano Giuffrida       if(rs_start.rss_map_prealloc_bytes) {
789fb6bd596SCristiano Giuffrida           void *addr = NULL;
790fb6bd596SCristiano Giuffrida           if(rs_verbose)
791fb6bd596SCristiano Giuffrida               printf("RS: %s preallocating %ld mmap bytes\n", srv_to_string(new_rp),
792fb6bd596SCristiano Giuffrida                   rs_start.rss_map_prealloc_bytes);
793fb6bd596SCristiano Giuffrida 
794fb6bd596SCristiano Giuffrida           new_rp->r_map_prealloc_len = rs_start.rss_map_prealloc_bytes;
795fb6bd596SCristiano Giuffrida           s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_MAP_PREALLOC,
796fb6bd596SCristiano Giuffrida               &addr, &new_rp->r_map_prealloc_len);
797fb6bd596SCristiano Giuffrida           if(s != OK) {
798fb6bd596SCristiano Giuffrida               printf("vm_memctl(VM_RS_MEM_MAP_PREALLOC) failed: %d\n", s);
799fb6bd596SCristiano Giuffrida               cleanup_service(new_rp);
800fb6bd596SCristiano Giuffrida               return s;
801433d6423SLionel Sambuc           }
802fb6bd596SCristiano Giuffrida           new_rp->r_map_prealloc_addr = (vir_bytes) addr;
803fb6bd596SCristiano Giuffrida       }
804fb6bd596SCristiano Giuffrida   }
805fb6bd596SCristiano Giuffrida 
806fb6bd596SCristiano Giuffrida   /* Process state data. */
807fb6bd596SCristiano Giuffrida   s = init_state_data(m_ptr->m_source, prepare_state, &rs_start.rss_state_data, &rpupd->prepare_state_data);
808fb6bd596SCristiano Giuffrida   if(s != OK) {
809fb6bd596SCristiano Giuffrida       rupdate_upd_clear(rpupd);
810fb6bd596SCristiano Giuffrida       return s;
811fb6bd596SCristiano Giuffrida   }
812fb6bd596SCristiano Giuffrida 
813fb6bd596SCristiano Giuffrida   /* Create update grants. */
814fb6bd596SCristiano Giuffrida   if(rpupd->prepare_state_data.size > 0) {
815fb6bd596SCristiano Giuffrida       struct rs_state_data *state_data = &rpupd->prepare_state_data;
816fb6bd596SCristiano Giuffrida       rpupd->prepare_state_data_gid = cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data,
817fb6bd596SCristiano Giuffrida           state_data->size, CPF_READ);
818fb6bd596SCristiano Giuffrida       if(rpupd->prepare_state_data_gid == GRANT_INVALID) {
819fb6bd596SCristiano Giuffrida           rupdate_upd_clear(rpupd);
820fb6bd596SCristiano Giuffrida           return ENOMEM;
821fb6bd596SCristiano Giuffrida       }
822fb6bd596SCristiano Giuffrida       state_data->ipcf_els_gid = GRANT_INVALID;
823fb6bd596SCristiano Giuffrida       if(state_data->ipcf_els) {
824fb6bd596SCristiano Giuffrida           state_data->ipcf_els_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->ipcf_els,
825fb6bd596SCristiano Giuffrida               state_data->ipcf_els_size, CPF_READ);
826fb6bd596SCristiano Giuffrida           if(state_data->ipcf_els_gid == GRANT_INVALID) {
827fb6bd596SCristiano Giuffrida               rupdate_upd_clear(rpupd);
828fb6bd596SCristiano Giuffrida               return ENOMEM;
829fb6bd596SCristiano Giuffrida           }
830fb6bd596SCristiano Giuffrida       }
831fb6bd596SCristiano Giuffrida       state_data->eval_gid = GRANT_INVALID;
832fb6bd596SCristiano Giuffrida       if(state_data->eval_addr) {
833fb6bd596SCristiano Giuffrida           state_data->eval_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->eval_addr,
834fb6bd596SCristiano Giuffrida               state_data->eval_len, CPF_READ);
835fb6bd596SCristiano Giuffrida           if(state_data->eval_gid == GRANT_INVALID) {
836fb6bd596SCristiano Giuffrida               rupdate_upd_clear(rpupd);
837fb6bd596SCristiano Giuffrida               return ENOMEM;
838fb6bd596SCristiano Giuffrida           }
839fb6bd596SCristiano Giuffrida       }
840fb6bd596SCristiano Giuffrida   }
841fb6bd596SCristiano Giuffrida 
842fb6bd596SCristiano Giuffrida   /* Fill the new update descriptor and add it to the update chain. */
843fb6bd596SCristiano Giuffrida   rpupd->prepare_state = prepare_state;
844fb6bd596SCristiano Giuffrida   rpupd->state_endpoint = state_endpoint;
845*d91f738bSDavid van Moolenbroek   rpupd->prepare_tm = getticks();
846fb6bd596SCristiano Giuffrida   rpupd->prepare_maxtime = prepare_maxtime;
847fb6bd596SCristiano Giuffrida   rupdate_add_upd(rpupd);
848fb6bd596SCristiano Giuffrida 
849fb6bd596SCristiano Giuffrida   if(rs_verbose)
850fb6bd596SCristiano Giuffrida       printf("RS: %s scheduled for %s\n", srv_to_string(rp), srv_upd_to_string(rpupd));
851fb6bd596SCristiano Giuffrida 
852fb6bd596SCristiano Giuffrida   /* If batch mode, reply immediately. More services to update will follow. */
853fb6bd596SCristiano Giuffrida   if(batch_mode) {
854fb6bd596SCristiano Giuffrida       return OK;
855fb6bd596SCristiano Giuffrida   }
856fb6bd596SCristiano Giuffrida 
857fb6bd596SCristiano Giuffrida   /* Start preparing for the update process. */
858fb6bd596SCristiano Giuffrida   s = start_update_prepare(allow_retries);
859fb6bd596SCristiano Giuffrida   if(s == ESRCH) {
860fb6bd596SCristiano Giuffrida       /* No process left in the update chain. We are done already. */
861fb6bd596SCristiano Giuffrida       return OK;
862fb6bd596SCristiano Giuffrida   }
863fb6bd596SCristiano Giuffrida   if(s != OK) {
864fb6bd596SCristiano Giuffrida       return s;
865fb6bd596SCristiano Giuffrida   }
866fb6bd596SCristiano Giuffrida 
867fb6bd596SCristiano Giuffrida   /* Unblock the caller immediately if requested. */
868fb6bd596SCristiano Giuffrida   if(noblock) {
869fb6bd596SCristiano Giuffrida       return OK;
870fb6bd596SCristiano Giuffrida   }
871fb6bd596SCristiano Giuffrida 
872fb6bd596SCristiano Giuffrida   /* Otherwise, send a reply when the new version completes initialization. */
873fb6bd596SCristiano Giuffrida   rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY;
874fb6bd596SCristiano Giuffrida   rupdate.last_rpupd->rp->r_caller = m_ptr->m_source;
875fb6bd596SCristiano Giuffrida   rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE;
876433d6423SLionel Sambuc 
877433d6423SLionel Sambuc   return EDONTREPLY;
878433d6423SLionel Sambuc }
879433d6423SLionel Sambuc 
880433d6423SLionel Sambuc /*===========================================================================*
881433d6423SLionel Sambuc  *				do_upd_ready				     *
882433d6423SLionel Sambuc  *===========================================================================*/
883433d6423SLionel Sambuc int do_upd_ready(message *m_ptr)
884433d6423SLionel Sambuc {
885fb6bd596SCristiano Giuffrida   struct rproc *rp;
886fb6bd596SCristiano Giuffrida   struct rprocupd *prev_rpupd, *rpupd;
887433d6423SLionel Sambuc   int who_p;
888433d6423SLionel Sambuc   int result;
889433d6423SLionel Sambuc   int is_rs;
890fb6bd596SCristiano Giuffrida   int i;
891433d6423SLionel Sambuc 
892433d6423SLionel Sambuc   who_p = _ENDPOINT_P(m_ptr->m_source);
893433d6423SLionel Sambuc   rp = rproc_ptr[who_p];
894433d6423SLionel Sambuc   result = m_ptr->m_rs_update.result;
895433d6423SLionel Sambuc 
896433d6423SLionel Sambuc   /* Make sure the originating service was requested to prepare for update. */
897fb6bd596SCristiano Giuffrida   rpupd = rupdate.curr_rpupd;
898fb6bd596SCristiano Giuffrida   if(!rpupd || rp != rpupd->rp || RUPDATE_IS_INITIALIZING()) {
899433d6423SLionel Sambuc       if(rs_verbose)
900fb6bd596SCristiano Giuffrida           printf("RS: %s sent late/unexpected update ready msg\n",
901fb6bd596SCristiano Giuffrida               srv_to_string(rp));
902433d6423SLionel Sambuc       return EINVAL;
903433d6423SLionel Sambuc   }
904fb6bd596SCristiano Giuffrida   rp->r_flags |= RS_PREPARE_DONE;
905433d6423SLionel Sambuc 
906433d6423SLionel Sambuc   /* Check if something went wrong and the service failed to prepare
907433d6423SLionel Sambuc    * for the update. In that case, end the update process. The old version will
908433d6423SLionel Sambuc    * be replied to and continue executing.
909433d6423SLionel Sambuc    */
910433d6423SLionel Sambuc   if(result != OK) {
911fb6bd596SCristiano Giuffrida       printf("RS: update failed: %s\n", lu_strerror(result));
912433d6423SLionel Sambuc       end_update(result, RS_REPLY);
913433d6423SLionel Sambuc 
914433d6423SLionel Sambuc       return EDONTREPLY;
915433d6423SLionel Sambuc   }
916433d6423SLionel Sambuc 
917fb6bd596SCristiano Giuffrida   if(rs_verbose)
918fb6bd596SCristiano Giuffrida       printf("RS: %s ready to update\n", srv_to_string(rp));
919fb6bd596SCristiano Giuffrida 
920fb6bd596SCristiano Giuffrida   /* If this is a multi-component update and this is not the last service
921fb6bd596SCristiano Giuffrida    * in the update, request the next process to update.
922fb6bd596SCristiano Giuffrida    */
923fb6bd596SCristiano Giuffrida   if(start_update_prepare_next() != NULL) {
924433d6423SLionel Sambuc       return EDONTREPLY;
925433d6423SLionel Sambuc   }
926433d6423SLionel Sambuc 
927fb6bd596SCristiano Giuffrida   /* Now perform the update and request each new instance to initialize. */
928fb6bd596SCristiano Giuffrida   start_update();
929fb6bd596SCristiano Giuffrida 
930433d6423SLionel Sambuc   return EDONTREPLY;
931433d6423SLionel Sambuc }
932433d6423SLionel Sambuc 
933433d6423SLionel Sambuc /*===========================================================================*
934433d6423SLionel Sambuc  *				do_period				     *
935433d6423SLionel Sambuc  *===========================================================================*/
936433d6423SLionel Sambuc void do_period(m_ptr)
937433d6423SLionel Sambuc message *m_ptr;
938433d6423SLionel Sambuc {
939433d6423SLionel Sambuc   register struct rproc *rp;
940433d6423SLionel Sambuc   register struct rprocpub *rpub;
941433d6423SLionel Sambuc   clock_t now = m_ptr->m_notify.timestamp;
942433d6423SLionel Sambuc   int s;
943433d6423SLionel Sambuc   long period;
944433d6423SLionel Sambuc 
945433d6423SLionel Sambuc   /* If an update is in progress, check its status. */
946fb6bd596SCristiano Giuffrida   if(RUPDATE_IS_UPDATING() && !RUPDATE_IS_INITIALIZING()) {
947433d6423SLionel Sambuc       update_period(m_ptr);
948433d6423SLionel Sambuc   }
949433d6423SLionel Sambuc 
950433d6423SLionel Sambuc   /* Search system services table. Only check slots that are in use and not
951433d6423SLionel Sambuc    * updating.
952433d6423SLionel Sambuc    */
953433d6423SLionel Sambuc   for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
954433d6423SLionel Sambuc       rpub = rp->r_pub;
955fb6bd596SCristiano Giuffrida 
956fb6bd596SCristiano Giuffrida       if ((rp->r_flags & RS_ACTIVE) && (!SRV_IS_UPDATING(rp) || ((rp->r_flags & (RS_INITIALIZING|RS_INIT_DONE|RS_INIT_PENDING)) == RS_INITIALIZING))) {
957433d6423SLionel Sambuc 
958433d6423SLionel Sambuc           /* Compute period. */
959433d6423SLionel Sambuc           period = rp->r_period;
960433d6423SLionel Sambuc           if(rp->r_flags & RS_INITIALIZING) {
961fb6bd596SCristiano Giuffrida               period = SRV_IS_UPDATING(rp) ? UPD_INIT_MAXTIME(&rp->r_upd) : RS_INIT_T;
962433d6423SLionel Sambuc           }
963433d6423SLionel Sambuc 
964433d6423SLionel Sambuc           /* If the service is to be revived (because it repeatedly exited,
965433d6423SLionel Sambuc 	   * and was not directly restarted), the binary backoff field is
966433d6423SLionel Sambuc 	   * greater than zero.
967433d6423SLionel Sambuc 	   */
968433d6423SLionel Sambuc 	  if (rp->r_backoff > 0) {
969433d6423SLionel Sambuc               rp->r_backoff -= 1;
970433d6423SLionel Sambuc 	      if (rp->r_backoff == 0) {
971433d6423SLionel Sambuc 		  restart_service(rp);
972433d6423SLionel Sambuc 	      }
973433d6423SLionel Sambuc 	  }
974433d6423SLionel Sambuc 
975433d6423SLionel Sambuc 	  /* If the service was signaled with a SIGTERM and fails to respond,
976433d6423SLionel Sambuc 	   * kill the system service with a SIGKILL signal.
977433d6423SLionel Sambuc 	   */
978433d6423SLionel Sambuc 	  else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
979433d6423SLionel Sambuc 	   && rp->r_pid > 0) {
980433d6423SLionel Sambuc               rp->r_stop_tm = 0;
981433d6423SLionel Sambuc               crash_service(rp); /* simulate crash */
982433d6423SLionel Sambuc 	  }
983433d6423SLionel Sambuc 
984433d6423SLionel Sambuc 	  /* There seems to be no special conditions. If the service has a
985433d6423SLionel Sambuc 	   * period assigned check its status.
986433d6423SLionel Sambuc 	   */
987433d6423SLionel Sambuc 	  else if (period > 0) {
988433d6423SLionel Sambuc 
989433d6423SLionel Sambuc 	      /* Check if an answer to a status request is still pending. If
990433d6423SLionel Sambuc 	       * the service didn't respond within time, kill it to simulate
991433d6423SLionel Sambuc 	       * a crash. The failure will be detected and the service will
992433d6423SLionel Sambuc 	       * be restarted automatically. Give the service a free pass if
993433d6423SLionel Sambuc 	       * somebody is initializing. There may be some weird dependencies
994433d6423SLionel Sambuc 	       * if another service is, for example, restarting at the same
995433d6423SLionel Sambuc 	       * time.
996433d6423SLionel Sambuc 	       */
997433d6423SLionel Sambuc               if (rp->r_alive_tm < rp->r_check_tm) {
998433d6423SLionel Sambuc 	          if (now - rp->r_alive_tm > 2*period &&
999433d6423SLionel Sambuc 		      rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) {
1000fb6bd596SCristiano Giuffrida 		      struct rproc *rp2;
1001fb6bd596SCristiano Giuffrida 		      int init_flag;
1002433d6423SLionel Sambuc 		      if(rs_verbose)
1003433d6423SLionel Sambuc                            printf("RS: %s reported late\n", srv_to_string(rp));
1004fb6bd596SCristiano Giuffrida                       init_flag = rp->r_flags & RS_INITIALIZING;
1005fb6bd596SCristiano Giuffrida                       rp->r_flags &= ~RS_INITIALIZING;
1006fb6bd596SCristiano Giuffrida                       rp2 = lookup_slot_by_flags(RS_INITIALIZING);
1007fb6bd596SCristiano Giuffrida                       rp->r_flags |= init_flag;
1008fb6bd596SCristiano Giuffrida 		      if(rp2 != NULL && !SRV_IS_UPDATING(rp)) {
1009433d6423SLionel Sambuc                            /* Skip for now. */
1010433d6423SLionel Sambuc                            if(rs_verbose)
1011433d6423SLionel Sambuc                                printf("RS: %s gets a free pass\n",
1012433d6423SLionel Sambuc                                    srv_to_string(rp));
1013433d6423SLionel Sambuc                            rp->r_alive_tm = now;
1014433d6423SLionel Sambuc                            rp->r_check_tm = now+1;
1015433d6423SLionel Sambuc                            continue;
1016433d6423SLionel Sambuc 		      }
1017433d6423SLionel Sambuc 		      rp->r_flags |= RS_NOPINGREPLY;
1018433d6423SLionel Sambuc                       crash_service(rp); /* simulate crash */
1019fb6bd596SCristiano Giuffrida                       if(rp->r_flags & RS_INITIALIZING) {
1020fb6bd596SCristiano Giuffrida                           rp->r_init_err = EINTR;
1021fb6bd596SCristiano Giuffrida                       }
1022433d6423SLionel Sambuc 		  }
1023433d6423SLionel Sambuc 	      }
1024433d6423SLionel Sambuc 
1025433d6423SLionel Sambuc 	      /* No answer pending. Check if a period expired since the last
1026433d6423SLionel Sambuc 	       * check and, if so request the system service's status.
1027433d6423SLionel Sambuc 	       */
1028433d6423SLionel Sambuc 	      else if (now - rp->r_check_tm > rp->r_period) {
1029433d6423SLionel Sambuc   		  ipc_notify(rpub->endpoint);		/* request status */
1030433d6423SLionel Sambuc 		  rp->r_check_tm = now;			/* mark time */
1031433d6423SLionel Sambuc               }
1032433d6423SLionel Sambuc           }
1033433d6423SLionel Sambuc       }
1034433d6423SLionel Sambuc   }
1035433d6423SLionel Sambuc 
1036433d6423SLionel Sambuc   /* Reschedule a synchronous alarm for the next period. */
1037433d6423SLionel Sambuc   if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
1038433d6423SLionel Sambuc       panic("couldn't set alarm: %d", s);
1039433d6423SLionel Sambuc }
1040433d6423SLionel Sambuc 
1041433d6423SLionel Sambuc /*===========================================================================*
1042433d6423SLionel Sambuc  *			          do_sigchld				     *
1043433d6423SLionel Sambuc  *===========================================================================*/
1044433d6423SLionel Sambuc void do_sigchld()
1045433d6423SLionel Sambuc {
1046433d6423SLionel Sambuc /* PM informed us that there are dead children to cleanup. Go get them. */
1047433d6423SLionel Sambuc   pid_t pid;
1048433d6423SLionel Sambuc   int status;
1049433d6423SLionel Sambuc   struct rproc *rp;
1050433d6423SLionel Sambuc   struct rproc **rps;
1051fb6bd596SCristiano Giuffrida   int i, nr_rps, found;
1052433d6423SLionel Sambuc 
1053433d6423SLionel Sambuc   if(rs_verbose)
1054433d6423SLionel Sambuc      printf("RS: got SIGCHLD signal, cleaning up dead children\n");
1055433d6423SLionel Sambuc 
1056433d6423SLionel Sambuc   while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) {
1057433d6423SLionel Sambuc       rp = lookup_slot_by_pid(pid);
1058433d6423SLionel Sambuc       if(rp != NULL) {
1059433d6423SLionel Sambuc 
1060433d6423SLionel Sambuc           if(rs_verbose)
1061433d6423SLionel Sambuc               printf("RS: %s exited via another signal manager\n",
1062433d6423SLionel Sambuc                   srv_to_string(rp));
1063433d6423SLionel Sambuc 
1064433d6423SLionel Sambuc           /* The slot is still there. This means RS is not the signal
1065433d6423SLionel Sambuc            * manager assigned to the process. Ignore the event but
1066433d6423SLionel Sambuc            * free slots for all the service instances and send a late
1067433d6423SLionel Sambuc            * reply if necessary.
1068433d6423SLionel Sambuc            */
1069fb6bd596SCristiano Giuffrida           found = 0;
1070433d6423SLionel Sambuc           get_service_instances(rp, &rps, &nr_rps);
1071433d6423SLionel Sambuc           for(i=0;i<nr_rps;i++) {
1072fb6bd596SCristiano Giuffrida               if(SRV_IS_UPDATING(rps[i])) {
1073fb6bd596SCristiano Giuffrida                   rps[i]->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING);
1074fb6bd596SCristiano Giuffrida                   found = 1;
1075433d6423SLionel Sambuc               }
1076433d6423SLionel Sambuc               free_slot(rps[i]);
1077433d6423SLionel Sambuc           }
1078fb6bd596SCristiano Giuffrida           if(found) {
1079fb6bd596SCristiano Giuffrida               rupdate_clear_upds();
1080fb6bd596SCristiano Giuffrida           }
1081433d6423SLionel Sambuc       }
1082433d6423SLionel Sambuc   }
1083433d6423SLionel Sambuc }
1084433d6423SLionel Sambuc 
1085433d6423SLionel Sambuc /*===========================================================================*
1086433d6423SLionel Sambuc  *				do_getsysinfo				     *
1087433d6423SLionel Sambuc  *===========================================================================*/
1088433d6423SLionel Sambuc int do_getsysinfo(m_ptr)
1089433d6423SLionel Sambuc message *m_ptr;
1090433d6423SLionel Sambuc {
1091433d6423SLionel Sambuc   vir_bytes src_addr, dst_addr;
1092433d6423SLionel Sambuc   int dst_proc;
10930eabb93cSDavid van Moolenbroek   size_t size, len;
1094433d6423SLionel Sambuc   int s;
1095433d6423SLionel Sambuc 
1096433d6423SLionel Sambuc   /* Check if the call can be allowed. */
1097433d6423SLionel Sambuc   if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK)
1098433d6423SLionel Sambuc       return s;
1099433d6423SLionel Sambuc 
11000eabb93cSDavid van Moolenbroek   dst_proc = m_ptr->m_source;
11010eabb93cSDavid van Moolenbroek   dst_addr = m_ptr->m_lsys_getsysinfo.where;
11020eabb93cSDavid van Moolenbroek   size = m_ptr->m_lsys_getsysinfo.size;
11030eabb93cSDavid van Moolenbroek 
1104433d6423SLionel Sambuc   switch(m_ptr->m_lsys_getsysinfo.what) {
1105433d6423SLionel Sambuc   case SI_PROC_TAB:
1106433d6423SLionel Sambuc   	src_addr = (vir_bytes) rproc;
1107433d6423SLionel Sambuc   	len = sizeof(struct rproc) * NR_SYS_PROCS;
1108433d6423SLionel Sambuc   	break;
11090eabb93cSDavid van Moolenbroek   case SI_PROCALL_TAB:
11100eabb93cSDavid van Moolenbroek 	/* Copy out both tables, one after the other. */
11110eabb93cSDavid van Moolenbroek 	src_addr = (vir_bytes) rproc;
11120eabb93cSDavid van Moolenbroek 	len = sizeof(struct rproc) * NR_SYS_PROCS;
11130eabb93cSDavid van Moolenbroek 	if (len > size)
11140eabb93cSDavid van Moolenbroek 		return EINVAL;
11150eabb93cSDavid van Moolenbroek 	if ((s = sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)) != OK)
11160eabb93cSDavid van Moolenbroek 		return s;
11170eabb93cSDavid van Moolenbroek 	dst_addr += len;
11180eabb93cSDavid van Moolenbroek 	size -= len;
11190eabb93cSDavid van Moolenbroek 	/* FALLTHROUGH */
1120433d6423SLionel Sambuc   case SI_PROCPUB_TAB:
1121433d6423SLionel Sambuc   	src_addr = (vir_bytes) rprocpub;
1122433d6423SLionel Sambuc   	len = sizeof(struct rprocpub) * NR_SYS_PROCS;
1123433d6423SLionel Sambuc   	break;
1124433d6423SLionel Sambuc   default:
1125433d6423SLionel Sambuc   	return(EINVAL);
1126433d6423SLionel Sambuc   }
1127433d6423SLionel Sambuc 
11280eabb93cSDavid van Moolenbroek   if (len != size)
1129433d6423SLionel Sambuc 	return(EINVAL);
1130433d6423SLionel Sambuc 
1131433d6423SLionel Sambuc   return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len);
1132433d6423SLionel Sambuc }
1133433d6423SLionel Sambuc 
1134433d6423SLionel Sambuc /*===========================================================================*
1135433d6423SLionel Sambuc  *				do_lookup				     *
1136433d6423SLionel Sambuc  *===========================================================================*/
1137433d6423SLionel Sambuc int do_lookup(m_ptr)
1138433d6423SLionel Sambuc message *m_ptr;
1139433d6423SLionel Sambuc {
1140433d6423SLionel Sambuc 	static char namebuf[100];
1141433d6423SLionel Sambuc 	int len, r;
1142433d6423SLionel Sambuc 	struct rproc *rrp;
1143433d6423SLionel Sambuc 	struct rprocpub *rrpub;
1144433d6423SLionel Sambuc 
1145433d6423SLionel Sambuc 	len = m_ptr->m_rs_req.name_len;
1146433d6423SLionel Sambuc 
1147433d6423SLionel Sambuc 	if(len < 2 || len >= sizeof(namebuf)) {
1148433d6423SLionel Sambuc 		printf("RS: len too weird (%d)\n", len);
1149433d6423SLionel Sambuc 		return EINVAL;
1150433d6423SLionel Sambuc 	}
1151433d6423SLionel Sambuc 
1152433d6423SLionel Sambuc 	if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name,
1153433d6423SLionel Sambuc 		SELF, (vir_bytes) namebuf, len)) != OK) {
1154433d6423SLionel Sambuc 		printf("RS: name copy failed\n");
1155433d6423SLionel Sambuc 		return r;
1156433d6423SLionel Sambuc 
1157433d6423SLionel Sambuc 	}
1158433d6423SLionel Sambuc 
1159433d6423SLionel Sambuc 	namebuf[len] = '\0';
1160433d6423SLionel Sambuc 
1161433d6423SLionel Sambuc 	rrp = lookup_slot_by_label(namebuf);
1162433d6423SLionel Sambuc 	if(!rrp) {
1163433d6423SLionel Sambuc 		return ESRCH;
1164433d6423SLionel Sambuc 	}
1165433d6423SLionel Sambuc 	rrpub = rrp->r_pub;
1166433d6423SLionel Sambuc 	m_ptr->m_rs_req.endpoint = rrpub->endpoint;
1167433d6423SLionel Sambuc 
1168433d6423SLionel Sambuc 	return OK;
1169433d6423SLionel Sambuc }
1170433d6423SLionel Sambuc 
1171433d6423SLionel Sambuc /*===========================================================================*
1172fb6bd596SCristiano Giuffrida  *				do_sysctl				     *
1173fb6bd596SCristiano Giuffrida  *===========================================================================*/
1174fb6bd596SCristiano Giuffrida int do_sysctl(message *m_ptr)
1175fb6bd596SCristiano Giuffrida {
1176fb6bd596SCristiano Giuffrida 	int request_type = m_ptr->m_rs_req.subtype;
1177fb6bd596SCristiano Giuffrida 	int r, allow_retries = 1;
1178fb6bd596SCristiano Giuffrida 	switch(request_type) {
1179fb6bd596SCristiano Giuffrida 		case RS_SYSCTL_SRV_STATUS:
1180fb6bd596SCristiano Giuffrida 			print_services_status();
1181fb6bd596SCristiano Giuffrida 		break;
1182fb6bd596SCristiano Giuffrida 		case RS_SYSCTL_UPD_START:
1183fb6bd596SCristiano Giuffrida 		case RS_SYSCTL_UPD_RUN:
1184fb6bd596SCristiano Giuffrida 			r = start_update_prepare(allow_retries);
1185fb6bd596SCristiano Giuffrida 			print_update_status();
1186fb6bd596SCristiano Giuffrida 			if(r != OK) {
1187fb6bd596SCristiano Giuffrida 			    if(r == ESRCH) {
1188fb6bd596SCristiano Giuffrida 			        /* We are done already. */
1189fb6bd596SCristiano Giuffrida 			         r = OK;
1190fb6bd596SCristiano Giuffrida 			    }
1191fb6bd596SCristiano Giuffrida 			    return r;
1192fb6bd596SCristiano Giuffrida 			}
1193fb6bd596SCristiano Giuffrida 			if(request_type == RS_SYSCTL_UPD_START) {
1194fb6bd596SCristiano Giuffrida 			    return OK;
1195fb6bd596SCristiano Giuffrida 			}
1196fb6bd596SCristiano Giuffrida                         /* Send a reply when done. */
1197fb6bd596SCristiano Giuffrida                         rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY;
1198fb6bd596SCristiano Giuffrida                         rupdate.last_rpupd->rp->r_caller = m_ptr->m_source;
1199fb6bd596SCristiano Giuffrida                         rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE;
1200fb6bd596SCristiano Giuffrida 			return EDONTREPLY;
1201fb6bd596SCristiano Giuffrida 		break;
1202fb6bd596SCristiano Giuffrida 		case RS_SYSCTL_UPD_STOP:
1203fb6bd596SCristiano Giuffrida 			r = abort_update_proc(EINTR);
1204fb6bd596SCristiano Giuffrida 			print_update_status();
1205fb6bd596SCristiano Giuffrida 			return r;
1206fb6bd596SCristiano Giuffrida 		break;
1207fb6bd596SCristiano Giuffrida 		case RS_SYSCTL_UPD_STATUS:
1208fb6bd596SCristiano Giuffrida 			print_update_status();
1209fb6bd596SCristiano Giuffrida 		break;
1210fb6bd596SCristiano Giuffrida 		default:
1211fb6bd596SCristiano Giuffrida 			printf("RS: bad sysctl type\n");
1212fb6bd596SCristiano Giuffrida 			return EINVAL;
1213fb6bd596SCristiano Giuffrida 		break;
1214fb6bd596SCristiano Giuffrida 	}
1215fb6bd596SCristiano Giuffrida 
1216fb6bd596SCristiano Giuffrida 	return OK;
1217fb6bd596SCristiano Giuffrida }
1218fb6bd596SCristiano Giuffrida 
1219fb6bd596SCristiano Giuffrida /*===========================================================================*
12203837bb5cSCristiano Giuffrida  *				do_fi				     *
12213837bb5cSCristiano Giuffrida  *===========================================================================*/
12223837bb5cSCristiano Giuffrida int do_fi(message *m_ptr)
12233837bb5cSCristiano Giuffrida {
12243837bb5cSCristiano Giuffrida   struct rproc *rp;
12253837bb5cSCristiano Giuffrida   struct rprocpub *rpub;
12263837bb5cSCristiano Giuffrida   int s, r;
12273837bb5cSCristiano Giuffrida   char label[RS_MAX_LABEL_LEN];
12283837bb5cSCristiano Giuffrida 
12293837bb5cSCristiano Giuffrida   /* Copy label. */
12303837bb5cSCristiano Giuffrida   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
12313837bb5cSCristiano Giuffrida       m_ptr->m_rs_req.len, label, sizeof(label));
12323837bb5cSCristiano Giuffrida   if(s != OK) {
12333837bb5cSCristiano Giuffrida       return s;
12343837bb5cSCristiano Giuffrida   }
12353837bb5cSCristiano Giuffrida 
12363837bb5cSCristiano Giuffrida   /* Lookup slot by label. */
12373837bb5cSCristiano Giuffrida   rp = lookup_slot_by_label(label);
12383837bb5cSCristiano Giuffrida   if(!rp) {
12393837bb5cSCristiano Giuffrida       if(rs_verbose)
12403837bb5cSCristiano Giuffrida           printf("RS: do_fi: service '%s' not found\n", label);
12413837bb5cSCristiano Giuffrida       return(ESRCH);
12423837bb5cSCristiano Giuffrida   }
12433837bb5cSCristiano Giuffrida   rpub = rp->r_pub;
12443837bb5cSCristiano Giuffrida 
12453837bb5cSCristiano Giuffrida   /* Check if the call can be allowed. */
12463837bb5cSCristiano Giuffrida   if((r = check_call_permission(m_ptr->m_source, RS_FI, rp)) != OK)
12473837bb5cSCristiano Giuffrida       return r;
12483837bb5cSCristiano Giuffrida 
12493837bb5cSCristiano Giuffrida   /* Inject fault into the service as requested. */
12503837bb5cSCristiano Giuffrida   s = fi_service(rp);
12513837bb5cSCristiano Giuffrida 
12523837bb5cSCristiano Giuffrida   return s;
12533837bb5cSCristiano Giuffrida }
12543837bb5cSCristiano Giuffrida 
12553837bb5cSCristiano Giuffrida /*===========================================================================*
1256433d6423SLionel Sambuc  *				   check_request			     *
1257433d6423SLionel Sambuc  *===========================================================================*/
1258433d6423SLionel Sambuc static int check_request(struct rs_start *rs_start)
1259433d6423SLionel Sambuc {
1260433d6423SLionel Sambuc   /* Verify scheduling parameters */
1261433d6423SLionel Sambuc   if (rs_start->rss_scheduler != KERNEL &&
1262433d6423SLionel Sambuc 	(rs_start->rss_scheduler < 0 ||
1263433d6423SLionel Sambuc 	rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) {
1264433d6423SLionel Sambuc 	printf("RS: check_request: invalid scheduler %d\n",
1265433d6423SLionel Sambuc 		rs_start->rss_scheduler);
1266433d6423SLionel Sambuc 	return EINVAL;
1267433d6423SLionel Sambuc   }
1268433d6423SLionel Sambuc   if (rs_start->rss_priority >= NR_SCHED_QUEUES) {
1269433d6423SLionel Sambuc 	printf("RS: check_request: priority %u out of range\n",
1270433d6423SLionel Sambuc 		rs_start->rss_priority);
1271433d6423SLionel Sambuc 	return EINVAL;
1272433d6423SLionel Sambuc   }
1273433d6423SLionel Sambuc   if (rs_start->rss_quantum <= 0) {
1274433d6423SLionel Sambuc 	printf("RS: check_request: quantum %u out of range\n",
1275433d6423SLionel Sambuc 		rs_start->rss_quantum);
1276433d6423SLionel Sambuc 	return EINVAL;
1277433d6423SLionel Sambuc   }
1278433d6423SLionel Sambuc 
1279433d6423SLionel Sambuc   if (rs_start->rss_cpu == RS_CPU_BSP)
1280433d6423SLionel Sambuc 	  rs_start->rss_cpu = machine.bsp_id;
1281433d6423SLionel Sambuc   else if (rs_start->rss_cpu == RS_CPU_DEFAULT) {
1282433d6423SLionel Sambuc 	  /* keep the default value */
1283433d6423SLionel Sambuc   } else if (rs_start->rss_cpu < 0)
1284433d6423SLionel Sambuc 	  return EINVAL;
1285433d6423SLionel Sambuc   else if (rs_start->rss_cpu > machine.processors_count) {
1286433d6423SLionel Sambuc 	  printf("RS: cpu number %d out of range 0-%d, using BSP\n",
1287433d6423SLionel Sambuc 			  rs_start->rss_cpu, machine.processors_count);
1288433d6423SLionel Sambuc 	  rs_start->rss_cpu = machine.bsp_id;
1289433d6423SLionel Sambuc   }
1290433d6423SLionel Sambuc 
1291433d6423SLionel Sambuc   /* Verify signal manager. */
1292433d6423SLionel Sambuc   if (rs_start->rss_sigmgr != SELF &&
1293433d6423SLionel Sambuc 	(rs_start->rss_sigmgr < 0 ||
1294433d6423SLionel Sambuc 	rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) {
1295433d6423SLionel Sambuc 	printf("RS: check_request: invalid signal manager %d\n",
1296433d6423SLionel Sambuc 		rs_start->rss_sigmgr);
1297433d6423SLionel Sambuc 	return EINVAL;
1298433d6423SLionel Sambuc   }
1299433d6423SLionel Sambuc 
1300433d6423SLionel Sambuc   return OK;
1301433d6423SLionel Sambuc }
1302433d6423SLionel Sambuc 
1303