On 08/06/2016 12:06 PM, Jan Kiszka wrote: > 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? I'd like to.
But this changes the existing jailhouse sysfs interface. Are you sure that no one relies on the structure? Symlinks could keep compatibility, but this gets problematic as soon as someone has the great idea to choose '0' as cell name. So you don't want to use the sysfs interface to expose human-readable bitmasks? Then bitmasks will have to be parsed in userspace. Cell ids do not necessarily have to be continuous, right? Then I still have to iterate over the cells/ directory. Ralf > > Jan > -- Ralf Ramsauer GPG: 0x8F10049B -- 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.
