#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;
-
- root = get_root_inode();
+#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 = "" },
+ };
- memset(&stat, 0, sizeof(stat));
- stat.mode = DIR_ALL_MODE;
- stat.uid = SUPER_USER;
- stat.gid = SUPER_USER;
+ /* 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;
- service_node = add_inode(root, "service", NO_INDEX, &stat,
- NR_SYS_PROCS, NULL);
+ 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
- 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;
}
}
+/*
+ * 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.
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));
}
--- /dev/null
+#!/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