[9] | 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 |
|
---|