New Reincarnation Server functionality.

- service refresh: to cleanly stop and restart a server or driver
- binary exponential backoff: don't restart in a loop
This commit is contained in:
Jorrit Herder 2005-10-20 20:31:18 +00:00
parent d1f2ba26b0
commit 2a98fed515
6 changed files with 218 additions and 134 deletions

View File

@ -7,7 +7,7 @@
* Created: * Created:
* Jul 22, 2005 by Jorrit N. Herder * Jul 22, 2005 by Jorrit N. Herder
*/ */
#include "rs.h" #include "inc.h"
#include <minix/dmap.h> #include <minix/dmap.h>
#include "../../kernel/const.h" #include "../../kernel/const.h"
#include "../../kernel/type.h" #include "../../kernel/type.h"
@ -16,7 +16,6 @@
FORWARD _PROTOTYPE(void init_server, (void) ); FORWARD _PROTOTYPE(void init_server, (void) );
FORWARD _PROTOTYPE(void get_work, (message *m) ); FORWARD _PROTOTYPE(void get_work, (message *m) );
FORWARD _PROTOTYPE(void reply, (int whom, int result) ); FORWARD _PROTOTYPE(void reply, (int whom, int result) );
FORWARD _PROTOTYPE(int do_getsysinfo, (message *m) );
/* Data buffers to retrieve info during initialization. */ /* Data buffers to retrieve info during initialization. */
PRIVATE struct boot_image image[NR_BOOT_PROCS]; PRIVATE struct boot_image image[NR_BOOT_PROCS];
@ -85,13 +84,16 @@ PUBLIC int main(void)
*/ */
else { else {
switch(call_nr) { switch(call_nr) {
case SRV_UP: case RS_UP:
result = do_start(&m); result = do_up(&m);
break; break;
case SRV_DOWN: case RS_DOWN:
result = do_stop(&m); result = do_down(&m);
break; break;
case SRV_SHUTDOWN: case RS_REFRESH:
result = do_refresh(&m);
break;
case RS_SHUTDOWN:
result = do_shutdown(&m); result = do_shutdown(&m);
break; break;
case GETSYSINFO: case GETSYSINFO:
@ -148,7 +150,7 @@ PRIVATE void init_server(void)
ip = &image[s]; ip = &image[s];
if (ip->proc_nr >= 0) { if (ip->proc_nr >= 0) {
nr_in_use ++; nr_in_use ++;
rproc[s].r_flags = IN_USE; rproc[s].r_flags = RS_IN_USE;
rproc[s].r_proc_nr = ip->proc_nr; rproc[s].r_proc_nr = ip->proc_nr;
rproc[s].r_pid = getnpid(ip->proc_nr); rproc[s].r_pid = getnpid(ip->proc_nr);
for(t=0; t< NR_DEVICES; t++) for(t=0; t< NR_DEVICES; t++)
@ -162,39 +164,12 @@ PRIVATE void init_server(void)
} }
/* Set alarm to periodically check driver status. */ /* Set alarm to periodically check driver status. */
if (OK != (s=sys_setalarm(HZ, 0))) if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
panic("RS", "couldn't set alarm", s); panic("RS", "couldn't set alarm", s);
} }
/*===========================================================================*
* do_getsysinfo *
*===========================================================================*/
PRIVATE int do_getsysinfo(m_ptr)
message *m_ptr;
{
vir_bytes src_addr, dst_addr;
int dst_proc;
size_t len;
int s;
switch(m_ptr->m1_i1) {
case SI_PROC_TAB:
src_addr = (vir_bytes) rproc;
len = sizeof(struct rproc) * NR_SYS_PROCS;
break;
default:
return(EINVAL);
}
dst_proc = m_ptr->m_source;
dst_addr = (vir_bytes) m_ptr->m1_p1;
if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
return(s);
return(OK);
}
/*===========================================================================* /*===========================================================================*
* get_work * * get_work *
*===========================================================================*/ *===========================================================================*/

View File

@ -3,7 +3,7 @@
* Jul 22, 2005: Created (Jorrit N. Herder) * Jul 22, 2005: Created (Jorrit N. Herder)
*/ */
#include "rs.h" #include "inc.h"
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -17,16 +17,16 @@ extern int errno; /* error status */
/* Prototypes for internal functions that do the hard work. */ /* Prototypes for internal functions that do the hard work. */
FORWARD _PROTOTYPE( int start_service, (struct rproc *rp) ); FORWARD _PROTOTYPE( int start_service, (struct rproc *rp) );
FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp) ); FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
PRIVATE int shutting_down = FALSE; PRIVATE int shutting_down = FALSE;
#define EXEC_FAILED 49 /* recognizable status */ #define EXEC_FAILED 49 /* recognizable status */
/*===========================================================================* /*===========================================================================*
* do_start * * do_up *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_start(m_ptr) PUBLIC int do_up(m_ptr)
message *m_ptr; /* request message pointer */ message *m_ptr; /* request message pointer */
{ {
/* A request was made to start a new system service. Dismember the request /* A request was made to start a new system service. Dismember the request
@ -44,7 +44,7 @@ message *m_ptr; /* request message pointer */
if (nr_in_use >= NR_SYS_PROCS) return(EAGAIN); if (nr_in_use >= NR_SYS_PROCS) return(EAGAIN);
for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
rp = &rproc[slot_nr]; /* get pointer to slot */ rp = &rproc[slot_nr]; /* get pointer to slot */
if (! rp->r_flags & IN_USE) /* check if available */ if (! rp->r_flags & RS_IN_USE) /* check if available */
break; break;
} }
nr_in_use ++; /* update administration */ nr_in_use ++; /* update administration */
@ -52,10 +52,10 @@ message *m_ptr; /* request message pointer */
/* Obtain command name and parameters. This is a space-separated string /* Obtain command name and parameters. This is a space-separated string
* that looks like "/sbin/service arg1 arg2 ...". Arguments are optional. * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
*/ */
if (m_ptr->SRV_CMD_LEN > MAX_COMMAND_LEN) return(E2BIG); if (m_ptr->RS_CMD_LEN > MAX_COMMAND_LEN) return(E2BIG);
if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->SRV_CMD_ADDR, if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
SELF, (vir_bytes) rp->r_cmd, m_ptr->SRV_CMD_LEN))) return(s); SELF, (vir_bytes) rp->r_cmd, m_ptr->RS_CMD_LEN))) return(s);
rp->r_cmd[m_ptr->SRV_CMD_LEN] = '\0'; /* ensure it is terminated */ rp->r_cmd[m_ptr->RS_CMD_LEN] = '\0'; /* ensure it is terminated */
if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */ if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
/* Build argument vector to be passed to execute call. The format of the /* Build argument vector to be passed to execute call. The format of the
@ -77,10 +77,11 @@ message *m_ptr; /* request message pointer */
rp->r_argv[arg_count] = NULL; /* end with NULL pointer */ rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
rp->r_argc = arg_count; rp->r_argc = arg_count;
/* Check if a heartbeat period was given. */ /* Initialize some fields. */
rp->r_period = m_ptr->SRV_PERIOD; rp->r_period = m_ptr->RS_PERIOD;
rp->r_dev_nr = m_ptr->SRV_DEV_MAJOR; rp->r_dev_nr = m_ptr->RS_DEV_MAJOR;
rp->r_dev_style = STYLE_DEV; rp->r_dev_style = STYLE_DEV;
rp->r_restarts = -1; /* will be incremented */
/* All information was gathered. Now try to start the system service. */ /* All information was gathered. Now try to start the system service. */
return(start_service(rp)); return(start_service(rp));
@ -88,21 +89,49 @@ message *m_ptr; /* request message pointer */
/*===========================================================================* /*===========================================================================*
* do_stop * * do_down *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_stop(message *m_ptr) PUBLIC int do_down(message *m_ptr)
{ {
register struct rproc *rp; register struct rproc *rp;
pid_t pid = (pid_t) m_ptr->SRV_PID; pid_t pid = (pid_t) m_ptr->RS_PID;
for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
if (rp->r_flags & IN_USE && rp->r_pid == pid) { if (rp->r_flags & RS_IN_USE && rp->r_pid == pid) {
printf("stopping %d (%d)\n", pid, m_ptr->SRV_PID); #if VERBOSE
stop_service(rp); printf("stopping %d (%d)\n", pid, m_ptr->RS_PID);
#endif
stop_service(rp,RS_EXITING);
return(OK); return(OK);
} }
} }
printf("not found %d (%d)\n", pid, m_ptr->SRV_PID); #if VERBOSE
printf("not found %d (%d)\n", pid, m_ptr->RS_PID);
#endif
return(ESRCH);
}
/*===========================================================================*
* do_refresh *
*===========================================================================*/
PUBLIC int do_refresh(message *m_ptr)
{
register struct rproc *rp;
pid_t pid = (pid_t) m_ptr->RS_PID;
for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
if (rp->r_flags & RS_IN_USE && rp->r_pid == pid) {
#if VERBOSE
printf("refreshing %d (%d)\n", pid, m_ptr->RS_PID);
#endif
stop_service(rp,RS_REFRESHING);
return(OK);
}
}
#if VERBOSE
printf("not found %d (%d)\n", pid, m_ptr->RS_PID);
#endif
return(ESRCH); return(ESRCH);
} }
@ -151,24 +180,37 @@ PUBLIC void do_exit(message *m_ptr)
* This should always succeed. * This should always succeed.
*/ */
for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
if ((rp->r_flags & IN_USE) && rp->r_pid == exit_pid) { if ((rp->r_flags & RS_IN_USE) && rp->r_pid == exit_pid) {
printf("Slot found!\n");
rproc_ptr[rp->r_proc_nr] = NULL; /* invalidate */ rproc_ptr[rp->r_proc_nr] = NULL; /* invalidate */
if ((rp->r_flags & EXIT_PENDING) || shutting_down) { if ((rp->r_flags & RS_EXITING) || shutting_down) {
printf("Expected exit. Doing nothing.\n");
rp->r_flags = 0; /* release slot */ rp->r_flags = 0; /* release slot */
rproc_ptr[rp->r_proc_nr] = NULL; rproc_ptr[rp->r_proc_nr] = NULL;
} }
else if(rp->r_flags & RS_REFRESHING) {
rp->r_restarts = -1; /* reset counter */
start_service(rp); /* direct restart */
}
else if (WIFEXITED(exit_status) && else if (WIFEXITED(exit_status) &&
WEXITSTATUS(exit_status) == EXEC_FAILED) { WEXITSTATUS(exit_status) == EXEC_FAILED) {
printf("Exit because EXEC() failed. Doing nothing.\n");
rp->r_flags = 0; /* release slot */ rp->r_flags = 0; /* release slot */
} }
else { else {
#if VERBOSE
printf("Unexpected exit. Restarting %s\n", rp->r_cmd); printf("Unexpected exit. Restarting %s\n", rp->r_cmd);
start_service(rp); /* restart */ #endif
/* Determine what to do. If this is the first unexpected
* exit, immediately restart this service. Otherwise use
* a binary exponetial backoff.
*/
if (rp->r_restarts > 0) {
rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-1));
rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
}
else {
start_service(rp); /* direct restart */
}
} }
break; break;
} }
@ -188,10 +230,30 @@ message *m_ptr;
/* Search system services table. Only check slots that are in use. */ /* Search system services table. Only check slots that are in use. */
for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
if (rp->r_flags & IN_USE) { if (rp->r_flags & RS_IN_USE) {
/* If the service is to be revived (because it repeatedly exited,
* and was not directly restarted), the binary backoff field is
* greater than zero.
*/
if (rp->r_backoff > 0) {
rp->r_backoff -= 1;
if (rp->r_backoff == 0) {
start_service(rp);
}
}
/* If the service was signaled with a SIGTERM and fails to respond,
* kill the system service with a SIGKILL signal.
*/
else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T) {
kill(rp->r_pid, SIGKILL); /* terminate */
}
/* If the service has a period assigned check its status. */ /* There seems to be no special conditions. If the service has a
if (rp->r_period > 0) { * period assigned check its status.
*/
else if (rp->r_period > 0) {
/* Check if an answer to a status request is still pending. If /* Check if an answer to a status request is still pending. If
* the driver didn't respond within time, kill it to simulate * the driver didn't respond within time, kill it to simulate
@ -218,18 +280,11 @@ message *m_ptr;
rp->r_check_tm = now; /* mark time */ rp->r_check_tm = now; /* mark time */
} }
} }
/* If the service was signaled with a SIGTERM and fails to respond,
* kill the system service with a SIGKILL signal.
*/
if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*HZ) {
kill(rp->r_pid, SIGKILL); /* terminate */
}
} }
} }
/* Reschedule a synchronous alarm for the next period. */ /* Reschedule a synchronous alarm for the next period. */
if (OK != (s=sys_setalarm(HZ, 0))) if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
panic("RS", "couldn't set alarm", s); panic("RS", "couldn't set alarm", s);
} }
@ -274,7 +329,7 @@ struct rproc *rp;
if ((s=mapdriver(child_proc_nr, rp->r_dev_nr, rp->r_dev_style)) < 0) { if ((s=mapdriver(child_proc_nr, rp->r_dev_nr, rp->r_dev_style)) < 0) {
report("RS", "couldn't map driver", errno); report("RS", "couldn't map driver", errno);
kill(child_pid, SIGKILL); /* kill driver */ kill(child_pid, SIGKILL); /* kill driver */
rp->r_flags |= EXIT_PENDING; /* expect exit */ rp->r_flags |= RS_EXITING; /* expect exit */
return(s); /* return error */ return(s); /* return error */
} }
} }
@ -287,7 +342,7 @@ struct rproc *rp;
if ((s = _taskcall(SYSTEM, SYS_PRIVCTL, &m)) < 0) { /* set privileges */ if ((s = _taskcall(SYSTEM, SYS_PRIVCTL, &m)) < 0) { /* set privileges */
report("RS","call to SYSTEM failed", s); /* to let child run */ report("RS","call to SYSTEM failed", s); /* to let child run */
kill(child_pid, SIGKILL); /* kill driver */ kill(child_pid, SIGKILL); /* kill driver */
rp->r_flags |= EXIT_PENDING; /* expect exit */ rp->r_flags |= RS_EXITING; /* expect exit */
return(s); /* return error */ return(s); /* return error */
} }
@ -301,7 +356,8 @@ struct rproc *rp;
* thing that can go wrong now, is that execution fails at the child. If * thing that can go wrong now, is that execution fails at the child. If
* that's the case, the child will exit. * that's the case, the child will exit.
*/ */
rp->r_flags = IN_USE; /* mark slot in use */ rp->r_flags = RS_IN_USE; /* mark slot in use */
rp->r_restarts += 1; /* raise nr of restarts */
rp->r_proc_nr = child_proc_nr; /* set child details */ rp->r_proc_nr = child_proc_nr; /* set child details */
rp->r_pid = child_pid; rp->r_pid = child_pid;
rp->r_check_tm = 0; /* not check yet */ rp->r_check_tm = 0; /* not check yet */
@ -314,16 +370,49 @@ struct rproc *rp;
/*===========================================================================* /*===========================================================================*
* stop_service * * stop_service *
*===========================================================================*/ *===========================================================================*/
PRIVATE int stop_service(rp) PRIVATE int stop_service(rp,how)
struct rproc *rp; struct rproc *rp;
int how;
{ {
printf("RS tries to stop %s (pid %d)\n", rp->r_cmd, rp->r_pid);
/* Try to stop the system service. First send a SIGTERM signal to ask the /* Try to stop the system service. First send a SIGTERM signal to ask the
* system service to terminate. If the service didn't install a signal * system service to terminate. If the service didn't install a signal
* handler, it will be killed. If it did and ignores the signal, we'll * handler, it will be killed. If it did and ignores the signal, we'll
* find out because we record the time here and send a SIGKILL. * find out because we record the time here and send a SIGKILL.
*/ */
rp->r_flags |= EXIT_PENDING; /* expect exit */ #if VERBOSE
printf("RS tries to stop %s (pid %d)\n", rp->r_cmd, rp->r_pid);
#endif
rp->r_flags |= how; /* what to on exit? */
kill(rp->r_pid, SIGTERM); /* first try friendly */ kill(rp->r_pid, SIGTERM); /* first try friendly */
getuptime(&rp->r_stop_tm); /* record current time */ getuptime(&rp->r_stop_tm); /* record current time */
} }
/*===========================================================================*
* do_getsysinfo *
*===========================================================================*/
PUBLIC int do_getsysinfo(m_ptr)
message *m_ptr;
{
vir_bytes src_addr, dst_addr;
int dst_proc;
size_t len;
int s;
switch(m_ptr->m1_i1) {
case SI_PROC_TAB:
src_addr = (vir_bytes) rproc;
len = sizeof(struct rproc) * NR_SYS_PROCS;
break;
default:
return(EINVAL);
}
dst_proc = m_ptr->m_source;
dst_addr = (vir_bytes) m_ptr->m1_p1;
if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
return(s);
return(OK);
}

51
servers/rs/manager.h Normal file
View File

@ -0,0 +1,51 @@
/* This table has one slot per system process. It contains information for
* servers and driver needed by the reincarnation server to keep track of
* each process' status.
*/
/* Space reserved for program and arguments. */
#define MAX_COMMAND_LEN 512 /* maximum argument string length */
#define MAX_NR_ARGS 4 /* maximum number of arguments */
/* Definition of the system process table. This table only has entries for
* the servers and drivers, and thus is not directly indexed by slot number.
*/
extern struct rproc {
int r_proc_nr; /* process slot number */
pid_t r_pid; /* process id */
dev_t r_dev_nr; /* major device number */
int r_dev_style; /* device style */
int r_restarts; /* number of restarts (initially zero) */
long r_backoff; /* number of periods to wait before revive */
unsigned r_flags; /* status and policy flags */
long r_period; /* heartbeat period (or zero) */
clock_t r_check_tm; /* timestamp of last check */
clock_t r_alive_tm; /* timestamp of last heartbeat */
clock_t r_stop_tm; /* timestamp of SIGTERM signal */
char r_cmd[MAX_COMMAND_LEN]; /* raw command plus arguments */
char *r_argv[MAX_NR_ARGS+2]; /* parsed arguments vector */
int r_argc; /* number of arguments */
} rproc[NR_SYS_PROCS];
/* Mapping for fast access to the system process table. */
extern struct rproc *rproc_ptr[NR_PROCS];
extern int nr_in_use;
/* Flag values. */
#define RS_IN_USE 0x001 /* set when process slot is in use */
#define RS_EXITING 0x002 /* set when exit is expected */
#define RS_REFRESHING 0x004 /* set when refresh must be done */
/* Constants determining RS period and binary exponential backoff. */
#define RS_DELTA_T 60 /* check every T ticks */
#define BACKOFF_BITS (sizeof(long)*8) /* bits in backoff field */
#define MAX_BACKOFF 30 /* max backoff in RS_DELTA_T */
/* Magic process table addresses. */
#define BEG_RPROC_ADDR (&rproc[0])
#define END_RPROC_ADDR (&rproc[NR_SYS_PROCS])
#define NIL_RPROC ((struct mproc *) 0)

View File

@ -4,10 +4,12 @@
_PROTOTYPE( int main, (void)); _PROTOTYPE( int main, (void));
/* manager.c */ /* manager.c */
_PROTOTYPE( int do_start, (message *m)); _PROTOTYPE( int do_up, (message *m));
_PROTOTYPE( int do_stop, (message *m)); _PROTOTYPE( int do_down, (message *m));
_PROTOTYPE( int do_refresh, (message *m));
_PROTOTYPE( int do_shutdown, (message *m)); _PROTOTYPE( int do_shutdown, (message *m));
_PROTOTYPE( void do_period, (message *m)); _PROTOTYPE( void do_period, (message *m));
_PROTOTYPE( void do_exit, (message *m)); _PROTOTYPE( void do_exit, (message *m));
_PROTOTYPE( int do_getsysinfo, (message *m));

View File

@ -1,37 +0,0 @@
/* Header file for the system service manager server.
*
* Created:
* Jul 22, 2005 by Jorrit N. Herder
*/
#define _SYSTEM 1 /* get OK and negative error codes */
#define _MINIX 1 /* tell headers to include MINIX stuff */
#define VERBOSE 1 /* display diagnostics */
#include <ansi.h>
#include <sys/types.h>
#include <limits.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <minix/callnr.h>
#include <minix/config.h>
#include <minix/type.h>
#include <minix/const.h>
#include <minix/com.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/keymap.h>
#include <minix/bitmap.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include "proto.h"
#include "rproc.h"

View File

@ -23,6 +23,7 @@
PRIVATE char *known_requests[] = { PRIVATE char *known_requests[] = {
"up", "up",
"down", "down",
"refresh",
"shutdown", "shutdown",
"catch for illegal requests" "catch for illegal requests"
}; };
@ -72,6 +73,7 @@ PRIVATE void print_usage(char *app_name, char *problem)
printf(" %s up <binary> [%s <args>] [%s <special>] [%s <ticks>]\n", printf(" %s up <binary> [%s <args>] [%s <special>] [%s <ticks>]\n",
app_name, ARG_ARGS, ARG_DEV, ARG_PERIOD); app_name, ARG_ARGS, ARG_DEV, ARG_PERIOD);
printf(" %s down <pid>\n", app_name); printf(" %s down <pid>\n", app_name);
printf(" %s refresh <pid>\n", app_name);
printf(" %s shutdown\n", app_name); printf(" %s shutdown\n", app_name);
printf("\n"); printf("\n");
} }
@ -109,9 +111,9 @@ PRIVATE int parse_arguments(int argc, char **argv)
print_usage(argv[ARG_NAME], "illegal request type"); print_usage(argv[ARG_NAME], "illegal request type");
exit(ENOSYS); exit(ENOSYS);
} }
req_nr = RS_RQ_BASE + req_type;
req_nr = SRV_RQ_BASE + req_type; if (req_nr == RS_UP) {
if (req_nr == SRV_UP) {
/* Verify argument count. */ /* Verify argument count. */
if (argc - 1 < ARG_PATH) { if (argc - 1 < ARG_PATH) {
@ -171,7 +173,7 @@ PRIVATE int parse_arguments(int argc, char **argv)
} }
} }
} }
else if (req_nr == SRV_DOWN) { else if (req_nr == RS_DOWN || req_nr == RS_REFRESH) {
/* Verify argument count. */ /* Verify argument count. */
if (argc - 1 < ARG_PID) { if (argc - 1 < ARG_PID) {
@ -183,7 +185,7 @@ PRIVATE int parse_arguments(int argc, char **argv)
exit(EINVAL); exit(EINVAL);
} }
} }
else if (req_nr == SRV_SHUTDOWN) { else if (req_nr == RS_SHUTDOWN) {
/* no extra arguments required */ /* no extra arguments required */
} }
@ -198,6 +200,7 @@ PUBLIC int main(int argc, char **argv)
{ {
message m; message m;
int result; int result;
int request;
int s; int s;
/* Verify and parse the command line arguments. All arguments are checked /* Verify and parse the command line arguments. All arguments are checked
@ -205,34 +208,35 @@ PUBLIC int main(int argc, char **argv)
* all needed parameters to perform the request are extracted and stored * all needed parameters to perform the request are extracted and stored
* global variables. * global variables.
*/ */
parse_arguments(argc, argv); request = parse_arguments(argc, argv);
/* Arguments seem fine. Try to perform the request. Only valid requests /* Arguments seem fine. Try to perform the request. Only valid requests
* should end up here. The default is used for not yet supported requests. * should end up here. The default is used for not yet supported requests.
*/ */
switch(req_type+SRV_RQ_BASE) { switch(request) {
case SRV_UP: case RS_UP:
/* Build space-separated command string to be passed to RS server. */ /* Build space-separated command string to be passed to RS server. */
strcpy(command, req_path); strcpy(command, req_path);
command[strlen(req_path)] = ' '; command[strlen(req_path)] = ' ';
strcpy(command+strlen(req_path)+1, req_args); strcpy(command+strlen(req_path)+1, req_args);
/* Build request message and send the request. */ /* Build request message and send the request. */
m.SRV_CMD_ADDR = command; m.RS_CMD_ADDR = command;
m.SRV_CMD_LEN = strlen(command); m.RS_CMD_LEN = strlen(command);
m.SRV_DEV_MAJOR = req_major; m.RS_DEV_MAJOR = req_major;
m.SRV_PERIOD = req_period; m.RS_PERIOD = req_period;
if (OK != (s=_taskcall(RS_PROC_NR, SRV_UP, &m))) if (OK != (s=_taskcall(RS_PROC_NR, request, &m)))
failure(s); failure(s);
result = m.m_type; result = m.m_type;
break; break;
case SRV_DOWN: case RS_DOWN:
m.SRV_PID = req_pid; case RS_REFRESH:
if (OK != (s=_taskcall(RS_PROC_NR, SRV_DOWN, &m))) m.RS_PID = req_pid;
if (OK != (s=_taskcall(RS_PROC_NR, request, &m)))
failure(s); failure(s);
break; break;
case SRV_SHUTDOWN: case RS_SHUTDOWN:
if (OK != (s=_taskcall(RS_PROC_NR, SRV_SHUTDOWN, &m))) if (OK != (s=_taskcall(RS_PROC_NR, request, &m)))
failure(s); failure(s);
break; break;
default: default: