diff options
Diffstat (limited to 'external')
-rw-r--r-- | external/gard/gard.c | 79 | ||||
-rw-r--r-- | external/gard/test/results/02-usage.err | 1 |
2 files changed, 76 insertions, 4 deletions
diff --git a/external/gard/gard.c b/external/gard/gard.c index 108ee670..1ee54e6b 100644 --- a/external/gard/gard.c +++ b/external/gard/gard.c @@ -25,6 +25,7 @@ #include <dirent.h> #include <limits.h> #include <inttypes.h> +#include <ctype.h> #include <ccan/array_size/array_size.h> @@ -175,7 +176,7 @@ static int str_to_target_type(const char *path) for (i = 0; i < chip_unit_count; i++) { len = strlen(chip_units[i].desc); - if (!strncmp(chip_units[i].desc, path, len)) + if (!strncasecmp(chip_units[i].desc, path, len)) return chip_units[i].type; /* match! */ } @@ -268,6 +269,7 @@ int parse_path(const char *str, struct entity_path *parsed) int unit_id = str_to_target_type(++str); /* ++ skips the '/' */ long instance; char *end; + size_t len; if (unit_count > MAX_PATH_ELEMENTS - 1) { fprintf(stderr, "Path has more than 10 components!\n"); @@ -283,8 +285,14 @@ int parse_path(const char *str, struct entity_path *parsed) parsed->path_elements[unit_count].target_type = unit_id; /* now parse the instance # */ - str += strlen(chip_units[unit_id].desc); - instance = strtol(str, &end, 10); + len = strlen(chip_units[unit_id].desc); + instance = strtol(str + len, &end, 10); + + if (!isdigit(*(str + len))) { + fprintf(stderr, "Missing instance number after '%s'\n", + str); + return -1; + } if (*end != '\0' && *end != '/') { fprintf(stderr, "Unable to parse instance after '%s'\n", @@ -294,7 +302,7 @@ int parse_path(const char *str, struct entity_path *parsed) if (instance > 15 || instance < 0) { fprintf(stderr, - "Instance %ld out of range should be 0 to 15\n", + "Instance %ld is invalid. Must be 0 to 15\n", instance); return -1; } @@ -613,6 +621,68 @@ static int do_clear(struct gard_ctx *ctx, int argc, char **argv) return rc; } +static int do_create(struct gard_ctx *ctx, int argc, char **argv) +{ + int rc, pos, max_id = 0, last_pos = 0; + struct gard_record gard; + struct entity_path path; + + if (argc < 2) { + fprintf(stderr, "create requires path to gard\n"); + fprintf(stderr, "e.g.\n"); + fprintf(stderr, " /Sys0/Node0/Proc0\n"); + fprintf(stderr, " /Sys0/Node0/DIMM15\n"); + return 0; + } + + if (parse_path(argv[1], &path)) { + fprintf(stderr, "Unable to parse path\n"); + return 0; + } + + /* check if we already have a gard record applied to this path */ + for_each_gard(ctx, pos, &gard, &rc) { + if (!memcmp(&path, &gard.target_id, sizeof(path))) { + fprintf(stderr, + "Unit %s is already GARDed by record %#08x\n", + argv[1], be32toh(gard.record_id)); + return 0; + } + + /* + * Keep track of the largest record ID seen so far, + * we'll give the new record the max + 1 to ensure + * that it's unique + */ + if (be32toh(gard.record_id) > max_id) + max_id = be32toh(gard.record_id); + + last_pos++; + } + + /* do we have an empty record to write into? */ + if (!rc && !is_valid_record(&gard)) { + int offset = last_pos * sizeof_gard(ctx); + + memset(&gard, 0xff, sizeof(gard)); + + gard.record_id = be32toh(max_id + 1); + gard.error_type = GARD_MANUAL; + gard.target_id = path; + gard.errlog_eid = 0x0; + + if (offset > ctx->gard_data_len - sizeof(gard)) { + fprintf(stderr, "No space in GUARD for a new record\n"); + return 0; + } + + rc = blocklevel_smart_write(ctx->bl, + ctx->gard_data_pos + offset, &gard, sizeof(gard)); + } + + return rc; +} + static int check_gard_partition(struct gard_ctx *ctx) { int rc; @@ -670,6 +740,7 @@ struct { { "list", "List current GARD records", do_list }, { "show", "Show details of a GARD record", do_show }, { "clear", "Clear GARD records", do_clear }, + { "create", "Create a GARD record", do_create }, }; static void print_version(void) diff --git a/external/gard/test/results/02-usage.err b/external/gard/test/results/02-usage.err index ba3dc683..356625bd 100644 --- a/external/gard/test/results/02-usage.err +++ b/external/gard/test/results/02-usage.err @@ -20,3 +20,4 @@ Where <command> is one of: list List current GARD records show Show details of a GARD record clear Clear GARD records + create Create a GARD record |