diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 8b32eb7af8..63bbb2edb2 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -24,6 +24,18 @@ #include "logging.h" #include "common.h" +enum simple_list_col { + SIMPLE_LIST_COL_NODE, + SIMPLE_LIST_COL_GENERIC, + SIMPLE_LIST_COL_SN, + SIMPLE_LIST_COL_MODEL, + SIMPLE_LIST_COL_NS, + SIMPLE_LIST_COL_USAGE, + SIMPLE_LIST_COL_FORMAT, + SIMPLE_LIST_COL_FW_REV, + SIMPLE_LIST_COL_NUM, +}; + static const uint8_t zero_uuid[16] = { 0 }; static const uint8_t invalid_uuid[16] = {[0 ... 15] = 0xff }; static const char dash[100] = {[0 ... 99] = '-'}; @@ -104,6 +116,11 @@ struct nvme_resources { struct strset namespaces; }; +struct nvme_resources_table { + struct nvme_resources *res; + struct table *t; +}; + static int nvme_resources_init(nvme_root_t r, struct nvme_resources *res) { nvme_host_t h; @@ -5346,7 +5363,7 @@ static void stdout_generic_full_path(nvme_ns_t n, char *path, size_t len) snprintf(path, len, "ng%dn%d", instance, head_instance); } -static void stdout_list_item(nvme_ns_t n) +static void list_item(nvme_ns_t n, struct table *t) { char usage[128] = { 0 }, format[128] = { 0 }; char devname[128] = { 0 }; char genname[128] = { 0 }; @@ -5358,6 +5375,8 @@ static void stdout_list_item(nvme_ns_t n) const char *s_suffix = suffix_si_get(&nsze); const char *u_suffix = suffix_si_get(&nuse); const char *l_suffix = suffix_binary_get(&lba); + char ns[STR_LEN]; + int row; snprintf(usage, sizeof(usage), "%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix); @@ -5367,19 +5386,76 @@ static void stdout_list_item(nvme_ns_t n) stdout_dev_full_path(n, devname, sizeof(devname)); stdout_generic_full_path(n, genname, sizeof(genname)); - printf("%-21s %-21s %-20s %-40s %#-10x %-26s %-16s %-8s\n", - devname, genname, nvme_ns_get_serial(n), - nvme_ns_get_model(n), nvme_ns_get_nsid(n), usage, format, - nvme_ns_get_firmware(n)); + if (!t) { + printf("%-21s %-21s %-20s %-40s %#-10x %-26s %-16s %-8s\n", + devname, genname, nvme_ns_get_serial(n), + nvme_ns_get_model(n), nvme_ns_get_nsid(n), usage, format, + nvme_ns_get_firmware(n)); + return; + } + + row = table_get_row_id(t); + if (row < 0) { + printf("Failed to add row\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_NODE, row, devname, LEFT)) { + printf("Failed to set node value\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_GENERIC, row, genname, LEFT)) { + printf("Failed to set generic value\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_SN, row, nvme_ns_get_serial(n), LEFT)) { + printf("Failed to set sn value\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_MODEL, row, nvme_ns_get_model(n), LEFT)) { + printf("Failed to set model value\n"); + return; + } + if (!sprintf(ns, "0x%x", nvme_ns_get_nsid(n))) { + printf("Failed to output ns string\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_NS, row, ns, LEFT)) { + printf("Failed to set ns value\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_USAGE, row, usage, LEFT)) { + printf("Failed to set usage value\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_FORMAT, row, format, LEFT)) { + printf("Failed to set format value\n"); + return; + } + if (table_set_value_str(t, SIMPLE_LIST_COL_FW_REV, row, nvme_ns_get_firmware(n), LEFT)) { + printf("Failed to set fw rev value\n"); + return; + } + table_add_row(t, row); +} + +static void stdout_list_item(nvme_ns_t n) +{ + list_item(n, NULL); +} + +static void stdout_list_item_table(nvme_ns_t n, struct table *t) +{ + list_item(n, t); } static bool stdout_simple_ns(const char *name, void *arg) { - struct nvme_resources *res = arg; + struct nvme_resources_table *rst_t = arg; + struct nvme_resources *res = rst_t->res; nvme_ns_t n; n = htable_ns_get(&res->ht_n, name); - stdout_list_item(n); + stdout_list_item_table(n, rst_t->t); return true; } @@ -5387,16 +5463,32 @@ static bool stdout_simple_ns(const char *name, void *arg) static void stdout_simple_list(nvme_root_t r) { struct nvme_resources res; + struct table_column columns[SIMPLE_LIST_COL_NUM] = { + { "Node", LEFT, 21 }, + { "Generic", LEFT, 21 }, + { "SN", LEFT, 20 }, + { "Model", LEFT, 40 }, + { "Namespace", LEFT, 10 }, + { "Usage", LEFT, 26 }, + { "Format", LEFT, 16 }, + { "FW Rev", LEFT, 8 }, + }; + struct table *t = table_init_with_columns(columns, ARRAY_SIZE(columns)); + struct nvme_resources_table res_t = { &res, t }; + + if (!t) { + printf("Failed to init table\n"); + return; + } nvme_resources_init(r, &res); - printf("%-21s %-21s %-20s %-40s %-10s %-26s %-16s %-8s\n", - "Node", "Generic", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev"); - printf("%-.21s %-.21s %-.20s %-.40s %-.10s %-.26s %-.16s %-.8s\n", - dash, dash, dash, dash, dash, dash, dash, dash); - strset_iterate(&res.namespaces, stdout_simple_ns, &res); + strset_iterate(&res.namespaces, stdout_simple_ns, &res_t); + + table_print(t); nvme_resources_free(&res); + table_free(t); } static void stdout_ns_details(nvme_ns_t n) @@ -5634,7 +5726,7 @@ static void stdout_tabular_subsystem_topology_multipath(nvme_subsystem_t s) {"State", LEFT, 0}, }; - t = table_init(); + t = table_create(); if (!t) { printf("Failed to init table\n"); return; @@ -5830,7 +5922,7 @@ static void stdout_tabular_subsystem_topology(nvme_subsystem_t s) {"State", LEFT, 0}, }; - t = table_init(); + t = table_create(); if (!t) { printf("Failed to init table\n"); return; diff --git a/util/table.c b/util/table.c index 88062699df..76366b93da 100644 --- a/util/table.c +++ b/util/table.c @@ -46,17 +46,23 @@ static void table_print_centered(struct value *val, int width, enum fmt_type typ int i, len, left_pad, right_pad; char buf[64]; - if (type == FMT_STRING) + switch (type) { + case FMT_STRING: len = strlen(val->s); - else if (type == FMT_INT) + break; + case FMT_INT: len = snprintf(buf, sizeof(buf), "%d", val->i); - else if (type == FMT_UNSIGNED) + break; + case FMT_UNSIGNED: len = snprintf(buf, sizeof(buf), "%u", val->u); - else if (type == FMT_LONG) + break; + case FMT_LONG: len = snprintf(buf, sizeof(buf), "%ld", val->ld); - else if (type == FMT_UNSIGNED_LONG) + break; + case FMT_UNSIGNED_LONG: len = snprintf(buf, sizeof(buf), "%lu", val->lu); - else { + break; + default: fprintf(stderr, "Invalid format!\n"); return; } @@ -69,16 +75,25 @@ static void table_print_centered(struct value *val, int width, enum fmt_type typ putchar(' '); /* print value */ - if (type == FMT_STRING) - printf("%s ", val->s); - else if (type == FMT_INT) - printf("%d ", val->i); - else if (type == FMT_UNSIGNED) - printf("%u ", val->u); - else if (type == FMT_LONG) - printf("%ld ", val->ld); - else if (type == FMT_UNSIGNED_LONG) + switch (type) { + case FMT_STRING: + printf("%s", val->s); + break; + case FMT_INT: + printf("%d", val->i); + break; + case FMT_UNSIGNED: + printf("%u", val->u); + break; + case FMT_LONG: + printf("%ld", val->ld); + break; + case FMT_UNSIGNED_LONG: printf("%lu", val->lu); + break; + default: + break; + } /* add right padding */ for (i = 0; i < right_pad; i++) @@ -94,15 +109,21 @@ static void table_print_columns(const struct table *t) for (col = 0; col < t->num_columns; col++) { c = &t->columns[col]; width = c->width; - if (c->align == LEFT) - width *= -1; - - if (c->align == CENTERED) { + switch (c->align) { + case CENTERED: v.s = c->name; v.align = c->align; table_print_centered(&v, width, FMT_STRING); - } else - printf("%*s ", width, c->name); + break; + case LEFT: + width *= -1; + fallthrough; + default: + printf("%*s", width, c->name); + break; + } + if (col + 1 != t->num_columns) + putchar(' '); } printf("\n"); @@ -110,7 +131,8 @@ static void table_print_columns(const struct table *t) for (col = 0; col < t->num_columns; col++) { for (j = 0; j < t->columns[col].width; j++) putchar('-'); - printf(" "); + if (col + 1 != t->num_columns) + putchar(' '); } printf("\n"); @@ -131,38 +153,38 @@ static void table_print_rows(const struct table *t) v = &r->val[col]; width = c->width; - if (v->align == LEFT) - width *= -1; - - if (v->align == CENTERED) + switch (v->align) { + case CENTERED: table_print_centered(v, width, v->type); - else { + break; + case LEFT: + width *= -1; + fallthrough; + default: switch (v->type) { case FMT_STRING: - printf("%*s ", width, v->s); + printf("%*s", width, v->s); break; - case FMT_INT: - printf("%*d ", width, v->i); + printf("%*d", width, v->i); break; - case FMT_UNSIGNED: - printf("%*u ", width, v->u); + printf("%*u", width, v->u); break; - case FMT_LONG: - printf("%*ld ", width, v->ld); + printf("%*ld", width, v->ld); break; - case FMT_UNSIGNED_LONG: - printf("%*lu ", width, v->lu); + printf("%*lu", width, v->lu); break; - default: fprintf(stderr, "Invalid format!\n"); break; } + break; } + if (col + 1 != t->num_columns) + putchar(' '); } printf("\n"); } @@ -209,15 +231,23 @@ void table_add_row(struct table *t, int row_id) } } -struct table *table_init(void) +struct table *table_create(void) { - struct table *t; + return calloc(1, sizeof(struct table)); +} + +struct table *table_init_with_columns(struct table_column *c, int num_columns) +{ + struct table *t = table_create(); - t = malloc(sizeof(struct table)); if (!t) return NULL; - memset(t, 0, sizeof(struct table)); + if (table_add_columns(t, c, num_columns)) { + table_free(t); + return NULL; + } + return t; } @@ -278,7 +308,10 @@ int table_add_columns(struct table *t, struct table_column *c, int num_columns) goto free_col; t->columns[col].align = c[col].align; - t->columns[col].width = strlen(t->columns[col].name); + if (c[col].width > strlen(t->columns[col].name)) + t->columns[col].width = c[col].width; + else + t->columns[col].width = strlen(t->columns[col].name); } t->num_columns = num_columns; diff --git a/util/table.h b/util/table.h index 1c98c990de..a2ab2860fd 100644 --- a/util/table.h +++ b/util/table.h @@ -135,7 +135,7 @@ static inline void table_set_value_unsigned_long(struct table *t, int col, v->type = FMT_UNSIGNED_LONG; } -struct table *table_init(void); +struct table *table_create(void); int table_add_columns(struct table *t, struct table_column *c, int num_columns); int table_add_columns_filter(struct table *t, struct table_column *c, int num_columns, @@ -146,4 +146,16 @@ void table_add_row(struct table *t, int row); void table_print(struct table *t); void table_free(struct table *t); +/** + * table_init_with_columns() - Allocate a table instance with column definitions + * @c: Column definitions + * @num_columns:Number of columns + * + * This is a function combined table_create() and table_add_columns(). + * + * Return: The table instance, or NULL if unsuccessful. If allocated, the caller + * is responsible to free the table. + */ +struct table *table_init_with_columns(struct table_column *c, int num_columns); + #endif /* _TABLE_H_ */