Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142826833
D18455.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D18455.diff
View Options
Index: head/etc/mtree/BSD.root.dist
===================================================================
--- head/etc/mtree/BSD.root.dist
+++ head/etc/mtree/BSD.root.dist
@@ -88,6 +88,8 @@
..
geom
..
+ nvmecontrol
+ ..
..
libexec
resolvconf
Index: head/sbin/nvmecontrol/Makefile
===================================================================
--- head/sbin/nvmecontrol/Makefile
+++ head/sbin/nvmecontrol/Makefile
@@ -6,6 +6,7 @@
perftest.c reset.c ns.c nvme_util.c power.c nc_util.c
SRCS+= wdc.c intel.c
MAN= nvmecontrol.8
+LDFLAGS+= -rdynamic
.PATH: ${SRCTOP}/sys/dev/nvme
Index: head/sbin/nvmecontrol/logpage.c
===================================================================
--- head/sbin/nvmecontrol/logpage.c
+++ head/sbin/nvmecontrol/logpage.c
@@ -48,13 +48,13 @@
#include "nvmecontrol.h"
-SET_DECLARE(logpage, struct logpage_function);
-
#define LOGPAGE_USAGE \
"logpage <-p page_id> [-b] [-v vendor] [-x] <controller id|namespace id>\n" \
#define MAX_FW_SLOTS (7)
+SET_CONCAT_DEF(logpage, struct logpage_function);
+
const char *
kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key)
{
@@ -332,7 +332,7 @@
fprintf(stderr, "\n");
fprintf(stderr, "%-8s %-10s %s\n", "Page", "Vendor","Page Name");
fprintf(stderr, "-------- ---------- ----------\n");
- for (f = SET_BEGIN(logpage); f < SET_LIMIT(logpage); f++) {
+ for (f = logpage_begin(); f < logpage_limit(); f++) {
v = (*f)->vendor == NULL ? "-" : (*f)->vendor;
fprintf(stderr, "0x%02x %-10s %s\n", (*f)->log_page, v, (*f)->name);
}
@@ -438,7 +438,7 @@
* the page is vendor specific, don't match the print function
* unless the vendors match.
*/
- for (f = SET_BEGIN(logpage); f < SET_LIMIT(logpage); f++) {
+ for (f = logpage_begin(); f < logpage_limit(); f++) {
if ((*f)->vendor != NULL && vendor != NULL &&
strcmp((*f)->vendor, vendor) != 0)
continue;
Index: head/sbin/nvmecontrol/ns.c
===================================================================
--- head/sbin/nvmecontrol/ns.c
+++ head/sbin/nvmecontrol/ns.c
@@ -41,7 +41,7 @@
#include "nvmecontrol.h"
-SET_DECLARE(ns, struct nvme_function);
+NVME_CMD_DECLARE(ns, struct nvme_function);
#define NS_USAGE \
"ns (create|delete|attach|detach)\n"
Index: head/sbin/nvmecontrol/nvmecontrol.h
===================================================================
--- head/sbin/nvmecontrol/nvmecontrol.h
+++ head/sbin/nvmecontrol/nvmecontrol.h
@@ -43,11 +43,15 @@
const char *usage;
};
-#define NVME_CMDSET(set, sym) DATA_SET(set, sym)
+#define NVME_SETNAME(set) set
+#define NVME_CMDSET(set, sym) DATA_SET(NVME_SETNAME(set), sym)
#define NVME_COMMAND(set, nam, function, usage_str) \
static struct nvme_function function ## _nvme_cmd = \
{ .name = #nam, .fn = function, .usage = usage_str }; \
NVME_CMDSET(set, function ## _nvme_cmd)
+#define NVME_CMD_BEGIN(set) SET_BEGIN(NVME_SETNAME(set))
+#define NVME_CMD_LIMIT(set) SET_LIMIT(NVME_SETNAME(set))
+#define NVME_CMD_DECLARE(set, t) SET_DECLARE(NVME_SETNAME(set), t)
typedef void (*print_fn_t)(const struct nvme_controller_data *cdata, void *buf, uint32_t size);
@@ -59,7 +63,8 @@
size_t size;
};
-#define NVME_LOGPAGESET(sym) DATA_SET(logpage, sym)
+
+#define NVME_LOGPAGESET(sym) DATA_SET(NVME_SETNAME(logpage), sym)
#define NVME_LOGPAGE(unique, lp, vend, nam, fn, sz) \
static struct logpage_function unique ## _lpf = { \
.log_page = lp, \
@@ -69,6 +74,9 @@
.size = sz, \
} ; \
NVME_LOGPAGESET(unique ## _lpf)
+#define NVME_LOGPAGE_BEGIN SET_BEGIN(NVME_SETNAME(logpage))
+#define NVME_LOGPAGE_LIMIT SET_LIMIT(NVME_SETNAME(logpage))
+#define NVME_LOGPAGE_DECLARE(t) SET_DECLARE(NVME_SETNAME(logpage), t)
#define DEFAULT_SIZE (4096)
struct kv_name {
@@ -78,6 +86,27 @@
const char *kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key);
+NVME_CMD_DECLARE(top, struct nvme_function);
+NVME_LOGPAGE_DECLARE(struct logpage_function);
+
+struct set_concat {
+ void **begin;
+ void **limit;
+};
+void set_concat_add(struct set_concat *m, void *begin, void *end);
+#define SET_CONCAT_DEF(set, t) \
+static struct set_concat set ## _concat; \
+static inline t **set ## _begin() { return ((t **)set ## _concat.begin); } \
+static inline t **set ## _limit() { return ((t **)set ## _concat.limit); } \
+void add_to_ ## set(t **b, t **e) \
+{ \
+ set_concat_add(&set ## _concat, b, e); \
+}
+#define SET_CONCAT_DECL(set, t) \
+ void add_to_ ## set(t **b, t **e)
+SET_CONCAT_DECL(top, struct nvme_function);
+SET_CONCAT_DECL(logpage, struct logpage_function);
+
#define NVME_CTRLR_PREFIX "nvme"
#define NVME_NS_PREFIX "ns"
@@ -95,7 +124,7 @@
struct nvme_function **tbl_limit);
#define DISPATCH(argc, argv, set) \
- dispatch_set(argc, argv, SET_BEGIN(set), SET_LIMIT(set))
+ dispatch_set(argc, argv, NVME_CMD_BEGIN(set), NVME_CMD_LIMIT(set))
/* Utility Routines */
/*
Index: head/sbin/nvmecontrol/nvmecontrol.8
===================================================================
--- head/sbin/nvmecontrol/nvmecontrol.8
+++ head/sbin/nvmecontrol/nvmecontrol.8
@@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 12, 2018
+.Dd December 7, 2018
.Dt NVMECONTROL 8
.Os
.Sh NAME
@@ -230,6 +230,19 @@
.Dl nvmecontrol power nvme0
.Pp
Get the current power mode.
+.Sh DYNAMIC LOADING
+The directories
+.Pa /libexec/nvmecontrol
+and
+.Pa /usr/local/libexec/nvmecontrol
+are scanned for any .so files.
+These files are loaded.
+The members of the
+.Va top
+linker set are added to the top-level commands.
+The members of the
+.Va logpage
+linker set are added to the logpage parsers.
.Sh HISTORY
The
.Nm
Index: head/sbin/nvmecontrol/nvmecontrol.c
===================================================================
--- head/sbin/nvmecontrol/nvmecontrol.c
+++ head/sbin/nvmecontrol/nvmecontrol.c
@@ -34,6 +34,8 @@
#include <sys/stat.h>
#include <ctype.h>
+#include <dlfcn.h>
+#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -47,7 +49,7 @@
#include "nvmecontrol.h"
-SET_DECLARE(top, struct nvme_function);
+SET_CONCAT_DEF(top, struct nvme_function);
static void
print_usage(const struct nvme_function *f)
@@ -116,6 +118,32 @@
gen_usage_set(tbl, tbl_limit);
}
+void
+set_concat_add(struct set_concat *m, void *b, void *e)
+{
+ void **bp, **ep;
+ int add_n, cur_n;
+
+ if (b == NULL)
+ return;
+ /*
+ * Args are really pointers to arrays of pointers, but C's
+ * casting rules kinda suck since you can't directly cast
+ * struct foo ** to a void **.
+ */
+ bp = (void **)b;
+ ep = (void **)e;
+ add_n = ep - bp;
+ cur_n = 0;
+ if (m->begin != NULL)
+ cur_n = m->limit - m->begin;
+ m->begin = reallocarray(m->begin, cur_n + add_n, sizeof(void *));
+ if (m->begin == NULL)
+ err(1, "expanding concat set");
+ memcpy(m->begin + cur_n, bp, add_n * sizeof(void *));
+ m->limit = m->begin + cur_n + add_n;
+}
+
static void
print_bytes(void *data, uint32_t length)
{
@@ -260,14 +288,64 @@
snprintf(ctrlr_str, nsloc - ns_str + 1, "%s", ns_str);
}
+/*
+ * Loads all the .so's from the specified directory.
+ */
+static void
+load_dir(const char *dir)
+{
+ DIR *d;
+ struct dirent *dent;
+ char *path = NULL;
+ void *h;
+
+ d = opendir(dir);
+ if (d == NULL)
+ return;
+ for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
+ if (strcmp(".so", dent->d_name + dent->d_namlen - 3) != 0)
+ continue;
+ asprintf(&path, "%s/%s", dir, dent->d_name);
+ if (path == NULL)
+ err(1, "Can't malloc for path, giving up.");
+ if ((h = dlopen(path, RTLD_NOW | RTLD_GLOBAL)) == NULL)
+ warnx("Can't load %s: %s", path, dlerror());
+ else {
+ /*
+ * Add in the top (for cli commands) and logpage (for
+ * logpage parsing) linker sets. We have to do this by
+ * hand because linker sets aren't automatically merged.
+ */
+ void *begin, *limit;
+ begin = dlsym(h, "__start_set_top");
+ limit = dlsym(h, "__stop_set_top");
+ if (begin)
+ add_to_top(begin, limit);
+ begin = dlsym(h, "__start_set_logpage");
+ limit = dlsym(h, "__stop_set_logpage");
+ if (begin)
+ add_to_logpage(begin, limit);
+ }
+ free(path);
+ path = NULL;
+ }
+ closedir(d);
+}
+
int
main(int argc, char *argv[])
{
+ 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("/usr/local/lib/nvmecontrol");
+
if (argc < 2)
- gen_usage_set(SET_BEGIN(top), SET_LIMIT(top));
+ gen_usage_set(top_begin(), top_limit());
- DISPATCH(argc, argv, top);
+ dispatch_set(argc, argv, top_begin(), top_limit());
return (0);
}
Index: head/sbin/nvmecontrol/wdc.c
===================================================================
--- head/sbin/nvmecontrol/wdc.c
+++ head/sbin/nvmecontrol/wdc.c
@@ -45,7 +45,7 @@
#define WDC_USAGE \
"wdc (cap-diag)\n"
-SET_DECLARE(wdc, struct nvme_function);
+NVME_CMD_DECLARE(wdc, struct nvme_function);
#define WDC_NVME_TOC_SIZE 8
Index: head/share/man/man7/hier.7
===================================================================
--- head/share/man/man7/hier.7
+++ head/share/man/man7/hier.7
@@ -152,6 +152,10 @@
class-specific libraries for the
.Xr geom 8
utility
+.It Pa nvmecontrol/
+vendor-specific libraries to extend the
+.Xr nvmecontrol 8
+utility
.El
.It Pa /libexec/
critical system utilities needed for binaries in
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 24, 11:18 PM (1 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27915224
Default Alt Text
D18455.diff (9 KB)
Attached To
Mode
D18455: Dynamically load .so modules to expand functionality
Attached
Detach File
Event Timeline
Log In to Comment