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/testkyua 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/testsh2 minix-sys
|
||||
./usr/tests/minix-posix/testvm minix-sys
|
||||
|
|
|
@ -6,39 +6,154 @@
|
|||
#include "rs/const.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 rproc rproc[NR_SYS_PROCS];
|
||||
static struct policies policies[NR_SYS_PROCS];
|
||||
|
||||
static struct inode *service_node;
|
||||
|
||||
/*
|
||||
* Initialize the service directory.
|
||||
*/
|
||||
void
|
||||
service_init(void)
|
||||
/* Updates the policies state from RS. Always returns an ASCIIZ string. */
|
||||
static const char *
|
||||
service_get_policies(struct policies * pol, index_t slot)
|
||||
{
|
||||
struct inode *root, *node;
|
||||
struct inode_stat stat;
|
||||
#if 1 /* The following should be retrieved from RS and formated instead. */
|
||||
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));
|
||||
stat.mode = DIR_ALL_MODE;
|
||||
stat.uid = SUPER_USER;
|
||||
stat.gid = SUPER_USER;
|
||||
memset(pol[slot].formatted, 0, MAX_POL_FORMAT_SZ);
|
||||
for(pos = 0; pos < (sizeof(def_pol) / sizeof(def_pol[0])); pos++) {
|
||||
if (0 == strcmp(ref_label, def_pol[pos].label)) {
|
||||
(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,
|
||||
NR_SYS_PROCS, NULL);
|
||||
|
||||
if (service_node == NULL)
|
||||
panic("unable to create service node");
|
||||
return pol[slot].formatted;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the contents of the service directory, by first updating the RS
|
||||
* tables and then updating the directory contents.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
service_update(void)
|
||||
{
|
||||
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,
|
||||
* update the tables. We do this lazily, to reduce overhead.
|
||||
|
@ -141,5 +279,8 @@ service_read(struct inode * node)
|
|||
rp = &rproc[slot];
|
||||
|
||||
/* 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
|
||||
|
||||
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.
|
||||
# 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 \
|
||||
test69 test76 test73 test74 test77 test78"
|
||||
# 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 \
|
||||
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