xref: /minix3/minix/servers/rs/request.c (revision 85723df033e1d687d5a1c1504bdc35063a74cc78)
1 /*
2  * Changes:
3  *   Jan 22, 2010:  Created  (Cristiano Giuffrida)
4  */
5 
6 #include "inc.h"
7 
8 #include "kernel/proc.h"
9 
10 static int check_request(struct rs_start *rs_start);
11 
12 /*===========================================================================*
13  *				   do_up				     *
14  *===========================================================================*/
15 int do_up(m_ptr)
16 message *m_ptr;					/* request message pointer */
17 {
18 /* A request was made to start a new system service. */
19   struct rproc *rp;
20   struct rprocpub *rpub;
21   int i, r;
22   struct rs_start rs_start;
23   int noblock;
24   int init_flags = 0;
25 
26   /* Check if the call can be allowed. */
27   if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK)
28       return r;
29 
30   /* Allocate a new system service slot. */
31   r = alloc_slot(&rp);
32   if(r != OK) {
33       printf("RS: do_up: unable to allocate a new slot: %d\n", r);
34       return r;
35   }
36   rpub = rp->r_pub;
37 
38   /* Copy the request structure. */
39   r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
40   if (r != OK) {
41       return r;
42   }
43   r = check_request(&rs_start);
44   if (r != OK) {
45       return r;
46   }
47 
48   /* Check flags. */
49   noblock = (rs_start.rss_flags & RSS_NOBLOCK);
50   if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) {
51       init_flags |= SEF_INIT_CRASH;
52   }
53   if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) {
54       init_flags |= SEF_INIT_FAIL;
55   }
56   if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) {
57       init_flags |= SEF_INIT_TIMEOUT;
58   }
59   if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) {
60       init_flags |= SEF_INIT_DEFCB;
61   }
62 
63   /* Initialize the slot as requested. */
64   r = init_slot(rp, &rs_start, m_ptr->m_source);
65   if(r != OK) {
66       printf("RS: do_up: unable to init the new slot: %d\n", r);
67       return r;
68   }
69 
70   /* Check for duplicates */
71   if(lookup_slot_by_label(rpub->label)) {
72       printf("RS: service with the same label '%s' already exists\n",
73           rpub->label);
74       return EBUSY;
75   }
76   if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) {
77       printf("RS: service with the same device number %d already exists\n",
78           rpub->dev_nr);
79       return EBUSY;
80   }
81   for (i = 0; i < rpub->nr_domain; i++) {
82       if (lookup_slot_by_domain(rpub->domain[i]) != NULL) {
83 	  printf("RS: service with the same domain %d already exists\n",
84 	      rpub->domain[i]);
85 	  return EBUSY;
86       }
87   }
88 
89   /* All information was gathered. Now try to start the system service. */
90   r = start_service(rp, init_flags);
91   if(r != OK) {
92       return r;
93   }
94 
95   /* Unblock the caller immediately if requested. */
96   if(noblock) {
97       return OK;
98   }
99 
100   /* Late reply - send a reply when service completes initialization. */
101   rp->r_flags |= RS_LATEREPLY;
102   rp->r_caller = m_ptr->m_source;
103   rp->r_caller_request = RS_UP;
104 
105   return EDONTREPLY;
106 }
107 
108 /*===========================================================================*
109  *				do_down					     *
110  *===========================================================================*/
111 int do_down(message *m_ptr)
112 {
113   register struct rproc *rp;
114   int s;
115   char label[RS_MAX_LABEL_LEN];
116 
117   /* Copy label. */
118   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
119       m_ptr->m_rs_req.len, label, sizeof(label));
120   if(s != OK) {
121       return s;
122   }
123 
124   /* Lookup slot by label. */
125   rp = lookup_slot_by_label(label);
126   if(!rp) {
127       if(rs_verbose)
128           printf("RS: do_down: service '%s' not found\n", label);
129       return(ESRCH);
130   }
131 
132   /* Check if the call can be allowed. */
133   if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK)
134       return s;
135 
136   /* Stop service. */
137   if (rp->r_flags & RS_TERMINATED) {
138         /* A recovery script is requesting us to bring down the service.
139          * The service is already gone, simply perform cleanup.
140          */
141         if(rs_verbose)
142             printf("RS: recovery script performs service down...\n");
143   	unpublish_service(rp);
144   	cleanup_service(rp);
145     	return(OK);
146   }
147   stop_service(rp,RS_EXITING);
148 
149   /* Late reply - send a reply when service dies. */
150   rp->r_flags |= RS_LATEREPLY;
151   rp->r_caller = m_ptr->m_source;
152   rp->r_caller_request = RS_DOWN;
153 
154   return EDONTREPLY;
155 }
156 
157 /*===========================================================================*
158  *				do_restart				     *
159  *===========================================================================*/
160 int do_restart(message *m_ptr)
161 {
162   struct rproc *rp;
163   int s, r;
164   char label[RS_MAX_LABEL_LEN];
165   char script[MAX_SCRIPT_LEN];
166 
167   /* Copy label. */
168   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
169       m_ptr->m_rs_req.len, label, sizeof(label));
170   if(s != OK) {
171       return s;
172   }
173 
174   /* Lookup slot by label. */
175   rp = lookup_slot_by_label(label);
176   if(!rp) {
177       if(rs_verbose)
178           printf("RS: do_restart: service '%s' not found\n", label);
179       return(ESRCH);
180   }
181 
182   /* Check if the call can be allowed. */
183   if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK)
184       return r;
185 
186   /* We can only be asked to restart a service from a recovery script. */
187   if (! (rp->r_flags & RS_TERMINATED) ) {
188       if(rs_verbose)
189           printf("RS: %s is still running\n", srv_to_string(rp));
190       return EBUSY;
191   }
192 
193   if(rs_verbose)
194       printf("RS: recovery script performs service restart...\n");
195 
196   /* Restart the service, but make sure we don't call the script again. */
197   strcpy(script, rp->r_script);
198   rp->r_script[0] = '\0';
199   restart_service(rp);
200   strcpy(rp->r_script, script);
201 
202   return OK;
203 }
204 
205 /*===========================================================================*
206  *				do_clone				     *
207  *===========================================================================*/
208 int do_clone(message *m_ptr)
209 {
210   struct rproc *rp;
211   struct rprocpub *rpub;
212   int s, r;
213   char label[RS_MAX_LABEL_LEN];
214 
215   /* Copy label. */
216   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
217       m_ptr->m_rs_req.len, label, sizeof(label));
218   if(s != OK) {
219       return s;
220   }
221 
222   /* Lookup slot by label. */
223   rp = lookup_slot_by_label(label);
224   if(!rp) {
225       if(rs_verbose)
226           printf("RS: do_clone: service '%s' not found\n", label);
227       return(ESRCH);
228   }
229   rpub = rp->r_pub;
230 
231   /* Check if the call can be allowed. */
232   if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK)
233       return r;
234 
235   /* Don't clone if a replica is already available. */
236   if(rp->r_next_rp) {
237       return EEXIST;
238   }
239 
240   /* Clone the service as requested. */
241   rpub->sys_flags |= SF_USE_REPL;
242   if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) {
243       rpub->sys_flags &= ~SF_USE_REPL;
244       return r;
245   }
246 
247   return OK;
248 }
249 
250 /*===========================================================================*
251  *				do_unclone				     *
252  *===========================================================================*/
253 int do_unclone(message *m_ptr)
254 {
255   struct rproc *rp;
256   struct rprocpub *rpub;
257   int s, r;
258   char label[RS_MAX_LABEL_LEN];
259 
260   /* Copy label. */
261   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
262       m_ptr->m_rs_req.len, label, sizeof(label));
263   if(s != OK) {
264       return s;
265   }
266 
267   /* Lookup slot by label. */
268   rp = lookup_slot_by_label(label);
269   if(!rp) {
270       if(rs_verbose)
271           printf("RS: do_unclone: service '%s' not found\n", label);
272       return(ESRCH);
273   }
274   rpub = rp->r_pub;
275 
276   /* Check if the call can be allowed. */
277   if((r = check_call_permission(m_ptr->m_source, RS_UNCLONE, rp)) != OK)
278       return r;
279 
280   /* Don't unclone if no replica is available. */
281   if(!(rpub->sys_flags & SF_USE_REPL)) {
282       return ENOENT;
283   }
284 
285   /* Unclone the service as requested. */
286   rpub->sys_flags &= ~SF_USE_REPL;
287   if(rp->r_next_rp) {
288       cleanup_service_now(rp->r_next_rp);
289       rp->r_next_rp = NULL;
290   }
291 
292   return OK;
293 }
294 
295 /*===========================================================================*
296  *				    do_edit				     *
297  *===========================================================================*/
298 int do_edit(message *m_ptr)
299 {
300   struct rproc *rp;
301   struct rprocpub *rpub;
302   struct rs_start rs_start;
303   int r;
304   char label[RS_MAX_LABEL_LEN];
305 
306   /* Copy the request structure. */
307   r = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
308   if (r != OK) {
309       return r;
310   }
311 
312   /* Copy label. */
313   r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
314       rs_start.rss_label.l_len, label, sizeof(label));
315   if(r != OK) {
316       return r;
317   }
318 
319   /* Lookup slot by label. */
320   rp = lookup_slot_by_label(label);
321   if(!rp) {
322       if(rs_verbose)
323           printf("RS: do_edit: service '%s' not found\n", label);
324       return ESRCH;
325   }
326   rpub = rp->r_pub;
327 
328   /* Check if the call can be allowed. */
329   if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK)
330       return r;
331 
332   if(rs_verbose)
333       printf("RS: %s edits settings\n", srv_to_string(rp));
334 
335   /* Synch the privilege structure with the kernel. */
336   if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) {
337       printf("RS: do_edit: unable to synch privilege structure: %d\n", r);
338       return r;
339   }
340 
341   /* Tell scheduler this process is finished */
342   if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) {
343       printf("RS: do_edit: scheduler won't give up process: %d\n", r);
344       return r;
345   }
346 
347   /* Edit the slot as requested. */
348   if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) {
349       printf("RS: do_edit: unable to edit the existing slot: %d\n", r);
350       return r;
351   }
352 
353   /* Update privilege structure. */
354   r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv);
355   if(r != OK) {
356       printf("RS: do_edit: unable to update privilege structure: %d\n", r);
357       return r;
358   }
359 
360   /* Update VM calls. */
361   if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0],
362     !!(rp->r_priv.s_flags & SYS_PROC))) != OK) {
363       printf("RS: do_edit: failed: %d\n", r);
364       return r;
365   }
366 
367   /* Reinitialize scheduling. */
368   if ((r = sched_init_proc(rp)) != OK) {
369       printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r);
370       return r;
371   }
372 
373   /* Cleanup old replicas and create a new one, if necessary. */
374   if(rpub->sys_flags & SF_USE_REPL) {
375       if(rp->r_next_rp) {
376           cleanup_service(rp->r_next_rp);
377           rp->r_next_rp = NULL;
378       }
379       if ((r = clone_service(rp, RST_SYS_PROC, 0)) != OK) {
380           printf("RS: warning: unable to clone %s\n", srv_to_string(rp));
381       }
382   }
383 
384   return OK;
385 }
386 
387 /*===========================================================================*
388  *				do_refresh				     *
389  *===========================================================================*/
390 int do_refresh(message *m_ptr)
391 {
392   register struct rproc *rp;
393   int s;
394   char label[RS_MAX_LABEL_LEN];
395 
396   /* Copy label. */
397   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
398       m_ptr->m_rs_req.len, label, sizeof(label));
399   if(s != OK) {
400       return s;
401   }
402 
403   /* Lookup slot by label. */
404   rp = lookup_slot_by_label(label);
405   if(!rp) {
406       if(rs_verbose)
407           printf("RS: do_refresh: service '%s' not found\n", label);
408       return(ESRCH);
409   }
410 
411   /* Check if the call can be allowed. */
412   if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK)
413       return s;
414 
415   /* Refresh service. */
416   if(rs_verbose)
417       printf("RS: %s refreshing\n", srv_to_string(rp));
418   stop_service(rp,RS_REFRESHING);
419 
420   /* Late reply - send a reply when refresh completes. */
421   rp->r_flags |= RS_LATEREPLY;
422   rp->r_caller = m_ptr->m_source;
423   rp->r_caller_request = RS_REFRESH;
424 
425   return EDONTREPLY;
426 }
427 
428 /*===========================================================================*
429  *				do_shutdown				     *
430  *===========================================================================*/
431 int do_shutdown(message *m_ptr)
432 {
433   int slot_nr;
434   struct rproc *rp;
435   int r;
436 
437   /* Check if the call can be allowed. */
438   if (m_ptr != NULL) {
439       if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK)
440           return r;
441   }
442 
443   if(rs_verbose)
444       printf("RS: shutting down...\n");
445 
446   /* Set flag to tell RS we are shutting down. */
447   shutting_down = TRUE;
448 
449   /* Don't restart dead services. */
450   for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
451       rp = &rproc[slot_nr];
452       if (rp->r_flags & RS_IN_USE) {
453           rp->r_flags |= RS_EXITING;
454       }
455   }
456   return(OK);
457 }
458 
459 /*===========================================================================*
460  *				do_init_ready				     *
461  *===========================================================================*/
462 int do_init_ready(message *m_ptr)
463 {
464   int who_p;
465   message m;
466   struct rproc *rp, *new_rp;
467   struct rprocpub *rpub;
468   int result;
469   int r;
470 
471   who_p = _ENDPOINT_P(m_ptr->m_source);
472   result = m_ptr->m_rs_init.result;
473 
474   rp = rproc_ptr[who_p];
475   rpub = rp->r_pub;
476 
477   /* Make sure the originating service was requested to initialize. */
478   if(! (rp->r_flags & RS_INITIALIZING) ) {
479       if(rs_verbose)
480           printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
481               m_ptr->m_source);
482       return EINVAL;
483   }
484 
485   /* Check if something went wrong and the service failed to init.
486    * In that case, kill the service.
487    */
488   if(result != OK) {
489       if(rs_verbose)
490           printf("RS: %s initialization error: %s\n", srv_to_string(rp),
491               init_strerror(result));
492       if (result == ERESTART && !SRV_IS_UPDATING(rp))
493           rp->r_flags |= RS_REINCARNATE;
494       crash_service(rp); /* simulate crash */
495       rp->r_init_err = result;
496       return EDONTREPLY;
497   }
498 
499   if(rs_verbose)
500       printf("RS: %s initialized\n", srv_to_string(rp));
501 
502   /* If updating, check if there is no service to update left. In that case,
503    * end the update process. If VM has completed initialization as part of
504    * multi-component live update, let the other services under update run now.
505    */
506   if(SRV_IS_UPDATING(rp)) {
507       rupdate.num_init_ready_pending--;
508       rp->r_flags |= RS_INIT_DONE;
509       if(rupdate.num_init_ready_pending == 0) {
510           printf("RS: update succeeded\n");
511           end_update(OK, RS_REPLY);
512       }
513   }
514   else {
515       /* Mark the slot as no longer initializing. */
516       rp->r_flags &= ~RS_INITIALIZING;
517       rp->r_check_tm = 0;
518       rp->r_alive_tm = getticks();
519 
520       /* Reply and unblock the service before doing anything else. */
521       m.m_type = OK;
522       reply(rpub->endpoint, rp, &m);
523 
524       /* Finalize initialization. */
525       end_srv_init(rp);
526   }
527 
528   return EDONTREPLY;
529 }
530 
531 /*===========================================================================*
532  *				do_update				     *
533  *===========================================================================*/
534 int do_update(message *m_ptr)
535 {
536   struct rproc *rp;
537   struct rproc *trg_rp;
538   struct rproc *new_rp;
539   struct rprocpub *rpub;
540   struct rprocupd *rpupd;
541   struct rs_start rs_start;
542   int noblock, do_self_update, force_self_update, batch_mode, prepare_only;
543   int s;
544   char label[RS_MAX_LABEL_LEN];
545   int prepare_state, prepare_maxtime;
546   endpoint_t state_endpoint;
547   int lu_flags = 0;
548   int init_flags = 0;
549   int allow_retries = 0;
550 
551   /* Copy the request structure. */
552   s = copy_rs_start(m_ptr->m_source, m_ptr->m_rs_req.addr, &rs_start);
553   if (s != OK) {
554       return s;
555   }
556 
557   /* Copy label. */
558   s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
559       rs_start.rss_label.l_len, label, sizeof(label));
560   if(s != OK) {
561       return s;
562   }
563 
564   /* Lookup slot by label. */
565   rp = lookup_slot_by_label(label);
566   if(!rp) {
567       if(rs_verbose)
568           printf("RS: do_update: service '%s' not found\n", label);
569       return ESRCH;
570   }
571   rpub = rp->r_pub;
572 
573   /* Check flags. */
574   noblock = (rs_start.rss_flags & RSS_NOBLOCK);
575   do_self_update = (rs_start.rss_flags & RSS_SELF_LU);
576   force_self_update = (rs_start.rss_flags & RSS_FORCE_SELF_LU);
577   batch_mode = (rs_start.rss_flags & RSS_BATCH);
578   prepare_only = (rs_start.rss_flags & RSS_PREPARE_ONLY_LU);
579   if(do_self_update || force_self_update) {
580       lu_flags |= SEF_LU_SELF;
581   }
582   if(prepare_only) {
583       lu_flags |= SEF_LU_PREPARE_ONLY;
584   }
585   if(rs_start.rss_flags & RSS_ASR_LU) {
586       lu_flags |= SEF_LU_ASR;
587   }
588   if(!prepare_only && (rs_start.rss_flags & RSS_DETACH)) {
589       lu_flags |= SEF_LU_DETACHED;
590   }
591   if(rs_start.rss_map_prealloc_bytes <= 0
592       && rpub->endpoint == VM_PROC_NR
593       && (((lu_flags & (SEF_LU_SELF|SEF_LU_ASR)) != SEF_LU_SELF) || rs_start.rss_flags & RSS_FORCE_INIT_ST)
594       && RS_VM_DEFAULT_MAP_PREALLOC_LEN > 0) {
595       /* Give VM some mmapped regions by default on non-identical updates.*/
596       rs_start.rss_map_prealloc_bytes = RS_VM_DEFAULT_MAP_PREALLOC_LEN;
597       if(rs_verbose)
598           printf("RS: %s gets %ld default mmap bytes\n", srv_to_string(rp),
599               rs_start.rss_map_prealloc_bytes);
600   }
601   if((rs_start.rss_flags & RSS_NOMMAP_LU) || rs_start.rss_map_prealloc_bytes) {
602       /* Don't inherit mmapped regions at update time if requested or if
603        * mmap preallocation is used.
604        */
605       lu_flags |= SEF_LU_NOMMAP;
606   }
607   if(rs_start.rss_flags & RSS_FORCE_INIT_CRASH) {
608       init_flags |= SEF_INIT_CRASH;
609   }
610   if(rs_start.rss_flags & RSS_FORCE_INIT_FAIL) {
611       init_flags |= SEF_INIT_FAIL;
612   }
613   if(rs_start.rss_flags & RSS_FORCE_INIT_TIMEOUT) {
614       init_flags |= SEF_INIT_TIMEOUT;
615   }
616   if(rs_start.rss_flags & RSS_FORCE_INIT_DEFCB) {
617       init_flags |= SEF_INIT_DEFCB;
618   }
619   if(rs_start.rss_flags & RSS_FORCE_INIT_ST) {
620       init_flags |= SEF_INIT_ST;
621   }
622   init_flags |= lu_flags;
623 
624   /* Lookup target label (if any). */
625   trg_rp = NULL;
626   state_endpoint = NONE;
627   if(rs_start.rss_trg_label.l_len > 0) {
628       s = copy_label(m_ptr->m_source, rs_start.rss_trg_label.l_addr,
629           rs_start.rss_trg_label.l_len, label, sizeof(label));
630       if(s != OK) {
631           return s;
632       }
633       trg_rp = lookup_slot_by_label(label);
634       if(!trg_rp) {
635           if(rs_verbose)
636               printf("RS: do_update: target service '%s' not found\n", label);
637           return ESRCH;
638       }
639       state_endpoint = trg_rp->r_pub->endpoint;
640   }
641 
642   /* Check if the call can be allowed. */
643   if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK)
644       return s;
645 
646   /* Retrieve live update state. */
647   prepare_state = m_ptr->m_rs_update.state;
648   if(prepare_state == SEF_LU_STATE_NULL) {
649       return(EINVAL);
650   }
651 
652   /* Retrieve prepare max time. */
653   prepare_maxtime = m_ptr->m_rs_update.prepare_maxtime;
654   if(prepare_maxtime == 0) {
655       prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME;
656   }
657 
658   /* Make sure we are not already updating. */
659   if(RUPDATE_IS_UPDATING()) {
660       printf("RS: an update is already in progress\n");
661       return EBUSY;
662   }
663 
664   /* If an update is already scheduled, check constraints. */
665   if(RUPDATE_IS_UPD_SCHEDULED()) {
666       if(!batch_mode) {
667           printf("RS: an update is already scheduled, cannot start a new one\n");
668           return EBUSY;
669       }
670       if(SRV_IS_UPD_SCHEDULED(rp)) {
671           printf("RS: the specified process is already part of the currently scheduled update\n");
672           return EINVAL;
673       }
674   }
675 
676   /* Prepare-only update for VM, PM, and VFS is only supported with an unreachable state. */
677   if(prepare_only
678       && (rp->r_pub->endpoint == VM_PROC_NR || rp->r_pub->endpoint == PM_PROC_NR || rp->r_pub->endpoint == VFS_PROC_NR)) {
679       if(prepare_state != SEF_LU_STATE_UNREACHABLE) {
680           printf("RS: prepare-only update for VM, PM and VFS is only supported with state %d\n", SEF_LU_STATE_UNREACHABLE);
681           return EINVAL;
682       }
683   }
684 
685   /* Prepare-only update for RS is not supported. */
686   if(prepare_only && rp->r_pub->endpoint == RS_PROC_NR) {
687       printf("RS: prepare-only update for RS is not supported\n");
688       return EINVAL;
689   }
690 
691   /* Initialize update descriptor. */
692   rpupd = &rp->r_upd;
693   rupdate_upd_init(rpupd, rp);
694   rpupd->lu_flags |= lu_flags;
695   rpupd->init_flags |= init_flags;
696   rupdate_set_new_upd_flags(rpupd);
697 
698   /* A self update live updates a service instance into a replica, a regular
699    * update live updates a service instance into a new version, as specified
700    * by the given binary.
701    */
702   if(!prepare_only) {
703       if(do_self_update) {
704           if(rs_verbose)
705               printf("RS: %s requested to perform self update\n", srv_to_string(rp));
706 
707           /* Clone the system service and use the replica as the new version. */
708           s = clone_service(rp, LU_SYS_PROC, rpupd->init_flags);
709           if(s != OK) {
710               printf("RS: do_update: unable to clone service: %d\n", s);
711               return s;
712           }
713           new_rp = rp->r_new_rp;
714       }
715       else {
716           if(rs_verbose)
717               printf("RS: %s requested to perform %s update\n", srv_to_string(rp),
718                   force_self_update ? "(forced) self" : "regular");
719 
720           /* Allocate a system service slot for the new version. */
721           s = alloc_slot(&new_rp);
722           if(s != OK) {
723               printf("RS: do_update: unable to allocate a new slot: %d\n", s);
724               return s;
725           }
726 
727           /* Initialize the slot as requested. */
728           s = init_slot(new_rp, &rs_start, m_ptr->m_source);
729           if(s != OK) {
730               printf("RS: do_update: unable to init the new slot: %d\n", s);
731               return s;
732           }
733 
734           /* Let the new version inherit defaults from the old one. */
735           inherit_service_defaults(rp, new_rp);
736 
737           /* Link the two versions. */
738           rp->r_new_rp = new_rp;
739           new_rp->r_old_rp = rp;
740 
741           /* Create new version of the service but don't let it run. */
742           new_rp->r_priv.s_flags |= LU_SYS_PROC;
743           new_rp->r_priv.s_init_flags |= rpupd->init_flags;
744           s = create_service(new_rp);
745           if(s != OK) {
746               printf("RS: do_update: unable to create a new service: %d\n", s);
747               return s;
748           }
749       }
750 
751       /* Set default state endpoint. */
752       if(state_endpoint == NONE) {
753           state_endpoint = new_rp->r_pub->endpoint;
754       }
755 
756       /* If RS is updating, set up signal managers for the new instance.
757        * The current RS instance must be made the backup signal manager to
758        * support rollback in case of a crash during initialization.
759        */
760       if(rp->r_priv.s_flags & ROOT_SYS_PROC) {
761           s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint);
762           if(s != OK) {
763               cleanup_service(new_rp);
764               return s;
765           }
766       }
767 
768       /* Preallocate heap regions if requested. */
769       if(rs_start.rss_heap_prealloc_bytes < 0) {
770           rs_start.rss_heap_prealloc_bytes = 0;
771       }
772       if(rs_start.rss_heap_prealloc_bytes) {
773           size_t len;
774           if(rs_verbose)
775               printf("RS: %s preallocating %ld heap bytes\n", srv_to_string(new_rp),
776                   rs_start.rss_heap_prealloc_bytes);
777 
778           len = rs_start.rss_heap_prealloc_bytes;
779           s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_HEAP_PREALLOC,
780               NULL, &len);
781           if(s != OK) {
782               printf("vm_memctl(VM_RS_MEM_HEAP_PREALLOC) failed: %d\n", s);
783               cleanup_service(new_rp);
784               return s;
785           }
786           if(rp->r_priv.s_flags & ROOT_SYS_PROC) {
787               vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_PIN, 0, 0);
788           }
789       }
790 
791       /* Preallocate mmapped regions if requested. */
792       if(rs_start.rss_map_prealloc_bytes < 0) {
793           rs_start.rss_map_prealloc_bytes = 0;
794       }
795       if(rs_start.rss_map_prealloc_bytes) {
796           void *addr = NULL;
797           if(rs_verbose)
798               printf("RS: %s preallocating %ld mmap bytes\n", srv_to_string(new_rp),
799                   rs_start.rss_map_prealloc_bytes);
800 
801           new_rp->r_map_prealloc_len = rs_start.rss_map_prealloc_bytes;
802           s = vm_memctl(new_rp->r_pub->endpoint, VM_RS_MEM_MAP_PREALLOC,
803               &addr, &new_rp->r_map_prealloc_len);
804           if(s != OK) {
805               printf("vm_memctl(VM_RS_MEM_MAP_PREALLOC) failed: %d\n", s);
806               cleanup_service(new_rp);
807               return s;
808           }
809           new_rp->r_map_prealloc_addr = (vir_bytes) addr;
810       }
811   }
812 
813   /* Process state data. */
814   s = init_state_data(m_ptr->m_source, prepare_state, &rs_start.rss_state_data, &rpupd->prepare_state_data);
815   if(s != OK) {
816       rupdate_upd_clear(rpupd);
817       return s;
818   }
819 
820   /* Create update grants. */
821   if(rpupd->prepare_state_data.size > 0) {
822       struct rs_state_data *state_data = &rpupd->prepare_state_data;
823       rpupd->prepare_state_data_gid = cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data,
824           state_data->size, CPF_READ);
825       if(rpupd->prepare_state_data_gid == GRANT_INVALID) {
826           rupdate_upd_clear(rpupd);
827           return ENOMEM;
828       }
829       state_data->ipcf_els_gid = GRANT_INVALID;
830       if(state_data->ipcf_els) {
831           state_data->ipcf_els_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->ipcf_els,
832               state_data->ipcf_els_size, CPF_READ);
833           if(state_data->ipcf_els_gid == GRANT_INVALID) {
834               rupdate_upd_clear(rpupd);
835               return ENOMEM;
836           }
837       }
838       state_data->eval_gid = GRANT_INVALID;
839       if(state_data->eval_addr) {
840           state_data->eval_gid = (int) cpf_grant_direct(rpub->endpoint, (vir_bytes) state_data->eval_addr,
841               state_data->eval_len, CPF_READ);
842           if(state_data->eval_gid == GRANT_INVALID) {
843               rupdate_upd_clear(rpupd);
844               return ENOMEM;
845           }
846       }
847   }
848 
849   /* Fill the new update descriptor and add it to the update chain. */
850   rpupd->prepare_state = prepare_state;
851   rpupd->state_endpoint = state_endpoint;
852   rpupd->prepare_tm = getticks();
853   rpupd->prepare_maxtime = prepare_maxtime;
854   rupdate_add_upd(rpupd);
855 
856   if(rs_verbose)
857       printf("RS: %s scheduled for %s\n", srv_to_string(rp), srv_upd_to_string(rpupd));
858 
859   /* If batch mode, reply immediately. More services to update will follow. */
860   if(batch_mode) {
861       return OK;
862   }
863 
864   /* Start preparing for the update process. */
865   s = start_update_prepare(allow_retries);
866   if(s == ESRCH) {
867       /* No process left in the update chain. We are done already. */
868       return OK;
869   }
870   if(s != OK) {
871       return s;
872   }
873 
874   /* Unblock the caller immediately if requested. */
875   if(noblock) {
876       return OK;
877   }
878 
879   /* Otherwise, send a reply when the new version completes initialization. */
880   rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY;
881   rupdate.last_rpupd->rp->r_caller = m_ptr->m_source;
882   rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE;
883 
884   return EDONTREPLY;
885 }
886 
887 /*===========================================================================*
888  *				do_upd_ready				     *
889  *===========================================================================*/
890 int do_upd_ready(message *m_ptr)
891 {
892   struct rproc *rp;
893   struct rprocupd *prev_rpupd, *rpupd;
894   int who_p;
895   int result;
896   int is_rs;
897   int i;
898 
899   who_p = _ENDPOINT_P(m_ptr->m_source);
900   rp = rproc_ptr[who_p];
901   result = m_ptr->m_rs_update.result;
902 
903   /* Make sure the originating service was requested to prepare for update. */
904   rpupd = rupdate.curr_rpupd;
905   if(!rpupd || rp != rpupd->rp || RUPDATE_IS_INITIALIZING()) {
906       if(rs_verbose)
907           printf("RS: %s sent late/unexpected update ready msg\n",
908               srv_to_string(rp));
909       return EINVAL;
910   }
911   rp->r_flags |= RS_PREPARE_DONE;
912 
913   /* Check if something went wrong and the service failed to prepare
914    * for the update. In that case, end the update process. The old version will
915    * be replied to and continue executing.
916    */
917   if(result != OK) {
918       printf("RS: update failed: %s\n", lu_strerror(result));
919       end_update(result, RS_REPLY);
920 
921       return EDONTREPLY;
922   }
923 
924   if(rs_verbose)
925       printf("RS: %s ready to update\n", srv_to_string(rp));
926 
927   /* If this is a multi-component update and this is not the last service
928    * in the update, request the next process to update.
929    */
930   if(start_update_prepare_next() != NULL) {
931       return EDONTREPLY;
932   }
933 
934   /* Now perform the update and request each new instance to initialize. */
935   start_update();
936 
937   return EDONTREPLY;
938 }
939 
940 /*===========================================================================*
941  *				do_period				     *
942  *===========================================================================*/
943 void do_period(m_ptr)
944 message *m_ptr;
945 {
946   register struct rproc *rp;
947   register struct rprocpub *rpub;
948   clock_t now = m_ptr->m_notify.timestamp;
949   int s;
950   long period;
951 
952   /* If an update is in progress, check its status. */
953   if(RUPDATE_IS_UPDATING() && !RUPDATE_IS_INITIALIZING()) {
954       update_period(m_ptr);
955   }
956 
957   /* Search system services table. Only check slots that are in use and not
958    * updating.
959    */
960   for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
961       rpub = rp->r_pub;
962 
963       if ((rp->r_flags & RS_ACTIVE) && (!SRV_IS_UPDATING(rp) || ((rp->r_flags & (RS_INITIALIZING|RS_INIT_DONE|RS_INIT_PENDING)) == RS_INITIALIZING))) {
964 
965           /* Compute period. */
966           period = rp->r_period;
967           if(rp->r_flags & RS_INITIALIZING) {
968               period = SRV_IS_UPDATING(rp) ? UPD_INIT_MAXTIME(&rp->r_upd) : RS_INIT_T;
969           }
970 
971           /* If the service is to be revived (because it repeatedly exited,
972 	   * and was not directly restarted), the binary backoff field is
973 	   * greater than zero.
974 	   */
975 	  if (rp->r_backoff > 0) {
976               rp->r_backoff -= 1;
977 	      if (rp->r_backoff == 0) {
978 		  restart_service(rp);
979 	      }
980 	  }
981 
982 	  /* If the service was signaled with a SIGTERM and fails to respond,
983 	   * kill the system service with a SIGKILL signal.
984 	   */
985 	  else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
986 	   && rp->r_pid > 0) {
987               rp->r_stop_tm = 0;
988               crash_service(rp); /* simulate crash */
989 	  }
990 
991 	  /* There seems to be no special conditions. If the service has a
992 	   * period assigned check its status.
993 	   */
994 	  else if (period > 0) {
995 
996 	      /* Check if an answer to a status request is still pending. If
997 	       * the service didn't respond within time, kill it to simulate
998 	       * a crash. The failure will be detected and the service will
999 	       * be restarted automatically. Give the service a free pass if
1000 	       * somebody is initializing. There may be some weird dependencies
1001 	       * if another service is, for example, restarting at the same
1002 	       * time.
1003 	       */
1004               if (rp->r_alive_tm < rp->r_check_tm) {
1005 	          if (now - rp->r_alive_tm > 2*period &&
1006 		      rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) {
1007 		      struct rproc *rp2;
1008 		      int init_flag;
1009 		      if(rs_verbose)
1010                            printf("RS: %s reported late\n", srv_to_string(rp));
1011                       init_flag = rp->r_flags & RS_INITIALIZING;
1012                       rp->r_flags &= ~RS_INITIALIZING;
1013                       rp2 = lookup_slot_by_flags(RS_INITIALIZING);
1014                       rp->r_flags |= init_flag;
1015 		      if(rp2 != NULL && !SRV_IS_UPDATING(rp)) {
1016                            /* Skip for now. */
1017                            if(rs_verbose)
1018                                printf("RS: %s gets a free pass\n",
1019                                    srv_to_string(rp));
1020                            rp->r_alive_tm = now;
1021                            rp->r_check_tm = now+1;
1022                            continue;
1023 		      }
1024 		      rp->r_flags |= RS_NOPINGREPLY;
1025                       crash_service(rp); /* simulate crash */
1026                       if(rp->r_flags & RS_INITIALIZING) {
1027                           rp->r_init_err = EINTR;
1028                       }
1029 		  }
1030 	      }
1031 
1032 	      /* No answer pending. Check if a period expired since the last
1033 	       * check and, if so request the system service's status.
1034 	       */
1035 	      else if (now - rp->r_check_tm > rp->r_period) {
1036   		  ipc_notify(rpub->endpoint);		/* request status */
1037 		  rp->r_check_tm = now;			/* mark time */
1038               }
1039           }
1040       }
1041   }
1042 
1043   /* Reschedule a synchronous alarm for the next period. */
1044   if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
1045       panic("couldn't set alarm: %d", s);
1046 }
1047 
1048 /*===========================================================================*
1049  *			          do_sigchld				     *
1050  *===========================================================================*/
1051 void do_sigchld()
1052 {
1053 /* PM informed us that there are dead children to cleanup. Go get them. */
1054   pid_t pid;
1055   int status;
1056   struct rproc *rp;
1057   struct rproc **rps;
1058   int i, nr_rps, found;
1059 
1060   if(rs_verbose)
1061      printf("RS: got SIGCHLD signal, cleaning up dead children\n");
1062 
1063   while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) {
1064       rp = lookup_slot_by_pid(pid);
1065       if(rp != NULL) {
1066 
1067           if(rs_verbose)
1068               printf("RS: %s exited via another signal manager\n",
1069                   srv_to_string(rp));
1070 
1071           /* The slot is still there. This means RS is not the signal
1072            * manager assigned to the process. Ignore the event but
1073            * free slots for all the service instances and send a late
1074            * reply if necessary.
1075            */
1076           found = 0;
1077           get_service_instances(rp, &rps, &nr_rps);
1078           for(i=0;i<nr_rps;i++) {
1079               if(SRV_IS_UPDATING(rps[i])) {
1080                   rps[i]->r_flags &= ~(RS_UPDATING|RS_PREPARE_DONE|RS_INIT_DONE|RS_INIT_PENDING);
1081                   found = 1;
1082               }
1083               free_slot(rps[i]);
1084           }
1085           if(found) {
1086               rupdate_clear_upds();
1087           }
1088       }
1089   }
1090 }
1091 
1092 /*===========================================================================*
1093  *				do_getsysinfo				     *
1094  *===========================================================================*/
1095 int do_getsysinfo(m_ptr)
1096 message *m_ptr;
1097 {
1098   vir_bytes src_addr, dst_addr;
1099   int dst_proc;
1100   size_t size, len;
1101   int s;
1102 
1103   /* Check if the call can be allowed. */
1104   if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK)
1105       return s;
1106 
1107   dst_proc = m_ptr->m_source;
1108   dst_addr = m_ptr->m_lsys_getsysinfo.where;
1109   size = m_ptr->m_lsys_getsysinfo.size;
1110 
1111   switch(m_ptr->m_lsys_getsysinfo.what) {
1112   case SI_PROC_TAB:
1113   	src_addr = (vir_bytes) rproc;
1114   	len = sizeof(struct rproc) * NR_SYS_PROCS;
1115   	break;
1116   case SI_PROCALL_TAB:
1117 	/* Copy out both tables, one after the other. */
1118 	src_addr = (vir_bytes) rproc;
1119 	len = sizeof(struct rproc) * NR_SYS_PROCS;
1120 	if (len > size)
1121 		return EINVAL;
1122 	if ((s = sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)) != OK)
1123 		return s;
1124 	dst_addr += len;
1125 	size -= len;
1126 	/* FALLTHROUGH */
1127   case SI_PROCPUB_TAB:
1128   	src_addr = (vir_bytes) rprocpub;
1129   	len = sizeof(struct rprocpub) * NR_SYS_PROCS;
1130   	break;
1131   default:
1132   	return(EINVAL);
1133   }
1134 
1135   if (len != size)
1136 	return(EINVAL);
1137 
1138   return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len);
1139 }
1140 
1141 /*===========================================================================*
1142  *				do_lookup				     *
1143  *===========================================================================*/
1144 int do_lookup(m_ptr)
1145 message *m_ptr;
1146 {
1147 	static char namebuf[100];
1148 	int len, r;
1149 	struct rproc *rrp;
1150 	struct rprocpub *rrpub;
1151 
1152 	len = m_ptr->m_rs_req.name_len;
1153 
1154 	if(len < 2 || len >= sizeof(namebuf)) {
1155 		printf("RS: len too weird (%d)\n", len);
1156 		return EINVAL;
1157 	}
1158 
1159 	if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->m_rs_req.name,
1160 		SELF, (vir_bytes) namebuf, len)) != OK) {
1161 		printf("RS: name copy failed\n");
1162 		return r;
1163 
1164 	}
1165 
1166 	namebuf[len] = '\0';
1167 
1168 	rrp = lookup_slot_by_label(namebuf);
1169 	if(!rrp) {
1170 		return ESRCH;
1171 	}
1172 	rrpub = rrp->r_pub;
1173 	m_ptr->m_rs_req.endpoint = rrpub->endpoint;
1174 
1175 	return OK;
1176 }
1177 
1178 /*===========================================================================*
1179  *				do_sysctl				     *
1180  *===========================================================================*/
1181 int do_sysctl(message *m_ptr)
1182 {
1183 	int request_type = m_ptr->m_rs_req.subtype;
1184 	int r, allow_retries = 1;
1185 	switch(request_type) {
1186 		case RS_SYSCTL_SRV_STATUS:
1187 			print_services_status();
1188 		break;
1189 		case RS_SYSCTL_UPD_START:
1190 		case RS_SYSCTL_UPD_RUN:
1191 			r = start_update_prepare(allow_retries);
1192 			print_update_status();
1193 			if(r != OK) {
1194 			    if(r == ESRCH) {
1195 			        /* We are done already. */
1196 			         r = OK;
1197 			    }
1198 			    return r;
1199 			}
1200 			if(request_type == RS_SYSCTL_UPD_START) {
1201 			    return OK;
1202 			}
1203                         /* Send a reply when done. */
1204                         rupdate.last_rpupd->rp->r_flags |= RS_LATEREPLY;
1205                         rupdate.last_rpupd->rp->r_caller = m_ptr->m_source;
1206                         rupdate.last_rpupd->rp->r_caller_request = RS_UPDATE;
1207 			return EDONTREPLY;
1208 		break;
1209 		case RS_SYSCTL_UPD_STOP:
1210 			r = abort_update_proc(EINTR);
1211 			print_update_status();
1212 			return r;
1213 		break;
1214 		case RS_SYSCTL_UPD_STATUS:
1215 			print_update_status();
1216 		break;
1217 		default:
1218 			printf("RS: bad sysctl type\n");
1219 			return EINVAL;
1220 		break;
1221 	}
1222 
1223 	return OK;
1224 }
1225 
1226 /*===========================================================================*
1227  *				do_fi				     *
1228  *===========================================================================*/
1229 int do_fi(message *m_ptr)
1230 {
1231   struct rproc *rp;
1232   struct rprocpub *rpub;
1233   int s, r;
1234   char label[RS_MAX_LABEL_LEN];
1235 
1236   /* Copy label. */
1237   s = copy_label(m_ptr->m_source, m_ptr->m_rs_req.addr,
1238       m_ptr->m_rs_req.len, label, sizeof(label));
1239   if(s != OK) {
1240       return s;
1241   }
1242 
1243   /* Lookup slot by label. */
1244   rp = lookup_slot_by_label(label);
1245   if(!rp) {
1246       if(rs_verbose)
1247           printf("RS: do_fi: service '%s' not found\n", label);
1248       return(ESRCH);
1249   }
1250   rpub = rp->r_pub;
1251 
1252   /* Check if the call can be allowed. */
1253   if((r = check_call_permission(m_ptr->m_source, RS_FI, rp)) != OK)
1254       return r;
1255 
1256   /* Inject fault into the service as requested. */
1257   s = fi_service(rp);
1258 
1259   return s;
1260 }
1261 
1262 /*===========================================================================*
1263  *				   check_request			     *
1264  *===========================================================================*/
1265 static int check_request(struct rs_start *rs_start)
1266 {
1267   /* Verify scheduling parameters */
1268   if (rs_start->rss_scheduler != KERNEL &&
1269 	(rs_start->rss_scheduler < 0 ||
1270 	rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) {
1271 	printf("RS: check_request: invalid scheduler %d\n",
1272 		rs_start->rss_scheduler);
1273 	return EINVAL;
1274   }
1275   if (rs_start->rss_priority >= NR_SCHED_QUEUES) {
1276 	printf("RS: check_request: priority %u out of range\n",
1277 		rs_start->rss_priority);
1278 	return EINVAL;
1279   }
1280   if (rs_start->rss_quantum <= 0) {
1281 	printf("RS: check_request: quantum %u out of range\n",
1282 		rs_start->rss_quantum);
1283 	return EINVAL;
1284   }
1285 
1286   if (rs_start->rss_cpu == RS_CPU_BSP)
1287 	  rs_start->rss_cpu = machine.bsp_id;
1288   else if (rs_start->rss_cpu == RS_CPU_DEFAULT) {
1289 	  /* keep the default value */
1290   } else if (rs_start->rss_cpu < 0)
1291 	  return EINVAL;
1292   else if (rs_start->rss_cpu > machine.processors_count) {
1293 	  printf("RS: cpu number %d out of range 0-%d, using BSP\n",
1294 			  rs_start->rss_cpu, machine.processors_count);
1295 	  rs_start->rss_cpu = machine.bsp_id;
1296   }
1297 
1298   /* Verify signal manager. */
1299   if (rs_start->rss_sigmgr != SELF &&
1300 	(rs_start->rss_sigmgr < 0 ||
1301 	rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) {
1302 	printf("RS: check_request: invalid signal manager %d\n",
1303 		rs_start->rss_sigmgr);
1304 	return EINVAL;
1305   }
1306 
1307   return OK;
1308 }
1309 
1310