From e9c310a3251352e7257d5204797a4e970d82dfe0 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Jun 2025 14:09:45 +0200 Subject: [PATCH] tree: filter tree after scan has completed The tree structure is not completely connected when the filter function is called. E.g. a controller might not yet have the namespace object associated. Thus, run the filter function after it has fully created and updated, allowing the filter function to inspect the objects with everything correctly setup. Signed-off-by: Daniel Wagner --- src/nvme/tree.c | 115 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 37 deletions(-) diff --git a/src/nvme/tree.c b/src/nvme/tree.c index b27058492..fc3467120 100644 --- a/src/nvme/tree.c +++ b/src/nvme/tree.c @@ -66,11 +66,9 @@ static struct nvme_host *default_host; static void __nvme_free_host(nvme_host_t h); static void __nvme_free_ctrl(nvme_ctrl_t c); static int nvme_subsystem_scan_namespace(nvme_root_t r, - struct nvme_subsystem *s, char *name, - nvme_scan_filter_t f, void *f_args); + struct nvme_subsystem *s, char *name); static int nvme_init_subsystem(nvme_subsystem_t s, const char *name); -static int nvme_scan_subsystem(nvme_root_t r, const char *name, - nvme_scan_filter_t f, void *f_args); +static int nvme_scan_subsystem(nvme_root_t r, const char *name); static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c, char *name); static int nvme_ctrl_scan_path(nvme_root_t r, struct nvme_ctrl *c, char *name); @@ -219,6 +217,68 @@ nvme_host_t nvme_default_host(nvme_root_t r) return h; } +static void nvme_filter_subsystem(nvme_root_t r, nvme_subsystem_t s, + nvme_scan_filter_t f, void *f_args) +{ + if (f(s, NULL, NULL, f_args)) + return; + + nvme_msg(r, LOG_DEBUG, "filter out subsystem %s\n", + nvme_subsystem_get_name(s)); + nvme_free_subsystem(s); +} + +static void nvme_filter_ns(nvme_root_t r, nvme_ns_t n, + nvme_scan_filter_t f, void *f_args) +{ + if (f(NULL, NULL, n, f_args)) + return; + + nvme_msg(r, LOG_DEBUG, "filter out namespace %s\n", + nvme_ns_get_name(n)); + nvme_free_ns(n); +} + +static void nvme_filter_ctrl(nvme_root_t r, nvme_ctrl_t c, + nvme_scan_filter_t f, void *f_args) +{ + if (f(NULL, c, NULL, f_args)) + return; + + nvme_msg(r, LOG_DEBUG, "filter out controller %s\n", + nvme_ctrl_get_name(c)); + nvme_free_ctrl(c); +} + +static void nvme_filter_tree(nvme_root_t r, nvme_scan_filter_t f, void *f_args) +{ + nvme_host_t h, _h; + nvme_subsystem_t s, _s; + nvme_ns_t n, _n; + nvme_path_t p, _p; + nvme_ctrl_t c, _c; + + if (!f) + return; + + nvme_for_each_host_safe(r, h, _h) { + nvme_for_each_subsystem_safe(h, s, _s) { + nvme_subsystem_for_each_ctrl_safe(s, c, _c) + nvme_filter_ctrl(r, c, f, f_args); + + nvme_subsystem_for_each_ns_safe(s, n, _n) { + nvme_namespace_for_each_path_safe(n, p, _p) { + nvme_filter_ctrl(r, nvme_path_get_ctrl(p), + f, f_args); + } + nvme_filter_ns(r, n, f, f_args); + } + + nvme_filter_subsystem(r, s, f, f_args); + } + } +} + int nvme_scan_topology(struct nvme_root *r, nvme_scan_filter_t f, void *f_args) { _cleanup_dirents_ struct dirents subsys = {}, ctrls = {}; @@ -241,11 +301,6 @@ int nvme_scan_topology(struct nvme_root *r, nvme_scan_filter_t f, void *f_args) ctrls.ents[i]->d_name, strerror(errno)); continue; } - if ((f) && !f(NULL, c, NULL, f_args)) { - nvme_msg(r, LOG_DEBUG, "filter out controller %s\n", - ctrls.ents[i]->d_name); - nvme_free_ctrl(c); - } } subsys.num = nvme_scan_subsystems(&subsys.ents); @@ -256,8 +311,7 @@ int nvme_scan_topology(struct nvme_root *r, nvme_scan_filter_t f, void *f_args) } for (i = 0; i < subsys.num; i++) { - ret = nvme_scan_subsystem( - r, subsys.ents[i]->d_name, f, f_args); + ret = nvme_scan_subsystem(r, subsys.ents[i]->d_name); if (ret < 0) { nvme_msg(r, LOG_DEBUG, "failed to scan subsystem %s: %s\n", @@ -265,6 +319,12 @@ int nvme_scan_topology(struct nvme_root *r, nvme_scan_filter_t f, void *f_args) } } + /* + * Filter the tree after it has been fully populated and + * updated + */ + nvme_filter_tree(r, f, f_args); + return 0; } @@ -752,8 +812,7 @@ struct nvme_host *nvme_lookup_host(nvme_root_t r, const char *hostnqn, return h; } -static int nvme_subsystem_scan_namespaces(nvme_root_t r, nvme_subsystem_t s, - nvme_scan_filter_t f, void *f_args) +static int nvme_subsystem_scan_namespaces(nvme_root_t r, nvme_subsystem_t s) { _cleanup_dirents_ struct dirents namespaces = {}; int i, ret; @@ -774,7 +833,7 @@ static int nvme_subsystem_scan_namespaces(nvme_root_t r, nvme_subsystem_t s, for (i = 0; i < namespaces.num; i++) { ret = nvme_subsystem_scan_namespace(r, s, - namespaces.ents[i]->d_name, f, f_args); + namespaces.ents[i]->d_name); if (ret < 0) nvme_msg(r, LOG_DEBUG, "failed to scan namespace %s: %s\n", @@ -812,20 +871,7 @@ static int nvme_init_subsystem(nvme_subsystem_t s, const char *name) return 0; } -static bool __nvme_scan_subsystem(struct nvme_root *r, nvme_subsystem_t s, - nvme_scan_filter_t f, void *f_args) -{ - if (f && !f(s, NULL, NULL, f_args)) { - nvme_msg(r, LOG_DEBUG, "filter out subsystem %s\n", s->name); - __nvme_free_subsystem(s); - return false; - } - nvme_subsystem_scan_namespaces(r, s, f, f_args); - return true; -} - -static int nvme_scan_subsystem(struct nvme_root *r, const char *name, - nvme_scan_filter_t f, void *f_args) +static int nvme_scan_subsystem(struct nvme_root *r, const char *name) { struct nvme_subsystem *s = NULL, *_s; _cleanup_free_ char *path = NULL, *subsysnqn = NULL; @@ -853,7 +899,7 @@ static int nvme_scan_subsystem(struct nvme_root *r, const char *name, continue; if (strcmp(_s->name, name)) continue; - if (!__nvme_scan_subsystem(r, _s, f, f_args)) { + if (!nvme_subsystem_scan_namespaces(r, _s)) { errno = EINVAL; return -1; } @@ -874,7 +920,7 @@ static int nvme_scan_subsystem(struct nvme_root *r, const char *name, errno = ENOMEM; return -1; } - if (!__nvme_scan_subsystem(r, s, f, f_args)) { + if (!nvme_subsystem_scan_namespaces(r, s)) { errno = EINVAL; return -1; } @@ -2276,7 +2322,7 @@ void nvme_rescan_ctrl(struct nvme_ctrl *c) return; nvme_ctrl_scan_namespaces(r, c); nvme_ctrl_scan_paths(r, c); - nvme_subsystem_scan_namespaces(r, c->s, NULL, NULL); + nvme_subsystem_scan_namespaces(r, c->s); } static int nvme_bytes_to_lba(nvme_ns_t n, off_t offset, size_t count, @@ -2983,7 +3029,7 @@ static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c, } static int nvme_subsystem_scan_namespace(nvme_root_t r, nvme_subsystem_t s, - char *name, nvme_scan_filter_t f, void *f_args) + char *name) { struct nvme_ns *n, *_n, *__n; @@ -2994,11 +3040,6 @@ static int nvme_subsystem_scan_namespace(nvme_root_t r, nvme_subsystem_t s, nvme_msg(r, LOG_DEBUG, "failed to scan namespace %s\n", name); return -1; } - if (f && !f(NULL, NULL, n, f_args)) { - nvme_msg(r, LOG_DEBUG, "filter out namespace %s\n", name); - __nvme_free_ns(n); - return 0; - } nvme_subsystem_for_each_ns_safe(s, _n, __n) { struct nvme_path *p, *_p;