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