Restart policies: Add testing and ProcFS DB
- Expose in procfs the service status and supported recovery policies. - This adds a test (testrelpol.sh) to exercise the restart policies of the system services and drivers. NOTE: The policy support information is temporarily hardcoded in ProcFS, but this has to be replaced by properly retrieving this information from RS, which should in turn be setup on a per service basis, at initialization time. Change-Id: I0cb1516a450355b38d0c46b1a8b3d9e841a2c029
This commit is contained in:
parent
ad8bffad67
commit
41ba8c04cc
5 changed files with 328 additions and 21 deletions
|
@ -6309,6 +6309,7 @@
|
||||||
./usr/tests/minix-posix/testisofs minix-sys
|
./usr/tests/minix-posix/testisofs minix-sys
|
||||||
./usr/tests/minix-posix/testkyua minix-sys
|
./usr/tests/minix-posix/testkyua minix-sys
|
||||||
./usr/tests/minix-posix/testmfs minix-sys
|
./usr/tests/minix-posix/testmfs minix-sys
|
||||||
|
./usr/tests/minix-posix/testrelpol minix-sys
|
||||||
./usr/tests/minix-posix/testsh1 minix-sys
|
./usr/tests/minix-posix/testsh1 minix-sys
|
||||||
./usr/tests/minix-posix/testsh2 minix-sys
|
./usr/tests/minix-posix/testsh2 minix-sys
|
||||||
./usr/tests/minix-posix/testvm minix-sys
|
./usr/tests/minix-posix/testvm minix-sys
|
||||||
|
|
|
@ -6,39 +6,154 @@
|
||||||
#include "rs/const.h"
|
#include "rs/const.h"
|
||||||
#include "rs/type.h"
|
#include "rs/type.h"
|
||||||
|
|
||||||
|
enum policy {
|
||||||
|
POL_NONE = 0x00, /* user | endpoint */
|
||||||
|
POL_RESET = 0x01, /* visible | change */
|
||||||
|
POL_RESTART = 0x02, /* transparent | preserved */
|
||||||
|
POL_LIVE_UPDATE = 0x04 /* transparent | preserved */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct policies {
|
||||||
|
#define MAX_POL_FORMAT_SZ 20
|
||||||
|
char formatted[MAX_POL_FORMAT_SZ];
|
||||||
|
enum policy supported;
|
||||||
|
};
|
||||||
|
|
||||||
static struct rprocpub rprocpub[NR_SYS_PROCS];
|
static struct rprocpub rprocpub[NR_SYS_PROCS];
|
||||||
static struct rproc rproc[NR_SYS_PROCS];
|
static struct rproc rproc[NR_SYS_PROCS];
|
||||||
|
static struct policies policies[NR_SYS_PROCS];
|
||||||
|
|
||||||
static struct inode *service_node;
|
static struct inode *service_node;
|
||||||
|
|
||||||
/*
|
/* Updates the policies state from RS. Always returns an ASCIIZ string. */
|
||||||
* Initialize the service directory.
|
static const char *
|
||||||
*/
|
service_get_policies(struct policies * pol, index_t slot)
|
||||||
void
|
|
||||||
service_init(void)
|
|
||||||
{
|
{
|
||||||
struct inode *root, *node;
|
#if 1 /* The following should be retrieved from RS and formated instead. */
|
||||||
struct inode_stat stat;
|
int pos;
|
||||||
|
char *ref_label;
|
||||||
|
static const struct {
|
||||||
|
const char *label;
|
||||||
|
const char *policy_str;
|
||||||
|
} def_pol[] = {
|
||||||
|
/* audio */
|
||||||
|
{ .label = "es1370", .policy_str = "reset" },
|
||||||
|
{ .label = "es1371", .policy_str = "reset" },
|
||||||
|
{ .label = "sb16", .policy_str = "reset" },
|
||||||
|
/* bus */
|
||||||
|
{ .label = "i2c", .policy_str = "restart" },
|
||||||
|
{ .label = "pci", .policy_str = "restart" },
|
||||||
|
{ .label = "ti1225", .policy_str = "restart" },
|
||||||
|
/* clock */
|
||||||
|
{ .label = "readclock.drv", .policy_str = "restart" },
|
||||||
|
/* eeprom */
|
||||||
|
{ .label = "cat24c256", .policy_str = "restart" },
|
||||||
|
/* examples */
|
||||||
|
{ .label = "hello", .policy_str = "restart" },
|
||||||
|
/* hid */
|
||||||
|
{ .label = "pckbd", .policy_str = "reset" },
|
||||||
|
/* iommu */
|
||||||
|
{ .label = "amddev", .policy_str = "" },
|
||||||
|
/* net */
|
||||||
|
{ .label = "atl2", .policy_str = "restart" },
|
||||||
|
{ .label = "dec21140A", .policy_str = "restart" },
|
||||||
|
{ .label = "dp8390", .policy_str = "restart" },
|
||||||
|
{ .label = "dpeth", .policy_str = "restart" },
|
||||||
|
{ .label = "e1000", .policy_str = "restart" },
|
||||||
|
{ .label = "fxp", .policy_str = "restart" },
|
||||||
|
{ .label = "lance", .policy_str = "restart" },
|
||||||
|
{ .label = "lan8710a", .policy_str = "restart" },
|
||||||
|
{ .label = "orinoco", .policy_str = "restart" },
|
||||||
|
{ .label = "rtl8139", .policy_str = "restart" },
|
||||||
|
{ .label = "rtl8169", .policy_str = "restart" },
|
||||||
|
{ .label = "uds", .policy_str = "reset" },
|
||||||
|
{ .label = "virtio_net", .policy_str = "restart" },
|
||||||
|
/* power */
|
||||||
|
{ .label = "acpi", .policy_str = "" },
|
||||||
|
{ .label = "tps65217", .policy_str = "" },
|
||||||
|
{ .label = "tps65590", .policy_str = "" },
|
||||||
|
/* printer */
|
||||||
|
{ .label = "printer", .policy_str = "restart" },
|
||||||
|
/* sensors */
|
||||||
|
{ .label = "bmp085", .policy_str = "" },
|
||||||
|
{ .label = "sht21", .policy_str = "restart" },
|
||||||
|
{ .label = "tsl2550", .policy_str = "restart" },
|
||||||
|
/* storage */
|
||||||
|
{ .label = "ahci", .policy_str = "reset" },
|
||||||
|
{ .label = "at_wini", .policy_str = "reset" },
|
||||||
|
{ .label = "fbd", .policy_str = "reset" },
|
||||||
|
{ .label = "filter", .policy_str = "reset" },
|
||||||
|
{ .label = "floppy", .policy_str = "reset" },
|
||||||
|
{ .label = "memory", .policy_str = "restart" },
|
||||||
|
{ .label = "mmc", .policy_str = "reset" },
|
||||||
|
{ .label = "virtio_blk", .policy_str = "reset" },
|
||||||
|
{ .label = "vnd", .policy_str = "reset" },
|
||||||
|
/* system */
|
||||||
|
{ .label = "gpio", .policy_str = "restart" },
|
||||||
|
{ .label = "log", .policy_str = "restart" },
|
||||||
|
{ .label = "random", .policy_str = "restart" },
|
||||||
|
/* tty */
|
||||||
|
{ .label = "pty", .policy_str = "restart" },
|
||||||
|
{ .label = "tty", .policy_str = "" },
|
||||||
|
/* usb */
|
||||||
|
{ .label = "usbd", .policy_str = "" },
|
||||||
|
{ .label = "usb_hub", .policy_str = "" },
|
||||||
|
{ .label = "usb_storage", .policy_str = "" },
|
||||||
|
/* video */
|
||||||
|
{ .label = "fb", .policy_str = "" },
|
||||||
|
{ .label = "tda19988", .policy_str = "" },
|
||||||
|
/* vmm_guest */
|
||||||
|
{ .label = "vbox", .policy_str = "" },
|
||||||
|
/* fs */
|
||||||
|
{ .label = "ext2", .policy_str = "" },
|
||||||
|
{ .label = "hgfs", .policy_str = "" },
|
||||||
|
{ .label = "isofs", .policy_str = "" },
|
||||||
|
{ .label = "mfs", .policy_str = "" },
|
||||||
|
{ .label = "pfs", .policy_str = "" },
|
||||||
|
{ .label = "procfs", .policy_str = "" },
|
||||||
|
{ .label = "vbfs", .policy_str = "" },
|
||||||
|
/* net */
|
||||||
|
{ .label = "inet", .policy_str = "reset" },
|
||||||
|
{ .label = "lwip", .policy_str = "" },
|
||||||
|
/* servers */
|
||||||
|
{ .label = "devman", .policy_str = "" },
|
||||||
|
{ .label = "ds", .policy_str = "" },
|
||||||
|
{ .label = "input", .policy_str = "reset" },
|
||||||
|
{ .label = "ipc", .policy_str = "restart" },
|
||||||
|
{ .label = "is", .policy_str = "restart" },
|
||||||
|
{ .label = "pm", .policy_str = "" },
|
||||||
|
{ .label = "rs", .policy_str = "" },
|
||||||
|
{ .label = "sched", .policy_str = "" },
|
||||||
|
{ .label = "vfs", .policy_str = "" },
|
||||||
|
{ .label = "vm", .policy_str = "" },
|
||||||
|
//{ .label = "", .policy_str = "" },
|
||||||
|
};
|
||||||
|
|
||||||
root = get_root_inode();
|
/* Find the related policy, based on the file name of the service. */
|
||||||
|
ref_label = strrchr(rprocpub[slot].proc_name, '/');
|
||||||
|
if (NULL == ref_label)
|
||||||
|
ref_label = rprocpub[slot].proc_name;
|
||||||
|
|
||||||
memset(&stat, 0, sizeof(stat));
|
memset(pol[slot].formatted, 0, MAX_POL_FORMAT_SZ);
|
||||||
stat.mode = DIR_ALL_MODE;
|
for(pos = 0; pos < (sizeof(def_pol) / sizeof(def_pol[0])); pos++) {
|
||||||
stat.uid = SUPER_USER;
|
if (0 == strcmp(ref_label, def_pol[pos].label)) {
|
||||||
stat.gid = SUPER_USER;
|
(void)strncpy(pol[slot].formatted, def_pol[pos].policy_str, MAX_POL_FORMAT_SZ);
|
||||||
|
pol[slot].formatted[MAX_POL_FORMAT_SZ-1] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Should do something sensible, based on flags from RS/SEF. */
|
||||||
|
#endif
|
||||||
|
|
||||||
service_node = add_inode(root, "service", NO_INDEX, &stat,
|
return pol[slot].formatted;
|
||||||
NR_SYS_PROCS, NULL);
|
|
||||||
|
|
||||||
if (service_node == NULL)
|
|
||||||
panic("unable to create service node");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the contents of the service directory, by first updating the RS
|
* Update the contents of the service directory, by first updating the RS
|
||||||
* tables and then updating the directory contents.
|
* tables and then updating the directory contents.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
service_update(void)
|
service_update(void)
|
||||||
{
|
{
|
||||||
struct inode *node;
|
struct inode *node;
|
||||||
|
@ -86,6 +201,29 @@ service_update(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the service directory.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
service_init(void)
|
||||||
|
{
|
||||||
|
struct inode *root, *node;
|
||||||
|
struct inode_stat stat;
|
||||||
|
|
||||||
|
root = get_root_inode();
|
||||||
|
|
||||||
|
memset(&stat, 0, sizeof(stat));
|
||||||
|
stat.mode = DIR_ALL_MODE;
|
||||||
|
stat.uid = SUPER_USER;
|
||||||
|
stat.gid = SUPER_USER;
|
||||||
|
|
||||||
|
service_node = add_inode(root, "service", NO_INDEX, &stat,
|
||||||
|
NR_SYS_PROCS, NULL);
|
||||||
|
|
||||||
|
if (service_node == NULL)
|
||||||
|
panic("unable to create service node");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A lookup request is being performed. If it is in the service directory,
|
* A lookup request is being performed. If it is in the service directory,
|
||||||
* update the tables. We do this lazily, to reduce overhead.
|
* update the tables. We do this lazily, to reduce overhead.
|
||||||
|
@ -141,5 +279,8 @@ service_read(struct inode * node)
|
||||||
rp = &rproc[slot];
|
rp = &rproc[slot];
|
||||||
|
|
||||||
/* TODO: add a large number of other fields! */
|
/* TODO: add a large number of other fields! */
|
||||||
buf_printf("%d %d\n", rpub->endpoint, rp->r_restarts);
|
buf_printf("filename: %s\n", rpub->proc_name);
|
||||||
|
buf_printf("endpoint: %d\n", rpub->endpoint);
|
||||||
|
buf_printf("restarts: %d\n", rp->r_restarts);
|
||||||
|
buf_printf("policies: %s\n", service_get_policies(policies, slot));
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ PROGS+= t10a t11a t11b t40a t40b t40c t40d t40e t40f t40g t60a t60b \
|
||||||
t67a t67b t68a t68b tvnd
|
t67a t67b t68a t68b tvnd
|
||||||
|
|
||||||
SCRIPTS+= run check-install testinterp.sh testsh1.sh testsh2.sh testmfs.sh \
|
SCRIPTS+= run check-install testinterp.sh testsh1.sh testsh2.sh testmfs.sh \
|
||||||
testisofs.sh testvnd.sh testkyua.sh
|
testisofs.sh testvnd.sh testkyua.sh testrelpol.sh
|
||||||
|
|
||||||
# test57loop.S is not linked into the .bcl file.
|
# test57loop.S is not linked into the .bcl file.
|
||||||
# This way, we can link it in when linking the final binary
|
# This way, we can link it in when linking the final binary
|
||||||
|
|
|
@ -23,7 +23,7 @@ badones= # list of tests that failed
|
||||||
setuids="test11 test33 test43 test44 test46 test56 test60 test61 test65 \
|
setuids="test11 test33 test43 test44 test46 test56 test60 test61 test65 \
|
||||||
test69 test76 test73 test74 test77 test78"
|
test69 test76 test73 test74 test77 test78"
|
||||||
# Scripts that require to be run as root
|
# Scripts that require to be run as root
|
||||||
rootscripts="testisofs testvnd"
|
rootscripts="testisofs testvnd testrelpol"
|
||||||
|
|
||||||
alltests="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
alltests="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
||||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||||
|
|
165
minix/tests/testrelpol.sh
Executable file
165
minix/tests/testrelpol.sh
Executable file
|
@ -0,0 +1,165 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Idea:
|
||||||
|
# Iterate over all the /proc/service entries, and
|
||||||
|
# for each restatability policy call the policy test function if it is
|
||||||
|
# supported. No accounting of failed / successful test is done, as a
|
||||||
|
# failed test can currently provoque cascading effects, so instead we
|
||||||
|
# fail the test as a whole on the first failurei found.
|
||||||
|
#
|
||||||
|
# Supported policies have to be in the POLICIES variable, and define a test
|
||||||
|
# function.
|
||||||
|
#
|
||||||
|
# Known limitations:
|
||||||
|
# - Currently not all recovery policies are tested
|
||||||
|
# - Running this test under X11 hangs the X server
|
||||||
|
#
|
||||||
|
# To add a new policy, you have to do the following:
|
||||||
|
# 1. Add the policy into the active policies array by:
|
||||||
|
# POLICIES="${POLICIES} <policyname>"
|
||||||
|
#
|
||||||
|
# 2. define the following shell function:
|
||||||
|
# pol_<policyname>() {}
|
||||||
|
# - it will recieve the following parameters:
|
||||||
|
# + service filename as $1 : the full path to the proc entry
|
||||||
|
# + label as $2 : the service label
|
||||||
|
# - which prints 'ok' on success, 'not ok' on failure.
|
||||||
|
|
||||||
|
# Currently known policies:
|
||||||
|
# /* user | endpoint */
|
||||||
|
# POL_RESET, /* visible | change */
|
||||||
|
# POL_RESTART, /* transparent | preserved */
|
||||||
|
# POL_LIVE_UPDATE /* transparent | preserved */
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Utility functions & global state initializations
|
||||||
|
#######################################################################
|
||||||
|
POLICIES=""
|
||||||
|
MAX_RETRY=7 # so that a single test takes at most 10 seconds
|
||||||
|
|
||||||
|
# get_value(key, filename)
|
||||||
|
get_value() {
|
||||||
|
if test -f $2
|
||||||
|
then
|
||||||
|
grep $1 $2 | cut -d: -f2
|
||||||
|
else
|
||||||
|
echo "Error: service $2 down"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# wait_for_service(filename)
|
||||||
|
wait_for_service() {
|
||||||
|
local retry
|
||||||
|
retry=0
|
||||||
|
|
||||||
|
# Arbitrary timeout, found by counting the number of mice crossing
|
||||||
|
# the hallway.
|
||||||
|
sleep 2
|
||||||
|
while test ${retry} -lt ${MAX_RETRY}
|
||||||
|
do
|
||||||
|
sleep 1
|
||||||
|
retry=$((${retry} + 1))
|
||||||
|
test -f $1 && break
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# POLICY: restart
|
||||||
|
#######################################################################
|
||||||
|
POLICIES="${POLICIES} restart"
|
||||||
|
pol_restart() {
|
||||||
|
local label service
|
||||||
|
local endpoint_pre endpoint_post
|
||||||
|
local restarts_pre restarts_post
|
||||||
|
|
||||||
|
service=$1
|
||||||
|
label=$2
|
||||||
|
|
||||||
|
restarts_pre=$(get_value restarts ${service})
|
||||||
|
endpoint_pre=$(get_value endpoint ${service})
|
||||||
|
|
||||||
|
service refresh ${label}
|
||||||
|
wait_for_service ${service}
|
||||||
|
|
||||||
|
restarts_post=$(get_value restarts ${service})
|
||||||
|
endpoint_post=$(get_value endpoint ${service})
|
||||||
|
|
||||||
|
if [ ${restarts_post} -gt ${restarts_pre} \
|
||||||
|
-a ${endpoint_post} -eq ${endpoint_pre} ]
|
||||||
|
then
|
||||||
|
echo ok
|
||||||
|
else
|
||||||
|
echo not ok
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# POLICY: reset
|
||||||
|
#######################################################################
|
||||||
|
POLICIES="${POLICIES} reset"
|
||||||
|
pol_reset() {
|
||||||
|
local label service
|
||||||
|
local endpoint_pre endpoint_post
|
||||||
|
|
||||||
|
service=$1
|
||||||
|
label=$2
|
||||||
|
|
||||||
|
endpoint_pre=$(get_value endpoint ${service})
|
||||||
|
|
||||||
|
service refresh ${label}
|
||||||
|
wait_for_service ${service}
|
||||||
|
|
||||||
|
endpoint_post=$(get_value endpoint ${service})
|
||||||
|
|
||||||
|
# This policy doesn't guarantee the endpoint to be kept, but there
|
||||||
|
# is a slight chance that it will actualy stay the same, and fail
|
||||||
|
# the test.
|
||||||
|
if [ ! ${endpoint_post} -eq ${endpoint_pre} ]
|
||||||
|
then
|
||||||
|
echo ok
|
||||||
|
else
|
||||||
|
echo not ok
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# main()
|
||||||
|
#######################################################################
|
||||||
|
main() {
|
||||||
|
local labels service_policies X11
|
||||||
|
|
||||||
|
# If there is a running X server, skip the input driver
|
||||||
|
if ps -ef | grep -v grep | grep -q /usr/X11R7/bin/X
|
||||||
|
then
|
||||||
|
echo "This test can't be run while a Xserver is running"
|
||||||
|
echo "not ok # A Xserver is running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
labels=$(echo /proc/service/*)
|
||||||
|
for label in ${labels}
|
||||||
|
do
|
||||||
|
service_policies=$(grep policies ${label}|cut -d: -f2)
|
||||||
|
for pol in ${service_policies}
|
||||||
|
do
|
||||||
|
# Check if the supported policy is under test
|
||||||
|
if echo "${POLICIES}" | grep -q ${pol}
|
||||||
|
then
|
||||||
|
echo "# testing ${label} :: ${pol}"
|
||||||
|
result=$(pol_${pol} ${label} $(basename ${label}))
|
||||||
|
#pol_${pol} ${label} $(basename ${label})
|
||||||
|
#result="FAILED"
|
||||||
|
if [ "x${result}" != "xok" ]
|
||||||
|
then
|
||||||
|
echo "not ok # failed ${label}, ${pol}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ok
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
Loading…
Reference in a new issue