]> Zhao Yanbai Git Server - minix.git/commitdiff
Restart policies: Add testing and ProcFS DB 28/2928/3
authorLionel Sambuc <lionel@minix3.org>
Mon, 8 Dec 2014 10:32:14 +0000 (10:32 +0000)
committerLionel Sambuc <lionel@minix3.org>
Wed, 10 Dec 2014 22:11:25 +0000 (23:11 +0100)
 - 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

distrib/sets/lists/minix/mi
minix/fs/procfs/service.c
minix/tests/Makefile
minix/tests/run
minix/tests/testrelpol.sh [new file with mode: 0755]

index 51917725ad55262ff6fb33b9882e133f44695c12..bf2d36920ba809db81700420b3957bdadbd918c4 100644 (file)
 ./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
index 2982b10dbc8190c1e8e9c07ae780e58b656172f7..a0d14b087cf85cf0c9f85d219f8ec3eee12e09af 100644 (file)
 #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;
@@ -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));
 }
index a0e16b9c61c4ddc88efa4f9f3f602b0958f2e5a2..ae7a9e38a02a2e1d5b55d0bce18dd1cfc303dc13 100644 (file)
@@ -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
index 6d939e17976322525536d8c5f1c94e64a8ade964..fd24433c4129c92ba1a284868b4f284fb8c6447e 100755 (executable)
@@ -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 \
diff --git a/minix/tests/testrelpol.sh b/minix/tests/testrelpol.sh
new file mode 100755 (executable)
index 0000000..e9b12fe
--- /dev/null
@@ -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