xref: /minix3/minix/servers/rs/main.c (revision b5e2faaaaf60a8b9a02f8d72f64caa56a87eb312)
1 /* Reincarnation Server.  This servers starts new system services and detects
2  * they are exiting.   In case of errors, system services can be restarted.
3  * The RS server periodically checks the status of all registered services
4  * services to see whether they are still alive.   The system services are
5  * expected to periodically send a heartbeat message.
6  *
7  * Changes:
8  *   Nov 22, 2009: rewrite of boot process (Cristiano Giuffrida)
9  *   Jul 22, 2005: Created  (Jorrit N. Herder)
10  */
11 #include "inc.h"
12 #include <fcntl.h>
13 #include "kernel/const.h"
14 #include "kernel/type.h"
15 #include "kernel/proc.h"
16 
17 /* Declare some local functions. */
18 static void boot_image_info_lookup( endpoint_t endpoint, struct
19 	boot_image *image, struct boot_image **ip, struct boot_image_priv **pp,
20 	struct boot_image_sys **sp, struct boot_image_dev **dp);
21 static void catch_boot_init_ready(endpoint_t endpoint);
22 static void get_work(message *m_ptr, int *status_ptr);
23 
24 /* SEF functions and variables. */
25 static void sef_local_startup(void);
26 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
27 static int sef_cb_init_restart(int type, sef_init_info_t *info);
28 static int sef_cb_init_lu(int type, sef_init_info_t *info);
29 static int sef_cb_init_response(message *m_ptr);
30 static int sef_cb_lu_response(message *m_ptr);
31 static void sef_cb_signal_handler(int signo);
32 static int sef_cb_signal_manager(endpoint_t target, int signo);
33 
34 
35 /*===========================================================================*
36  *				main                                         *
37  *===========================================================================*/
38 int main(void)
39 {
40 /* This is the main routine of this service. The main loop consists of
41  * three major activities: getting new work, processing the work, and
42  * sending the reply. The loop never terminates, unless a panic occurs.
43  */
44   message m;					/* request message */
45   int ipc_status;				/* status code */
46   int call_nr, who_e,who_p;			/* call number and caller */
47   int result;                 			/* result to return */
48   int s;
49 
50   /* SEF local startup. */
51   sef_local_startup();
52 
53   if (OK != (s=sys_getmachine(&machine)))
54 	  panic("couldn't get machine info: %d", s);
55 
56   if (OK != (s=sys_getkinfo(&kinfo)))
57 	  panic("couldn't get kernel kinfo: %d", s);
58 
59   /* Main loop - get work and do it, forever. */
60   while (TRUE) {
61       /* Perform sensitive background operations when RS is idle. */
62       rs_idle_period();
63 
64       /* Wait for request message. */
65       get_work(&m, &ipc_status);
66       who_e = m.m_source;
67       if(rs_isokendpt(who_e, &who_p) != OK) {
68           panic("message from bogus source: %d", who_e);
69       }
70 
71       call_nr = m.m_type;
72 
73       /* Now determine what to do.  Four types of requests are expected:
74        * - Heartbeat messages (notifications from registered system services)
75        * - System notifications (synchronous alarm)
76        * - User requests (control messages to manage system services)
77        * - Ready messages (reply messages from registered services)
78        */
79 
80       /* Notification messages are control messages and do not need a reply.
81        * These include heartbeat messages and system notifications.
82        */
83       if (is_ipc_notify(ipc_status)) {
84           switch (who_p) {
85           case CLOCK:
86 	      do_period(&m);			/* check services status */
87 	      continue;
88 	  default:				/* heartbeat notification */
89 	      if (rproc_ptr[who_p] != NULL) {	/* mark heartbeat time */
90 		  rproc_ptr[who_p]->r_alive_tm = m.m_notify.timestamp;
91 	      } else {
92 		  printf("RS: warning: got unexpected notify message from %d\n",
93 		      m.m_source);
94 	      }
95 	  }
96       }
97 
98       /* If we get this far, this is a normal request.
99        * Handle the request and send a reply to the caller.
100        */
101       else {
102           /* Handler functions are responsible for permission checking. */
103           switch(call_nr) {
104           /* User requests. */
105 	  case RS_UP:		result = do_up(&m);		break;
106           case RS_DOWN: 	result = do_down(&m); 		break;
107           case RS_REFRESH: 	result = do_refresh(&m); 	break;
108           case RS_RESTART: 	result = do_restart(&m); 	break;
109           case RS_SHUTDOWN: 	result = do_shutdown(&m); 	break;
110           case RS_UPDATE: 	result = do_update(&m); 	break;
111           case RS_CLONE: 	result = do_clone(&m); 		break;
112 	  case RS_UNCLONE: 	result = do_unclone(&m);	break;
113           case RS_EDIT: 	result = do_edit(&m); 		break;
114 	  case RS_SYSCTL:	result = do_sysctl(&m);		break;
115 	  case RS_FI:	result = do_fi(&m);		break;
116           case RS_GETSYSINFO:  result = do_getsysinfo(&m);     break;
117 	  case RS_LOOKUP:	result = do_lookup(&m);		break;
118 	  /* Ready messages. */
119 	  case RS_INIT: 	result = do_init_ready(&m); 	break;
120 	  case RS_LU_PREPARE: 	result = do_upd_ready(&m); 	break;
121           default:
122               printf("RS: warning: got unexpected request %d from %d\n",
123                   m.m_type, m.m_source);
124               result = ENOSYS;
125           }
126 
127           /* Finally send reply message, unless disabled. */
128           if (result != EDONTREPLY) {
129 	      m.m_type = result;
130               reply(who_e, NULL, &m);
131           }
132       }
133   }
134 }
135 
136 /*===========================================================================*
137  *			       sef_local_startup			     *
138  *===========================================================================*/
139 static void sef_local_startup()
140 {
141   /* Register init callbacks. */
142   sef_setcb_init_fresh(sef_cb_init_fresh);
143   sef_setcb_init_restart(sef_cb_init_restart);
144   sef_setcb_init_lu(sef_cb_init_lu);
145 
146   /* Register response callbacks. */
147   sef_setcb_init_response(sef_cb_init_response);
148   sef_setcb_lu_response(sef_cb_lu_response);
149 
150   /* Register signal callbacks. */
151   sef_setcb_signal_handler(sef_cb_signal_handler);
152   sef_setcb_signal_manager(sef_cb_signal_manager);
153 
154   /* Let SEF perform startup. */
155   sef_startup();
156 }
157 
158 /*===========================================================================*
159  *		            sef_cb_init_fresh                                *
160  *===========================================================================*/
161 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
162 {
163 /* Initialize the reincarnation server. */
164   struct boot_image *ip;
165   int s,i;
166   int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs;
167   struct rproc *rp;
168   struct rproc *replica_rp;
169   struct rprocpub *rpub;
170   struct boot_image image[NR_BOOT_PROCS];
171   struct boot_image_priv *boot_image_priv;
172   struct boot_image_sys *boot_image_sys;
173   struct boot_image_dev *boot_image_dev;
174   int pid, replica_pid;
175   endpoint_t replica_endpoint;
176   int ipc_to;
177   int *calls;
178   int all_c[] = { ALL_C, NULL_C };
179   int no_c[] = {  NULL_C };
180 
181   /* See if we run in verbose mode. */
182   env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
183 
184   if ((s = sys_getinfo(GET_HZ, &system_hz, sizeof(system_hz), 0, 0)) != OK)
185 	  panic("Cannot get system timer frequency\n");
186 
187   /* Initialize the global init descriptor. */
188   rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub,
189       sizeof(rprocpub), CPF_READ);
190   if(!GRANT_VALID(rinit.rproctab_gid)) {
191       panic("unable to create rprocpub table grant: %d", rinit.rproctab_gid);
192   }
193 
194   /* Initialize some global variables. */
195   RUPDATE_INIT();
196   shutting_down = FALSE;
197 
198   /* Get a copy of the boot image table. */
199   if ((s = sys_getimage(image)) != OK) {
200       panic("unable to get copy of boot image table: %d", s);
201   }
202 
203   /* Determine the number of system services in the boot image table. */
204   nr_image_srvs = 0;
205   for(i=0;i<NR_BOOT_PROCS;i++) {
206       ip = &image[i];
207 
208       /* System services only. */
209       if(iskerneln(_ENDPOINT_P(ip->endpoint))) {
210           continue;
211       }
212       nr_image_srvs++;
213   }
214 
215   /* Determine the number of entries in the boot image priv table and make sure
216    * it matches the number of system services in the boot image table.
217    */
218   nr_image_priv_srvs = 0;
219   for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
220       boot_image_priv = &boot_image_priv_table[i];
221 
222       /* System services only. */
223       if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
224           continue;
225       }
226       nr_image_priv_srvs++;
227   }
228   if(nr_image_srvs != nr_image_priv_srvs) {
229 	panic("boot image table and boot image priv table mismatch");
230   }
231 
232   /* Reset the system process table. */
233   for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
234       rp->r_flags = 0;
235       rp->r_init_err = ERESTART;
236       rp->r_pub = &rprocpub[rp - rproc];
237       rp->r_pub->in_use = FALSE;
238       rp->r_pub->old_endpoint = NONE;
239       rp->r_pub->new_endpoint = NONE;
240   }
241 
242   /* Initialize the system process table in 4 steps, each of them following
243    * the appearance of system services in the boot image priv table.
244    * - Step 1: set priviliges, sys properties, and dev properties (if any)
245    * for every system service.
246    */
247   for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
248       boot_image_priv = &boot_image_priv_table[i];
249 
250       /* System services only. */
251       if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
252           continue;
253       }
254 
255       /* Lookup the corresponding entries in other tables. */
256       boot_image_info_lookup(boot_image_priv->endpoint, image,
257           &ip, NULL, &boot_image_sys, &boot_image_dev);
258       rp = &rproc[boot_image_priv - boot_image_priv_table];
259       rpub = rp->r_pub;
260 
261       /*
262        * Set privileges.
263        */
264       /* Get label. */
265       strcpy(rpub->label, boot_image_priv->label);
266 
267       /* Force a static priv id for system services in the boot image. */
268       rp->r_priv.s_id = static_priv_id(
269           _ENDPOINT_P(boot_image_priv->endpoint));
270 
271       /* Initialize privilege bitmaps and signal manager. */
272       rp->r_priv.s_flags = boot_image_priv->flags;          /* priv flags */
273       rp->r_priv.s_init_flags = SRV_OR_USR(rp, SRV_I, USR_I); /* init flags */
274       rp->r_priv.s_trap_mask= SRV_OR_USR(rp, SRV_T, USR_T); /* traps */
275       ipc_to = SRV_OR_USR(rp, SRV_M, USR_M);                /* targets */
276       fill_send_mask(&rp->r_priv.s_ipc_to, ipc_to == ALL_M);
277       rp->r_priv.s_sig_mgr= SRV_OR_USR(rp, SRV_SM, USR_SM); /* sig mgr */
278       rp->r_priv.s_bak_sig_mgr = NONE;                      /* backup sig mgr */
279 
280       /* Initialize kernel call mask bitmap. */
281       calls = SRV_OR_USR(rp, SRV_KC, USR_KC) == ALL_C ? all_c : no_c;
282       fill_call_mask(calls, NR_SYS_CALLS,
283           rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE);
284 
285       /* Set the privilege structure. RS and VM are exceptions and are already
286        * running.
287        */
288       if(boot_image_priv->endpoint != RS_PROC_NR &&
289          boot_image_priv->endpoint != VM_PROC_NR) {
290           if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv)))
291               != OK) {
292               panic("unable to set privilege structure: %d", s);
293           }
294       }
295 
296       /* Synch the privilege structure with the kernel. */
297       if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) {
298           panic("unable to synch privilege structure: %d", s);
299       }
300 
301       /*
302        * Set sys properties.
303        */
304       rpub->sys_flags = boot_image_sys->flags;        /* sys flags */
305 
306       /*
307        * Set dev properties.
308        */
309       rpub->dev_nr = boot_image_dev->dev_nr;          /* major device number */
310 
311       /* Build command settings. This will also set the process name. */
312       strlcpy(rp->r_cmd, ip->proc_name, sizeof(rp->r_cmd));
313       rp->r_script[0]= '\0';
314       build_cmd_dep(rp);
315 
316       /* Initialize vm call mask bitmap. */
317       calls = SRV_OR_USR(rp, SRV_VC, USR_VC) == ALL_C ? all_c : no_c;
318       fill_call_mask(calls, NR_VM_CALLS, rpub->vm_call_mask, VM_RQ_BASE, TRUE);
319 
320       /* Scheduling parameters. */
321       rp->r_scheduler = SRV_OR_USR(rp, SRV_SCH, USR_SCH);
322       rp->r_priority = SRV_OR_USR(rp, SRV_Q, USR_Q);
323       rp->r_quantum = SRV_OR_USR(rp, SRV_QT, USR_QT);
324 
325       /* Get some settings from the boot image table. */
326       rpub->endpoint = ip->endpoint;
327 
328       /* Set some defaults. */
329       rp->r_old_rp = NULL;                     /* no old version yet */
330       rp->r_new_rp = NULL;                     /* no new version yet */
331       rp->r_prev_rp = NULL;                    /* no prev replica yet */
332       rp->r_next_rp = NULL;                    /* no next replica yet */
333       rp->r_uid = 0;                           /* root */
334       rp->r_check_tm = 0;                      /* not checked yet */
335       getticks(&rp->r_alive_tm);               /* currently alive */
336       rp->r_stop_tm = 0;                       /* not exiting yet */
337       rp->r_restarts = 0;                      /* no restarts so far */
338       rp->r_period = 0;                        /* no period yet */
339       rp->r_exec = NULL;                       /* no in-memory copy yet */
340       rp->r_exec_len = 0;
341 
342       /* Mark as in use and active. */
343       rp->r_flags = RS_IN_USE | RS_ACTIVE;
344       rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp;
345       rpub->in_use = TRUE;
346   }
347 
348   /* - Step 2: allow every system service in the boot image to run. */
349   nr_uncaught_init_srvs = 0;
350   for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
351       boot_image_priv = &boot_image_priv_table[i];
352 
353       /* System services only. */
354       if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
355           continue;
356       }
357 
358       /* Lookup the corresponding slot in the system process table. */
359       rp = &rproc[boot_image_priv - boot_image_priv_table];
360       rpub = rp->r_pub;
361 
362       /* RS/VM are already running as we speak. */
363       if(boot_image_priv->endpoint == RS_PROC_NR ||
364          boot_image_priv->endpoint == VM_PROC_NR) {
365           if ((s = init_service(rp, SEF_INIT_FRESH, rp->r_priv.s_init_flags)) != OK) {
366               panic("unable to initialize %d: %d", boot_image_priv->endpoint, s);
367           }
368           /* VM will still send an RS_INIT message, though. */
369           if (boot_image_priv->endpoint != RS_PROC_NR) {
370               nr_uncaught_init_srvs++;
371           }
372           continue;
373       }
374 
375       /* Allow the service to run. */
376       if ((s = sched_init_proc(rp)) != OK) {
377           panic("unable to initialize scheduling: %d", s);
378       }
379       if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
380           panic("unable to initialize privileges: %d", s);
381       }
382 
383       /* Initialize service. We assume every service will always get
384        * back to us here at boot time.
385        */
386       if(boot_image_priv->flags & SYS_PROC) {
387           if ((s = init_service(rp, SEF_INIT_FRESH, rp->r_priv.s_init_flags)) != OK) {
388               panic("unable to initialize service: %d", s);
389           }
390           if(rpub->sys_flags & SF_SYNCH_BOOT) {
391               /* Catch init ready message now to synchronize. */
392               catch_boot_init_ready(rpub->endpoint);
393           }
394           else {
395               /* Catch init ready message later. */
396               nr_uncaught_init_srvs++;
397           }
398       }
399   }
400 
401   /* - Step 3: let every system service complete initialization by
402    * catching all the init ready messages left.
403    */
404   while(nr_uncaught_init_srvs) {
405       catch_boot_init_ready(ANY);
406       nr_uncaught_init_srvs--;
407   }
408 
409   /* - Step 4: all the system services in the boot image are now running.
410    * Complete the initialization of the system process table in collaboration
411    * with other system services.
412    */
413   for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
414       boot_image_priv = &boot_image_priv_table[i];
415 
416       /* System services only. */
417       if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
418           continue;
419       }
420 
421       /* Lookup the corresponding slot in the system process table. */
422       rp = &rproc[boot_image_priv - boot_image_priv_table];
423       rpub = rp->r_pub;
424 
425       /* Get pid from PM. */
426       rp->r_pid = getnpid(rpub->endpoint);
427       if(rp->r_pid < 0) {
428           panic("unable to get pid: %d", rp->r_pid);
429       }
430   }
431 
432   /* Set alarm to periodically check service status. */
433   if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
434       panic("couldn't set alarm: %d", s);
435 
436 #if USE_LIVEUPDATE
437   /* Now create a new RS instance and let the current
438    * instance live update into the replica. Clone RS' own slot first.
439    */
440   rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
441   if((s = clone_slot(rp, &replica_rp)) != OK) {
442       panic("unable to clone current RS instance: %d", s);
443   }
444 
445   /* Fork a new RS instance with root:operator. */
446   pid = srv_fork(0, 0);
447   if(pid < 0) {
448       panic("unable to fork a new RS instance: %d", pid);
449   }
450   replica_pid = pid ? pid : getpid();
451   if ((s = getprocnr(replica_pid, &replica_endpoint)) != 0)
452 	panic("unable to get replica endpoint: %d", s);
453   replica_rp->r_pid = replica_pid;
454   replica_rp->r_pub->endpoint = replica_endpoint;
455 
456   if(pid == 0) {
457       /* New RS instance running. */
458 
459       /* Live update the old instance into the new one. */
460       s = update_service(&rp, &replica_rp, RS_SWAP, 0);
461       if(s != OK) {
462           panic("unable to live update RS: %d", s);
463       }
464       cpf_reload();
465 
466       /* Clean up the old RS instance, the new instance will take over. */
467       cleanup_service(rp);
468 
469       /* Ask VM to pin memory for the new RS instance. */
470       if((s = vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN, 0, 0)) != OK) {
471           panic("unable to pin memory for the new RS instance: %d", s);
472       }
473   }
474   else {
475       /* Old RS instance running. */
476 
477       /* Set up privileges for the new instance and let it run. */
478       s = sys_privctl(replica_endpoint, SYS_PRIV_SET_SYS, &(replica_rp->r_priv));
479       if(s != OK) {
480           panic("unable to set privileges for the new RS instance: %d", s);
481       }
482       if ((s = sched_init_proc(replica_rp)) != OK) {
483           panic("unable to initialize RS replica scheduling: %d", s);
484       }
485       s = sys_privctl(replica_endpoint, SYS_PRIV_YIELD, NULL);
486       if(s != OK) {
487           panic("unable to yield control to the new RS instance: %d", s);
488       }
489       NOT_REACHABLE;
490   }
491 #endif /* USE_LIVEUPDATE */
492 
493   return(OK);
494 }
495 
496 /*===========================================================================*
497  *		            sef_cb_init_restart                              *
498  *===========================================================================*/
499 static int sef_cb_init_restart(int type, sef_init_info_t *info)
500 {
501 /* Restart the reincarnation server. */
502   int r;
503   struct rproc *old_rs_rp, *new_rs_rp;
504 
505   assert(info->endpoint == RS_PROC_NR);
506 
507   /* Perform default state transfer first. */
508   r = SEF_CB_INIT_RESTART_STATEFUL(type, info);
509   if(r != OK) {
510       printf("SEF_CB_INIT_RESTART_STATEFUL failed: %d\n", r);
511       return r;
512   }
513 
514   /* New RS takes over. */
515   old_rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
516   new_rs_rp = rproc_ptr[_ENDPOINT_P(info->old_endpoint)];
517   if(rs_verbose)
518       printf("RS: %s is the new RS after restart\n", srv_to_string(new_rs_rp));
519 
520   /* If an update was in progress, end it. */
521   if(SRV_IS_UPDATING(old_rs_rp)) {
522       end_update(ERESTART, RS_REPLY);
523   }
524 
525   /* Update the service into the replica. */
526   r = update_service(&old_rs_rp, &new_rs_rp, RS_DONTSWAP, 0);
527   if(r != OK) {
528       printf("update_service failed: %d\n", r);
529       return r;
530   }
531 
532   /* Initialize the new RS instance. */
533   r = init_service(new_rs_rp, SEF_INIT_RESTART, 0);
534   if(r != OK) {
535       printf("init_service failed: %d\n", r);
536       return r;
537   }
538 
539   /* Reschedule a synchronous alarm for the next period. */
540   if (OK != (r=sys_setalarm(RS_DELTA_T, 0)))
541       panic("couldn't set alarm: %d", r);
542 
543   return OK;
544 }
545 
546 /*===========================================================================*
547  *		              sef_cb_init_lu                                 *
548  *===========================================================================*/
549 static int sef_cb_init_lu(int type, sef_init_info_t *info)
550 {
551 /* Start a new version of the reincarnation server. */
552   int r;
553   struct rproc *old_rs_rp, *new_rs_rp;
554 
555   assert(info->endpoint == RS_PROC_NR);
556 
557   /* Perform default state transfer first. */
558   sef_setcb_init_restart(SEF_CB_INIT_RESTART_STATEFUL);
559   r = SEF_CB_INIT_LU_DEFAULT(type, info);
560   if(r != OK) {
561       printf("SEF_CB_INIT_LU_DEFAULT failed: %d\n", r);
562       return r;
563   }
564 
565   /* New RS takes over. */
566   old_rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
567   new_rs_rp = rproc_ptr[_ENDPOINT_P(info->old_endpoint)];
568   if(rs_verbose)
569       printf("RS: %s is the new RS after live update\n",
570           srv_to_string(new_rs_rp));
571 
572   /* Update the service into the replica. */
573   r = update_service(&old_rs_rp, &new_rs_rp, RS_DONTSWAP, 0);
574   if(r != OK) {
575       printf("update_service failed: %d\n", r);
576       return r;
577   }
578 
579   /* Check if everything is as expected. */
580   assert(RUPDATE_IS_UPDATING());
581   assert(RUPDATE_IS_INITIALIZING());
582   assert(rupdate.num_rpupds > 0);
583   assert(rupdate.num_init_ready_pending > 0);
584 
585   return OK;
586 }
587 
588 /*===========================================================================*
589 *			    sef_cb_init_response			     *
590  *===========================================================================*/
591 int sef_cb_init_response(message *m_ptr)
592 {
593   int r;
594 
595   /* Return now if RS initialization failed. */
596   r = m_ptr->m_rs_init.result;
597   if(r != OK) {
598       return r;
599   }
600 
601   /* Simulate an RS-to-RS init message. */
602   r = do_init_ready(m_ptr);
603 
604   /* Assume everything is OK if EDONTREPLY was returned. */
605   if(r == EDONTREPLY) {
606       r = OK;
607   }
608   return r;
609 }
610 
611 /*===========================================================================*
612 *			     sef_cb_lu_response				     *
613  *===========================================================================*/
614 int sef_cb_lu_response(message *m_ptr)
615 {
616   int r;
617 
618   /* Simulate an RS-to-RS update ready message. */
619   r = do_upd_ready(m_ptr);
620 
621   /* If we get this far, we didn't get updated for some reason. Report error. */
622   if(r == EDONTREPLY) {
623       r = EGENERIC;
624   }
625   return r;
626 }
627 
628 /*===========================================================================*
629  *		            sef_cb_signal_handler                            *
630  *===========================================================================*/
631 static void sef_cb_signal_handler(int signo)
632 {
633   /* Check for known signals, ignore anything else. */
634   switch(signo) {
635       case SIGCHLD:
636           do_sigchld();
637       break;
638       case SIGTERM:
639           do_shutdown(NULL);
640       break;
641   }
642 }
643 
644 /*===========================================================================*
645  *		            sef_cb_signal_manager                            *
646  *===========================================================================*/
647 static int sef_cb_signal_manager(endpoint_t target, int signo)
648 {
649 /* Process system signal on behalf of the kernel. */
650   int target_p;
651   struct rproc *rp;
652   message m;
653 
654   /* Lookup slot. */
655   if(rs_isokendpt(target, &target_p) != OK || rproc_ptr[target_p] == NULL) {
656       if(rs_verbose)
657           printf("RS: ignoring spurious signal %d for process %d\n",
658               signo, target);
659       return OK; /* clear the signal */
660   }
661   rp = rproc_ptr[target_p];
662 
663   /* Don't bother if a termination signal has already been processed. */
664   if((rp->r_flags & RS_TERMINATED) && !(rp->r_flags & RS_EXITING)) {
665       return EDEADEPT; /* process is gone */
666   }
667 
668   /* Ignore external signals for inactive service instances. */
669   if( !(rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_EXITING)) {
670       if(rs_verbose)
671           printf("RS: ignoring signal %d for inactive %s\n",
672               signo, srv_to_string(rp));
673       return OK; /* clear the signal */
674   }
675 
676   if(rs_verbose)
677       printf("RS: %s got %s signal %d\n", srv_to_string(rp),
678           SIGS_IS_TERMINATION(signo) ? "termination" : "non-termination",signo);
679 
680   /* Print stacktrace if necessary. */
681   if(SIGS_IS_STACKTRACE(signo)) {
682        sys_diagctl_stacktrace(target);
683   }
684 
685   /* In case of termination signal handle the event. */
686   if(SIGS_IS_TERMINATION(signo)) {
687       rp->r_flags |= RS_TERMINATED;
688       terminate_service(rp);
689       rs_idle_period();
690 
691       return EDEADEPT; /* process is now gone */
692   }
693   /* Never deliver signals to VM. */
694   if (rp->r_pub->endpoint == VM_PROC_NR) {
695       return OK;
696   }
697 
698   /* Translate every non-termination signal into a message. */
699   m.m_type = SIGS_SIGNAL_RECEIVED;
700   m.m_pm_lsys_sigs_signal.num = signo;
701   rs_asynsend(rp, &m, 1);
702 
703   return OK; /* signal has been delivered */
704 }
705 
706 /*===========================================================================*
707  *                         boot_image_info_lookup                            *
708  *===========================================================================*/
709 static void boot_image_info_lookup(endpoint, image, ip, pp, sp, dp)
710 endpoint_t endpoint;
711 struct boot_image *image;
712 struct boot_image **ip;
713 struct boot_image_priv **pp;
714 struct boot_image_sys **sp;
715 struct boot_image_dev **dp;
716 {
717 /* Lookup entries in boot image tables. */
718   int i;
719 
720   /* When requested, locate the corresponding entry in the boot image table
721    * or panic if not found.
722    */
723   if(ip) {
724       for (i=0; i < NR_BOOT_PROCS; i++) {
725           if(image[i].endpoint == endpoint) {
726               *ip = &image[i];
727               break;
728           }
729       }
730       if(i == NR_BOOT_PROCS) {
731           panic("boot image table lookup failed");
732       }
733   }
734 
735   /* When requested, locate the corresponding entry in the boot image priv table
736    * or panic if not found.
737    */
738   if(pp) {
739       for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
740           if(boot_image_priv_table[i].endpoint == endpoint) {
741               *pp = &boot_image_priv_table[i];
742               break;
743           }
744       }
745       if(i == NULL_BOOT_NR) {
746           panic("boot image priv table lookup failed");
747       }
748   }
749 
750   /* When requested, locate the corresponding entry in the boot image sys table
751    * or resort to the default entry if not found.
752    */
753   if(sp) {
754       for (i=0; boot_image_sys_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
755           if(boot_image_sys_table[i].endpoint == endpoint) {
756               *sp = &boot_image_sys_table[i];
757               break;
758           }
759       }
760       if(boot_image_sys_table[i].endpoint == DEFAULT_BOOT_NR) {
761           *sp = &boot_image_sys_table[i];         /* accept the default entry */
762       }
763   }
764 
765   /* When requested, locate the corresponding entry in the boot image dev table
766    * or resort to the default entry if not found.
767    */
768   if(dp) {
769       for (i=0; boot_image_dev_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
770           if(boot_image_dev_table[i].endpoint == endpoint) {
771               *dp = &boot_image_dev_table[i];
772               break;
773           }
774       }
775       if(boot_image_dev_table[i].endpoint == DEFAULT_BOOT_NR) {
776           *dp = &boot_image_dev_table[i];         /* accept the default entry */
777       }
778   }
779 }
780 
781 /*===========================================================================*
782  *			      catch_boot_init_ready                          *
783  *===========================================================================*/
784 static void catch_boot_init_ready(endpoint)
785 endpoint_t endpoint;
786 {
787 /* Block and catch an init ready message from the given source. */
788   int r;
789   int ipc_status;
790   message m;
791   struct rproc *rp;
792   int result;
793 
794   /* Receive init ready message. */
795   if ((r = sef_receive_status(endpoint, &m, &ipc_status)) != OK) {
796       panic("unable to receive init reply: %d", r);
797   }
798   if(m.m_type != RS_INIT) {
799       panic("unexpected reply from service: %d", m.m_source);
800   }
801   result = m.m_rs_init.result;
802   rp = rproc_ptr[_ENDPOINT_P(m.m_source)];
803 
804   /* Check result. */
805   if(result != OK) {
806       panic("unable to complete init for service: %d", m.m_source);
807   }
808 
809   /* Send a reply to unblock the service, except to VM, which sent the reply
810    * asynchronously.  Synchronous replies could lead to deadlocks there.
811    */
812   if (m.m_source != VM_PROC_NR) {
813       m.m_type = OK;
814       reply(m.m_source, rp, &m);
815   }
816 
817   /* Mark the slot as no longer initializing. */
818   rp->r_flags &= ~RS_INITIALIZING;
819   rp->r_check_tm = 0;
820   getticks(&rp->r_alive_tm);
821 }
822 
823 /*===========================================================================*
824  *				get_work                                     *
825  *===========================================================================*/
826 static void get_work(m_ptr, status_ptr)
827 message *m_ptr;				/* pointer to message */
828 int *status_ptr;			/* pointer to status */
829 {
830     int r;
831     if (OK != (r=sef_receive_status(ANY, m_ptr, status_ptr)))
832         panic("sef_receive_status failed: %d", r);
833 }
834 
835