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 | * Created:
|
---|
8 | * Jul 22, 2005 by Jorrit N. Herder
|
---|
9 | */
|
---|
10 | #include "inc.h"
|
---|
11 | #include <minix/dmap.h>
|
---|
12 | #include <minix/endpoint.h>
|
---|
13 | #include "../../kernel/const.h"
|
---|
14 | #include "../../kernel/type.h"
|
---|
15 |
|
---|
16 | /* Declare some local functions. */
|
---|
17 | FORWARD _PROTOTYPE(void init_server, (void) );
|
---|
18 | FORWARD _PROTOTYPE(void sig_handler, (void) );
|
---|
19 | FORWARD _PROTOTYPE(void get_work, (message *m) );
|
---|
20 | FORWARD _PROTOTYPE(void reply, (int whom, int result) );
|
---|
21 |
|
---|
22 | /* Data buffers to retrieve info during initialization. */
|
---|
23 | PRIVATE struct boot_image image[NR_BOOT_PROCS];
|
---|
24 | PUBLIC struct dmap dmap[NR_DEVICES];
|
---|
25 |
|
---|
26 | /*===========================================================================*
|
---|
27 | * main *
|
---|
28 | *===========================================================================*/
|
---|
29 | PUBLIC int main(void)
|
---|
30 | {
|
---|
31 | /* This is the main routine of this service. The main loop consists of
|
---|
32 | * three major activities: getting new work, processing the work, and
|
---|
33 | * sending the reply. The loop never terminates, unless a panic occurs.
|
---|
34 | */
|
---|
35 | message m; /* request message */
|
---|
36 | int call_nr, who_e,who_p; /* call number and caller */
|
---|
37 | int result; /* result to return */
|
---|
38 | sigset_t sigset; /* system signal set */
|
---|
39 | int s;
|
---|
40 |
|
---|
41 | /* Initialize the server, then go to work. */
|
---|
42 | init_server();
|
---|
43 |
|
---|
44 | /* Main loop - get work and do it, forever. */
|
---|
45 | while (TRUE) {
|
---|
46 |
|
---|
47 | /* Wait for request message. */
|
---|
48 | get_work(&m);
|
---|
49 | who_e = m.m_source;
|
---|
50 | who_p = _ENDPOINT_P(who_e);
|
---|
51 | if(who_p < -NR_TASKS || who_p >= NR_PROCS)
|
---|
52 | panic("RS","message from bogus source", who_e);
|
---|
53 |
|
---|
54 | call_nr = m.m_type;
|
---|
55 |
|
---|
56 | /* Now determine what to do. Three types of requests are expected:
|
---|
57 | * - Heartbeat messages (notifications from registered system services)
|
---|
58 | * - System notifications (POSIX signals or synchronous alarm)
|
---|
59 | * - User requests (control messages to manage system services)
|
---|
60 | */
|
---|
61 |
|
---|
62 | /* Notification messages are control messages and do not need a reply.
|
---|
63 | * These include heartbeat messages and system notifications.
|
---|
64 | */
|
---|
65 | if (m.m_type & NOTIFY_MESSAGE) {
|
---|
66 | switch (call_nr) {
|
---|
67 | case SYN_ALARM:
|
---|
68 | do_period(&m); /* check drivers status */
|
---|
69 | continue;
|
---|
70 | case PROC_EVENT:
|
---|
71 | sig_handler();
|
---|
72 | continue;
|
---|
73 | default: /* heartbeat notification */
|
---|
74 | if (rproc_ptr[who_p] != NULL) /* mark heartbeat time */
|
---|
75 | rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
|
---|
76 | }
|
---|
77 | }
|
---|
78 |
|
---|
79 | /* If this is not a notification message, it is a normal request.
|
---|
80 | * Handle the request and send a reply to the caller.
|
---|
81 | */
|
---|
82 | else {
|
---|
83 | switch(call_nr) {
|
---|
84 | case RS_UP: result = do_up(&m); break;
|
---|
85 | case RS_DOWN: result = do_down(&m); break;
|
---|
86 | case RS_REFRESH: result = do_refresh(&m); break;
|
---|
87 | case RS_RESCUE: result = do_rescue(&m); break;
|
---|
88 | case RS_SHUTDOWN: result = do_shutdown(&m); break;
|
---|
89 | case GETSYSINFO: result = do_getsysinfo(&m); break;
|
---|
90 | default:
|
---|
91 | printf("Warning, RS got unexpected request %d from %d\n",
|
---|
92 | m.m_type, m.m_source);
|
---|
93 | result = EINVAL;
|
---|
94 | }
|
---|
95 |
|
---|
96 | /* Finally send reply message, unless disabled. */
|
---|
97 | if (result != EDONTREPLY) {
|
---|
98 | reply(who_e, result);
|
---|
99 | }
|
---|
100 | }
|
---|
101 | }
|
---|
102 | }
|
---|
103 |
|
---|
104 |
|
---|
105 | /*===========================================================================*
|
---|
106 | * init_server *
|
---|
107 | *===========================================================================*/
|
---|
108 | PRIVATE void init_server(void)
|
---|
109 | {
|
---|
110 | /* Initialize the reincarnation server. */
|
---|
111 | struct sigaction sa;
|
---|
112 | struct boot_image *ip;
|
---|
113 | int s,t;
|
---|
114 |
|
---|
115 | /* Install signal handlers. Ask PM to transform signal into message. */
|
---|
116 | sa.sa_handler = SIG_MESS;
|
---|
117 | sigemptyset(&sa.sa_mask);
|
---|
118 | sa.sa_flags = 0;
|
---|
119 | if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
|
---|
120 | if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
|
---|
121 |
|
---|
122 | /* Initialize the system process table. Use the boot image from the kernel
|
---|
123 | * and the device map from the FS to gather all needed information.
|
---|
124 | */
|
---|
125 | if ((s = sys_getimage(image)) != OK)
|
---|
126 | panic("RS","warning: couldn't get copy of image table", s);
|
---|
127 | if ((s = getsysinfo(FS_PROC_NR, SI_DMAP_TAB, dmap)) < 0)
|
---|
128 | panic("RS","warning: couldn't get copy of dmap table", errno);
|
---|
129 |
|
---|
130 | /* Now initialize the table with the processes in the system image.
|
---|
131 | * Prepend /sbin/ to the binaries so that we can actually find them.
|
---|
132 | */
|
---|
133 | for (s=0; s< NR_BOOT_PROCS; s++) {
|
---|
134 | ip = &image[s];
|
---|
135 | if (ip->proc_nr >= 0) {
|
---|
136 | nr_in_use ++;
|
---|
137 | rproc[s].r_flags = RS_IN_USE;
|
---|
138 | rproc[s].r_proc_nr_e = ip->endpoint;
|
---|
139 | rproc[s].r_pid = getnpid(ip->proc_nr);
|
---|
140 | for(t=0; t< NR_DEVICES; t++)
|
---|
141 | if (dmap[t].dmap_driver == ip->proc_nr)
|
---|
142 | rproc[s].r_dev_nr = t;
|
---|
143 | strcpy(rproc[s].r_cmd, "/sbin/");
|
---|
144 | strcpy(rproc[s].r_cmd+6, ip->proc_name);
|
---|
145 | rproc[s].r_argc = 1;
|
---|
146 | rproc[s].r_argv[0] = rproc[s].r_cmd;
|
---|
147 | rproc[s].r_argv[1] = NULL;
|
---|
148 | }
|
---|
149 | }
|
---|
150 |
|
---|
151 | /* Set alarm to periodically check driver status. */
|
---|
152 | if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
|
---|
153 | panic("RS", "couldn't set alarm", s);
|
---|
154 |
|
---|
155 | }
|
---|
156 |
|
---|
157 | /*===========================================================================*
|
---|
158 | * sig_handler *
|
---|
159 | *===========================================================================*/
|
---|
160 | PRIVATE void sig_handler()
|
---|
161 | {
|
---|
162 | sigset_t sigset;
|
---|
163 | int sig;
|
---|
164 |
|
---|
165 | /* Try to obtain signal set from PM. */
|
---|
166 | if (getsigset(&sigset) != 0) return;
|
---|
167 |
|
---|
168 | /* Check for known signals. */
|
---|
169 | if (sigismember(&sigset, SIGCHLD)) do_exit(NULL);
|
---|
170 | if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL);
|
---|
171 | }
|
---|
172 |
|
---|
173 | /*===========================================================================*
|
---|
174 | * get_work *
|
---|
175 | *===========================================================================*/
|
---|
176 | PRIVATE void get_work(m_in)
|
---|
177 | message *m_in; /* pointer to message */
|
---|
178 | {
|
---|
179 | int s; /* receive status */
|
---|
180 | if (OK != (s=receive(ANY, m_in))) /* wait for message */
|
---|
181 | panic("RS","receive failed", s);
|
---|
182 | }
|
---|
183 |
|
---|
184 |
|
---|
185 | /*===========================================================================*
|
---|
186 | * reply *
|
---|
187 | *===========================================================================*/
|
---|
188 | PRIVATE void reply(who, result)
|
---|
189 | int who; /* replyee */
|
---|
190 | int result; /* report result */
|
---|
191 | {
|
---|
192 | message m_out; /* reply message */
|
---|
193 | int s; /* send status */
|
---|
194 |
|
---|
195 | m_out.m_type = result; /* build reply message */
|
---|
196 | if (OK != (s=send(who, &m_out))) /* send the message */
|
---|
197 | panic("RS", "unable to send reply", s);
|
---|
198 | }
|
---|
199 |
|
---|
200 |
|
---|
201 |
|
---|