On 2016-08-04 21:28, Ralf Ramsauer wrote:
> 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) {
>
If we want to go down this way, sysfs should first of all be improved
to support this better:
diff --git a/Documentation/sysfs-entries.txt b/Documentation/sysfs-entries.txt
index 2845220..0fc315a 100644
--- a/Documentation/sysfs-entries.txt
+++ b/Documentation/sysfs-entries.txt
@@ -11,8 +11,8 @@ can be used for monitoring the state of the hypervisor and
its cells.
|- remap_pool_size - number of pages in hypervisor remapping pool
|- remap_pool_used - used pages of hypervisor remapping pool
`- cells
- |- <name of cell>
- | |- id - unique numerical ID
+ |- <id> - unique numerical ID
+ | |- name - cell name
| |- state - "running", "running/locked", "shut down", or
| | "failed"
| |- cpus_assigned - bitmask of assigned logical CPUs
This would allow to sort the cells by ID while reading their directory
entries, thus should make the code above simpler. Would you give this a
try?
Jan
--
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.