From c167671b58fc7e1c90d300faabed3b57f3ef7b2e Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Thu, 11 Dec 2025 09:28:53 +0100 Subject: [PATCH] tree: open transport handle for the ns init fallback Older kernels do not expose the sysfs entries the library needs. In this in this case it falls back to use a command to fetch the missing data. Though, the transport handle is not available yet. Open an temporary one. No need to optimize this code path, it is only for older kernels. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/tree.c | 46 +++++++++++++++------- libnvme/src/nvme/tree.h | 3 +- plugins/sandisk/sandisk-utils.c | 2 +- plugins/solidigm/solidigm-get-drive-info.c | 2 +- plugins/wdc/wdc-nvme.c | 2 +- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index c4d5a94b89..25ba7b98d9 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -2677,7 +2677,8 @@ static int parse_attrs(const char *path, struct sysfs_attr_table *tbl, int size) return 0; } -static int nvme_ns_init(const char *path, struct nvme_ns *ns) +static int nvme_ns_init(struct nvme_global_ctx *ctx, const char *path, + struct nvme_ns *ns) { _cleanup_free_ char *attr = NULL; struct stat sb; @@ -2722,20 +2723,32 @@ static int nvme_ns_init(const char *path, struct nvme_ns *ns) return ret; } else { _cleanup_free_ struct nvme_id_ns *id = NULL; + struct nvme_transport_handle *hdl = NULL; + struct nvme_passthru_cmd cmd; + uint8_t flbas; id = __nvme_alloc(sizeof(*ns)); if (!id) return -ENOMEM; - ret = nvme_ns_identify(ns, id); + ret = nvme_open(ctx, ns->name, &hdl); + if (ret) { + nvme_msg(ctx, LOG_ERR, "need root permissions"); + goto close_hdl; + } + + nvme_init_identify_ns(&cmd, nvme_ns_get_nsid(ns), id); + ret = nvme_submit_admin_passthru(hdl, &cmd); if (ret) - return ret; + goto close_hdl; nvme_id_ns_flbas_to_lbaf_inuse(id->flbas, &flbas); ns->lba_count = le64_to_cpu(id->nsze); ns->lba_util = le64_to_cpu(id->nuse); ns->meta_size = le16_to_cpu(id->lbaf[flbas].ms); +close_hdl: + nvme_close(hdl); } return 0; @@ -2755,7 +2768,8 @@ static void nvme_ns_set_generic_name(struct nvme_ns *n, const char *name) n->generic_name = strdup(generic_name); } -int nvme_ns_open(const char *sys_path, const char *name, nvme_ns_t *ns) +int nvme_ns_open(struct nvme_global_ctx *ctx, const char *sys_path, + const char *name, nvme_ns_t *ns) { int ret; struct nvme_ns *n; @@ -2798,7 +2812,7 @@ int nvme_ns_open(const char *sys_path, const char *name, nvme_ns_t *ns) nvme_ns_set_generic_name(n, name); - ret = nvme_ns_init(sys_path, n); + ret = nvme_ns_init(ctx, sys_path, n); if (ret) goto free_ns; @@ -2842,7 +2856,8 @@ static char *nvme_ns_generic_to_blkdev(const char *generic) return strdup(blkdev); } -static int __nvme_scan_namespace(const char *sysfs_dir, const char *name, nvme_ns_t *ns) +static int __nvme_scan_namespace(struct nvme_global_ctx *ctx, + const char *sysfs_dir, const char *name, nvme_ns_t *ns) { _cleanup_free_ char *blkdev = NULL; _cleanup_free_ char *path = NULL; @@ -2857,7 +2872,7 @@ static int __nvme_scan_namespace(const char *sysfs_dir, const char *name, nvme_n if (ret < 0) return -ENOMEM; - ret = nvme_ns_open(path, blkdev, &n); + ret = nvme_ns_open(ctx, path, blkdev, &n); if (ret) return ret; @@ -2868,9 +2883,10 @@ static int __nvme_scan_namespace(const char *sysfs_dir, const char *name, nvme_n return 0; } -int nvme_scan_namespace(const char *name, nvme_ns_t *ns) +int nvme_scan_namespace(struct nvme_global_ctx *ctx, + const char *name, nvme_ns_t *ns) { - return __nvme_scan_namespace(nvme_ns_sysfs_dir(), name, ns); + return __nvme_scan_namespace(ctx, nvme_ns_sysfs_dir(), name, ns); } @@ -2938,8 +2954,8 @@ static void nvme_subsystem_set_ns_path(nvme_subsystem_t s, nvme_ns_t n) } } -static int nvme_ctrl_scan_namespace(struct nvme_global_ctx *ctx, struct nvme_ctrl *c, - char *name) +static int nvme_ctrl_scan_namespace(struct nvme_global_ctx *ctx, + struct nvme_ctrl *c, char *name) { struct nvme_ns *n, *_n, *__n; int ret; @@ -2950,7 +2966,7 @@ static int nvme_ctrl_scan_namespace(struct nvme_global_ctx *ctx, struct nvme_ctr nvme_msg(ctx, LOG_DEBUG, "no subsystem for %s\n", name); return -EINVAL; } - ret = __nvme_scan_namespace(c->sysfs_dir, name, &n); + ret = __nvme_scan_namespace(ctx, c->sysfs_dir, name, &n); if (ret) { nvme_msg(ctx, LOG_DEBUG, "failed to scan namespace %s\n", name); return ret; @@ -2968,15 +2984,15 @@ static int nvme_ctrl_scan_namespace(struct nvme_global_ctx *ctx, struct nvme_ctr return 0; } -static int nvme_subsystem_scan_namespace(struct nvme_global_ctx *ctx, nvme_subsystem_t s, - char *name) +static int nvme_subsystem_scan_namespace(struct nvme_global_ctx *ctx, + nvme_subsystem_t s, char *name) { struct nvme_ns *n, *_n, *__n; int ret; nvme_msg(ctx, LOG_DEBUG, "scan subsystem %s namespace %s\n", s->name, name); - ret = __nvme_scan_namespace(s->sysfs_dir, name, &n); + ret = __nvme_scan_namespace(ctx, s->sysfs_dir, name, &n); if (ret) { nvme_msg(ctx, LOG_DEBUG, "failed to scan namespace %s\n", name); return ret; diff --git a/libnvme/src/nvme/tree.h b/libnvme/src/nvme/tree.h index c1622d3454..fdab9c9b9a 100644 --- a/libnvme/src/nvme/tree.h +++ b/libnvme/src/nvme/tree.h @@ -1564,7 +1564,8 @@ char *nvme_get_path_attr(nvme_path_t p, const char *attr); * * Return: 0 on success or negative error code otherwise */ -int nvme_scan_namespace(const char *name, nvme_ns_t *ns); +int nvme_scan_namespace(struct nvme_global_ctx *ctx, const char *name, + nvme_ns_t *ns); /** * nvme_host_get_hostsymname() - Get the host's symbolic name diff --git a/plugins/sandisk/sandisk-utils.c b/plugins/sandisk/sandisk-utils.c index 2d3a766b4a..1b28f9e1da 100644 --- a/plugins/sandisk/sandisk-utils.c +++ b/plugins/sandisk/sandisk-utils.c @@ -48,7 +48,7 @@ int sndk_get_pci_ids(struct nvme_global_ctx *ctx, struct nvme_transport_handle * nvme_ctrl_get_sysfs_dir(c)); nvme_free_ctrl(c); } else { - ret = nvme_scan_namespace(name, &n); + ret = nvme_scan_namespace(ctx, name, &n); if (!ret) { fprintf(stderr, "Unable to find %s\n", name); return ret; diff --git a/plugins/solidigm/solidigm-get-drive-info.c b/plugins/solidigm/solidigm-get-drive-info.c index f92abfb41d..a8fde387ce 100644 --- a/plugins/solidigm/solidigm-get-drive-info.c +++ b/plugins/solidigm/solidigm-get-drive-info.c @@ -48,7 +48,7 @@ int sldgm_get_drive_info(int argc, char **argv, struct command *acmd, struct plu if (!err) n = nvme_ctrl_first_ns(c); else { - err = nvme_scan_namespace(nvme_transport_handle_get_name(hdl), &n); + err = nvme_scan_namespace(ctx, nvme_transport_handle_get_name(hdl), &n); if (err) { nvme_show_error("solidigm-vs-drive-info: drive missing namespace"); return err; diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index 53a23ec0e7..1935de534c 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -1490,7 +1490,7 @@ static int wdc_get_pci_ids(struct nvme_global_ctx *ctx, struct nvme_transport_ha nvme_ctrl_get_sysfs_dir(c)); nvme_free_ctrl(c); } else { - ret = nvme_scan_namespace(name, &n); + ret = nvme_scan_namespace(ctx, name, &n); if (ret) { fprintf(stderr, "Unable to find %s\n", name); return ret;