Use a native implementation of the jailhouse-cell-list interface. Though
this implementation requires more lines of code, it is nice to be able
to run jailhouse cell list without a dependency on python.

Keep the output format of the former python script.

Also Add add simple interface to read sysfs entries.

Signed-off-by: Ralf Ramsauer <[email protected]>
---
 tools/jailhouse-cell-list |  71 ---------------------
 tools/jailhouse.c         | 153 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 152 insertions(+), 72 deletions(-)
 delete mode 100755 tools/jailhouse-cell-list

diff --git a/tools/jailhouse-cell-list b/tools/jailhouse-cell-list
deleted file mode 100755
index 3b5bc20..0000000
--- a/tools/jailhouse-cell-list
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-
-# Jailhouse, a Linux-based partitioning hypervisor
-#
-# Copyright (c) Siemens AG, 2014
-#
-# Authors:
-#  Jan Kiszka <[email protected]>
-#
-# This work is licensed under the terms of the GNU GPL, version 2.  See
-# the COPYING file in the top-level directory.
-
-import glob
-import os
-import sys
-
-
-def read_cpus(path):
-    return int(open(path).readline().strip().replace(",", ""), 16)
-
-
-def finish_cpu_list(last_cpu, cpu):
-    if last_cpu is not None:
-        if cpu-last_cpu > 1:
-            return "%s%d," % ("-" if cpu-last_cpu > 2 else ",", cpu-1)
-        else:
-            return ","
-    else:
-        return ""
-
-
-def print_cpus(mask):
-    last_cpu = None
-    cpu = 0
-    output = ""
-    while mask > 0:
-        if mask & 1:
-            if last_cpu is None:
-                last_cpu = cpu
-                output += str(cpu)
-        else:
-            output += finish_cpu_list(last_cpu, cpu)
-            last_cpu = None
-        mask >>= 1
-        cpu += 1
-    output += finish_cpu_list(last_cpu, cpu)
-    return output.strip(",")
-
-
-if len(sys.argv) > 1:
-    print("usage: %s" % os.path.basename(sys.argv[0]).replace("-", " "))
-    exit(0 if sys.argv[1] in ("--help", "-h") else 1)
-
-cells = []
-for cell_path in glob.glob('/sys/devices/jailhouse/cells/*'):
-    cells.append({
-        'name': os.path.basename(cell_path),
-        'id': open(cell_path + "/id").readline().strip(),
-        'state': open(cell_path + "/state").readline().strip(),
-        'cpus_assigned': read_cpus(cell_path + "/cpus_assigned"),
-        'cpus_failed': read_cpus(cell_path + "/cpus_failed")
-        })
-
-line_format = "%-8s%-24s%-16s%-24s%-24s"
-if not cells == []:
-    print(line_format % ("ID", "Name", "State",
-                         "Assigned CPUs", "Failed CPUs"))
-for cell in sorted(cells, key=lambda cell: cell['id']):
-    print(line_format % (cell['id'], cell['name'], cell['state'],
-                         print_cpus(cell['cpus_assigned']),
-                         print_cpus(cell['cpus_failed'])))
diff --git a/tools/jailhouse.c b/tools/jailhouse.c
index 8a2a2b2..ea3c315 100644
--- a/tools/jailhouse.c
+++ b/tools/jailhouse.c
@@ -14,6 +14,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <dirent.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -27,6 +28,7 @@
 
 #define JAILHOUSE_EXEC_DIR     LIBEXECDIR "/jailhouse"
 #define JAILHOUSE_DEVICE       "/dev/jailhouse"
+#define JAILHOUSE_CELLS                "/sys/devices/jailhouse/cells/"
 
 enum shutdown_load_mode {LOAD, SHUTDOWN};
 static int jailhouse_fd = -1;
@@ -35,11 +37,17 @@ struct extension {
        char *cmd, *subcmd, *help;
 };
 
+struct jailhouse_cell_info {
+       struct jailhouse_cell_id id;
+       char *state;
+       char *cpus_assigned;
+       char *cpus_failed;
+};
+
 static const struct extension extensions[] = {
        { "cell", "linux", "CELLCONFIG KERNEL [-i | --initrd FILE]\n"
          "              [-c | --cmdline \"STRING\"] "
                                        "[-w | --write-params FILE]" },
-       { "cell", "list", "" },
        { "cell", "stats", "{ ID | [--name] NAME }" },
        { "config", "create", "[-h] [-g] [-r ROOT] "
          "[--mem-inmates MEM_INMATES]\n"
@@ -58,6 +66,7 @@ static void __attribute__((noreturn)) help(char *prog, int 
exit_status)
               "   enable SYSCONFIG\n"
               "   disable\n"
               "   cell create CELLCONFIG\n"
+              "   cell list\n"
               "   cell load { ID | [--name] NAME } "
                                "{ IMAGE | { -s | --string } \"STRING\" }\n"
               "             [-a | --address ADDRESS] ...\n"
@@ -185,6 +194,20 @@ static void *read_file(const char *name, size_t *size, 
bool respect_size)
        return buffer;
 }
 
+static char *read_sysfs_entry(const char *name)
+{
+       char *ret;
+       size_t size;
+
+       ret = read_file(name, &size, false);
+
+       /* enforce the string to be null-terminated */
+       if (size && ret[size-1] != '\0')
+               ret[size-1] = '\0';
+
+       return ret;
+}
+
 static int enable(int argc, char *argv[])
 {
        void *config;
@@ -267,6 +290,132 @@ static bool match_opt(const char *argv, const char 
*short_opt,
                strcmp(argv, long_opt) == 0;
 }
 
+static struct jailhouse_cell_info *get_cell_info(const char *name)
+{
+       char buf[sizeof(JAILHOUSE_CELLS) + JAILHOUSE_CELL_ID_NAMELEN +
+               sizeof("/cpus_assigned") + 1];
+       struct jailhouse_cell_info *cinfo;
+       char *tmp;
+
+       cinfo = calloc(1, sizeof(struct jailhouse_cell_info));
+
+       /* copy cell name */
+       strncpy(cinfo->id.name, name, JAILHOUSE_CELL_ID_NAMELEN);
+
+       /* get cell id */
+       snprintf(buf, sizeof(buf), JAILHOUSE_CELLS "/%s/id", cinfo->id.name);
+       tmp = read_sysfs_entry(buf);
+       cinfo->id.id = (__s32)strtol(tmp, NULL, 10);
+       free(tmp);
+
+       /* get cell state */
+       snprintf(buf, sizeof(buf), JAILHOUSE_CELLS "/%s/state", cinfo->id.name);
+       cinfo->state = read_sysfs_entry(buf);
+
+       /* getassigned cpus */
+       snprintf(buf, sizeof(buf), JAILHOUSE_CELLS "/%s/cpus_assigned", 
cinfo->id.name);
+       cinfo->cpus_assigned = read_sysfs_entry(buf);
+
+       /* get failed cpus */
+       snprintf(buf, sizeof(buf), JAILHOUSE_CELLS "/%s/cpus_failed", 
cinfo->id.name);
+       cinfo->cpus_failed = read_sysfs_entry(buf);
+
+       return cinfo;
+}
+
+static void cell_info_free(struct jailhouse_cell_info *cinfo)
+{
+       free(cinfo->state);
+       free(cinfo->cpus_assigned);
+       free(cinfo->cpus_failed);
+       free(cinfo);
+}
+
+static char **get_cell_names(void)
+{
+       DIR *dir;
+       struct dirent *dent;
+       char **ret;
+       int num_cells = 0;
+
+       ret = calloc(1, sizeof(char*));
+       if (ret == NULL) {
+               perror("calloc");
+               exit(1);
+       }
+
+       dir = opendir(JAILHOUSE_CELLS);
+       if (dir == NULL) {
+               perror("opendir " JAILHOUSE_CELLS);
+               exit(1);
+       }
+
+       while ((dent = readdir(dir)) != NULL) {
+               /* Skip hidden files, '.' and '..' */
+               if (dent->d_name[0] == '.')
+                       continue;
+
+               ret = realloc(ret, (++num_cells+1) * sizeof(char*));
+               if (ret == NULL) {
+                       perror("realloc");
+                       exit(1);
+               }
+
+               ret[num_cells-1] = strdup(dent->d_name);
+               if (ret[num_cells-1] == NULL) {
+                       perror("strdup");
+                       exit(1);
+               }
+
+               /* propagate null termination */
+               ret[num_cells] = NULL;
+       }
+
+       if (closedir(dir)) {
+               perror("closedir " JAILHOUSE_CELLS);
+               exit(1);
+       }
+
+       return ret;
+}
+
+static void cell_names_free(char **cell_names)
+{
+       char **cell_name;
+       for (cell_name = cell_names; *cell_name; cell_name++)
+               free(*cell_name);
+       free(cell_names);
+}
+
+static int cell_list(int argc, char *argv[])
+{
+       char **cell_names, **cell_name;
+       struct jailhouse_cell_info *cinfo;
+       (void)argv;
+
+       if (argc != 3)
+               help(argv[0], 1);
+
+       cell_names = get_cell_names();
+       if (cell_names[0] == NULL) {
+               printf("No active jailhouse cells\n");
+               goto out;
+       }
+
+       printf("%-8s%-24s%-16s%-24s%-24s\n",
+               "ID", "Name", "State", "Assigned CPUs", "Failed CPUs");
+       for (cell_name = cell_names; *cell_name; cell_name++) {
+               cinfo = get_cell_info(*cell_name);
+               printf("%-8d%-24s%-16s%-24s%-24s\n", cinfo->id.id, 
cinfo->id.name, cinfo->state,
+                       cinfo->cpus_assigned, cinfo->cpus_failed);
+               cell_info_free(cinfo);
+       }
+
+out:
+       cell_names_free(cell_names);
+       return 0;
+}
+
 static int cell_shutdown_load(int argc, char *argv[],
                              enum shutdown_load_mode mode)
 {
@@ -378,6 +527,8 @@ static int cell_management(int argc, char *argv[])
 
        if (strcmp(argv[2], "create") == 0) {
                err = cell_create(argc, argv);
+       } else if (strcmp(argv[2], "list") == 0) {
+               err = cell_list(argc, argv);
        } else if (strcmp(argv[2], "load") == 0) {
                err = cell_shutdown_load(argc, argv, LOAD);
        } else if (strcmp(argv[2], "start") == 0) {
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to