diff --git a/plugins/micron/micron-utils-linux.c b/plugins/micron/micron-utils-linux.c index 267ee60b37..a413961bd0 100644 --- a/plugins/micron/micron-utils-linux.c +++ b/plugins/micron/micron-utils-linux.c @@ -25,6 +25,7 @@ #include "micron-utils.h" #include "nvme-print.h" #include "src/cleanup.h" +#include "src/global-ctx.h" /* * Validates that a string is a canonical PCI address in the @@ -74,6 +75,7 @@ static int get_pcie_bdf(struct libnvme_transport_handle *hdl, char *bdf, size_t bdf_len) { __cleanup_free char *ctrl_name = micron_get_ctrl_name(hdl); + __cleanup_free char *ctrl_dir = NULL; char path[512]; char target[512]; ssize_t n; @@ -84,11 +86,15 @@ static int get_pcie_bdf(struct libnvme_transport_handle *hdl, if (!ctrl_name) return -EINVAL; + err = nvme_sysfs_ctrl_path(ctrl_name, &ctrl_dir); + if (err) + return err; + /* * If possible, use /sys/class/nvme//address (kernel >= 4.13). * On failure, fall back to using the /device symlink. */ - snprintf(path, sizeof(path), "/sys/class/nvme/%s/address", ctrl_name); + snprintf(path, sizeof(path), "%s/address", ctrl_dir); fd = open(path, O_RDONLY); if (fd >= 0) { n = read(fd, target, sizeof(target) - 1); @@ -111,7 +117,7 @@ static int get_pcie_bdf(struct libnvme_transport_handle *hdl, * If unable to use the address file, use the last component of the * /sys/class/nvme//device symlink. */ - snprintf(path, sizeof(path), "/sys/class/nvme/%s/device", ctrl_name); + snprintf(path, sizeof(path), "%s/device", ctrl_dir); n = readlink(path, target, sizeof(target) - 1); if (n < 0) { err = -errno; diff --git a/src/global-ctx.c b/src/global-ctx.c index 43bde9aafc..1859a86a31 100644 --- a/src/global-ctx.c +++ b/src/global-ctx.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -90,6 +91,22 @@ static bool is_true(const char *val) !strncasecmp(val, "enable", 6); } +/* + * Mirror of libnvme's test sysfs root. libnvme keeps its own copy, set + * through libnvme_set_test_sysfs_dir(); this one covers the sysfs + * attributes nvme-cli reads by path rather than through libnvme. + */ +static char test_sysfs_dir[PATH_MAX]; + +int nvme_sysfs_ctrl_path(const char *ctrl_name, char **path) +{ + if (asprintf(path, "%s/sys/class/nvme/%s", test_sysfs_dir, + ctrl_name) < 0) + return -ENOMEM; + + return 0; +} + /* * nvme_apply_option() - apply a single "key=value" pair to @ctx. * @@ -121,6 +138,9 @@ static int nvme_apply_option(struct libnvme_global_ctx *ctx, const char *kv) ret = libnvme_set_test_base_dir(ctx, val); } else if (!strcmp(key, "test-sysfs-dir")) { ret = libnvme_set_test_sysfs_dir(ctx, val); + if (!ret) + snprintf(test_sysfs_dir, sizeof(test_sysfs_dir), "%s", + val); } else { nvme_show_error("--set-options: unknown key '%s'", key); return -EINVAL; diff --git a/src/global-ctx.h b/src/global-ctx.h index 2a31df73e9..404bdf4e66 100644 --- a/src/global-ctx.h +++ b/src/global-ctx.h @@ -31,6 +31,18 @@ int nvme_create_global_ctx_hostnqn(struct libnvme_global_ctx **ctx, int nvme_create_global_ctx(struct libnvme_global_ctx **ctx); +/* + * nvme_sysfs_ctrl_path() - Build the sysfs directory path of a controller + * @ctrl_name: controller name, e.g. "nvme0" + * @path: output path, allocated; caller frees + * + * Prefixed by "--set-options test-sysfs-dir=" when given, so callers reading + * sysfs attributes directly stay consistent with libnvme under test. + * + * Return: 0 on success, -ENOMEM on allocation failure. + */ +int nvme_sysfs_ctrl_path(const char *ctrl_name, char **path); + /* * parse_and_open - parses arguments and opens the NVMe device, populating @ctx, @hdl */ diff --git a/src/nvme-pci-ids-linux.c b/src/nvme-pci-ids-linux.c index 159a8b3b0b..69342f6c21 100644 --- a/src/nvme-pci-ids-linux.c +++ b/src/nvme-pci-ids-linux.c @@ -13,6 +13,7 @@ #include +#include "global-ctx.h" #include "nvme-print.h" static int read_pci_attr(const char *dir, const char *attr, __u32 *out) @@ -61,10 +62,7 @@ static int read_pci_attr(const char *dir, const char *attr, __u32 *out) int __nvme_get_sysfs_dir(__attribute__((__unused__)) struct libnvme_global_ctx *ctx, const char *ctrl_name, char **sysfs_dir) { - if (asprintf(sysfs_dir, "/sys/class/nvme/%s", ctrl_name) < 0) - return -ENOMEM; - - return 0; + return nvme_sysfs_ctrl_path(ctrl_name, sysfs_dir); } int __nvme_get_pci_ids(const char *sysfs_dir,