Rework logpage extensibility.

Move from using a linker set to a constructor function that's
called. This simplifies the code and is slightly more obvious.  We now
keep a list of page decoders rather than having an array we managed
before. Commands will move to something similar in the future.

Reviewed by: jhb@
Differential Revision: https://reviews.freebsd.org/D19275
This commit is contained in:
imp 2019-02-22 15:15:36 +00:00
parent b9af2aaaa3
commit 90eaca25c1
3 changed files with 29 additions and 27 deletions

View File

@ -53,7 +53,14 @@ __FBSDID("$FreeBSD$");
#define MAX_FW_SLOTS (7) #define MAX_FW_SLOTS (7)
SET_CONCAT_DEF(logpage, struct logpage_function); static SLIST_HEAD(,logpage_function) logpages;
void
logpage_register(struct logpage_function *p)
{
SLIST_INSERT_HEAD(&logpages, p, link);
}
const char * const char *
kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key) kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key)
@ -326,15 +333,15 @@ NVME_LOGPAGE(fw,
static void static void
logpage_help(void) logpage_help(void)
{ {
const struct logpage_function * const *f; const struct logpage_function *f;
const char *v; const char *v;
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "%-8s %-10s %s\n", "Page", "Vendor","Page Name"); fprintf(stderr, "%-8s %-10s %s\n", "Page", "Vendor","Page Name");
fprintf(stderr, "-------- ---------- ----------\n"); fprintf(stderr, "-------- ---------- ----------\n");
for (f = logpage_begin(); f < logpage_limit(); f++) { SLIST_FOREACH(f, &logpages, link) {
v = (*f)->vendor == NULL ? "-" : (*f)->vendor; v = f->vendor == NULL ? "-" : f->vendor;
fprintf(stderr, "0x%02x %-10s %s\n", (*f)->log_page, v, (*f)->name); fprintf(stderr, "0x%02x %-10s %s\n", f->log_page, v, f->name);
} }
exit(1); exit(1);
@ -352,7 +359,7 @@ logpage(const struct nvme_function *nf, int argc, char *argv[])
uint32_t nsid, size; uint32_t nsid, size;
void *buf; void *buf;
const char *vendor = NULL; const char *vendor = NULL;
const struct logpage_function * const *f; const struct logpage_function *f;
struct nvme_controller_data cdata; struct nvme_controller_data cdata;
print_fn_t print_fn; print_fn_t print_fn;
uint8_t ns_smart; uint8_t ns_smart;
@ -438,14 +445,14 @@ logpage(const struct nvme_function *nf, int argc, char *argv[])
* the page is vendor specific, don't match the print function * the page is vendor specific, don't match the print function
* unless the vendors match. * unless the vendors match.
*/ */
for (f = logpage_begin(); f < logpage_limit(); f++) { SLIST_FOREACH(f, &logpages, link) {
if ((*f)->vendor != NULL && vendor != NULL && if (f->vendor != NULL && vendor != NULL &&
strcmp((*f)->vendor, vendor) != 0) strcmp(f->vendor, vendor) != 0)
continue; continue;
if (log_page != (*f)->log_page) if (log_page != f->log_page)
continue; continue;
print_fn = (*f)->print_fn; print_fn = f->print_fn;
size = (*f)->size; size = f->size;
break; break;
} }
} }

View File

@ -312,19 +312,17 @@ load_dir(const char *dir)
warnx("Can't load %s: %s", path, dlerror()); warnx("Can't load %s: %s", path, dlerror());
else { else {
/* /*
* Add in the top (for cli commands) and logpage (for * Add in the top (for cli commands)linker sets. We have
* logpage parsing) linker sets. We have to do this by * to do this by hand because linker sets aren't
* hand because linker sets aren't automatically merged. * automatically merged.
*/ */
void *begin, *limit; void *begin, *limit;
begin = dlsym(h, "__start_set_top"); begin = dlsym(h, "__start_set_top");
limit = dlsym(h, "__stop_set_top"); limit = dlsym(h, "__stop_set_top");
if (begin) if (begin)
add_to_top(begin, limit); add_to_top(begin, limit);
begin = dlsym(h, "__start_set_logpage"); /* log pages use constructors so are done on load */
limit = dlsym(h, "__stop_set_logpage");
if (begin)
add_to_logpage(begin, limit);
} }
free(path); free(path);
path = NULL; path = NULL;
@ -337,7 +335,6 @@ main(int argc, char *argv[])
{ {
add_to_top(NVME_CMD_BEGIN(top), NVME_CMD_LIMIT(top)); add_to_top(NVME_CMD_BEGIN(top), NVME_CMD_LIMIT(top));
add_to_logpage(NVME_LOGPAGE_BEGIN, NVME_LOGPAGE_LIMIT);
load_dir("/lib/nvmecontrol"); load_dir("/lib/nvmecontrol");
load_dir("/usr/local/lib/nvmecontrol"); load_dir("/usr/local/lib/nvmecontrol");

View File

@ -32,6 +32,7 @@
#define __NVMECONTROL_H__ #define __NVMECONTROL_H__
#include <sys/linker_set.h> #include <sys/linker_set.h>
#include <sys/queue.h>
#include <dev/nvme/nvme.h> #include <dev/nvme/nvme.h>
struct nvme_function; struct nvme_function;
@ -56,6 +57,7 @@ struct nvme_function {
typedef void (*print_fn_t)(const struct nvme_controller_data *cdata, void *buf, uint32_t size); typedef void (*print_fn_t)(const struct nvme_controller_data *cdata, void *buf, uint32_t size);
struct logpage_function { struct logpage_function {
SLIST_ENTRY(logpage_function) link;
uint8_t log_page; uint8_t log_page;
const char *vendor; const char *vendor;
const char *name; const char *name;
@ -64,7 +66,6 @@ struct logpage_function {
}; };
#define NVME_LOGPAGESET(sym) DATA_SET(NVME_SETNAME(logpage), sym)
#define NVME_LOGPAGE(unique, lp, vend, nam, fn, sz) \ #define NVME_LOGPAGE(unique, lp, vend, nam, fn, sz) \
static struct logpage_function unique ## _lpf = { \ static struct logpage_function unique ## _lpf = { \
.log_page = lp, \ .log_page = lp, \
@ -73,10 +74,8 @@ struct logpage_function {
.print_fn = fn, \ .print_fn = fn, \
.size = sz, \ .size = sz, \
} ; \ } ; \
NVME_LOGPAGESET(unique ## _lpf) static void logpage_reg_##unique(void) __attribute__((constructor)); \
#define NVME_LOGPAGE_BEGIN SET_BEGIN(NVME_SETNAME(logpage)) static void logpage_reg_##unique(void) { logpage_register(&unique##_lpf); }
#define NVME_LOGPAGE_LIMIT SET_LIMIT(NVME_SETNAME(logpage))
#define NVME_LOGPAGE_DECLARE(t) SET_DECLARE(NVME_SETNAME(logpage), t)
#define DEFAULT_SIZE (4096) #define DEFAULT_SIZE (4096)
struct kv_name { struct kv_name {
@ -87,7 +86,7 @@ struct kv_name {
const char *kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key); const char *kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key);
NVME_CMD_DECLARE(top, struct nvme_function); NVME_CMD_DECLARE(top, struct nvme_function);
NVME_LOGPAGE_DECLARE(struct logpage_function); void logpage_register(struct logpage_function *p);
struct set_concat { struct set_concat {
void **begin; void **begin;
@ -105,7 +104,6 @@ void add_to_ ## set(t **b, t **e) \
#define SET_CONCAT_DECL(set, t) \ #define SET_CONCAT_DECL(set, t) \
void add_to_ ## set(t **b, t **e) void add_to_ ## set(t **b, t **e)
SET_CONCAT_DECL(top, struct nvme_function); SET_CONCAT_DECL(top, struct nvme_function);
SET_CONCAT_DECL(logpage, struct logpage_function);
#define NVME_CTRLR_PREFIX "nvme" #define NVME_CTRLR_PREFIX "nvme"
#define NVME_NS_PREFIX "ns" #define NVME_NS_PREFIX "ns"