Re: [PATCH v18 34/42] dept: add module support for struct dept_event_site and dept_event_site_dep
Byungchul Park <[email protected]>
| Newsgroups | org.kernel.vger.rcu,dev.linux.lists.linux-rt-devel,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-arch,org.kernel.vger.linux-block,org.kernel.vger.linux-doc,org.kernel.vger.linux-ext4,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-i2c,org.kernel.vger.linux-ide,org.kernel.vger.linux-kernel,org.kernel.vger.linux-media,org.kernel.vger.linux-modules,org.kernel.vger.linux-nfs,org.kernel.vger.netdev,org.kernel.vger.rust-for-linux,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On Wed, Jan 07, 2026 at 01:19:00PM +0100, Petr Pavlu wrote: > On 12/5/25 8:18 AM, Byungchul Park wrote: > > struct dept_event_site and struct dept_event_site_dep have been > > introduced to track dependencies between multi event sites for a single > > wait, that will be loaded to data segment. Plus, a custom section, > > '.dept.event_sites', also has been introduced to keep pointers to the > > objects to make sure all the event sites defined exist in code. > > > > dept should work with the section and segment of module. Add the > > support to handle the section and segment properly whenever modules are > > loaded and unloaded. > > > > Signed-off-by: Byungchul Park <[email protected]> > > Below are a few comments from the module loader perspective. > > > --- > > include/linux/dept.h | 14 +++++++ > > include/linux/module.h | 5 +++ > > kernel/dependency/dept.c | 79 +++++++++++++++++++++++++++++++++++----- > > kernel/module/main.c | 15 ++++++++ > > 4 files changed, 103 insertions(+), 10 deletions(-) > > > > diff --git a/include/linux/dept.h b/include/linux/dept.h > > index 44083e6651ab..c796cdceb04e 100644 > > --- a/include/linux/dept.h > > +++ b/include/linux/dept.h > > @@ -166,6 +166,11 @@ struct dept_event_site { > > struct dept_event_site *bfs_parent; > > struct list_head bfs_node; > > > > + /* > > + * for linking all dept_event_site's > > + */ > > + struct list_head all_node; > > + > > /* > > * flag indicating the event is not only declared but also > > * actually used in code > > @@ -182,6 +187,11 @@ struct dept_event_site_dep { > > */ > > struct list_head dep_node; > > struct list_head dep_rev_node; > > + > > + /* > > + * for linking all dept_event_site_dep's > > + */ > > + struct list_head all_node; > > }; > > > > #define DEPT_EVENT_SITE_INITIALIZER(es) \ > > @@ -193,6 +203,7 @@ struct dept_event_site_dep { > > .bfs_gen = 0, \ > > .bfs_parent = NULL, \ > > .bfs_node = LIST_HEAD_INIT((es).bfs_node), \ > > + .all_node = LIST_HEAD_INIT((es).all_node), \ > > .used = false, \ > > } > > > > @@ -202,6 +213,7 @@ struct dept_event_site_dep { > > .recover_site = NULL, \ > > .dep_node = LIST_HEAD_INIT((esd).dep_node), \ > > .dep_rev_node = LIST_HEAD_INIT((esd).dep_rev_node), \ > > + .all_node = LIST_HEAD_INIT((esd).all_node), \ > > } > > > > struct dept_event_site_init { > > @@ -225,6 +237,7 @@ extern void dept_init(void); > > extern void dept_task_init(struct task_struct *t); > > extern void dept_task_exit(struct task_struct *t); > > extern void dept_free_range(void *start, unsigned int sz); > > +extern void dept_mark_event_site_used(void *start, void *end); > > Nit: The coding style recommends not using the extern keyword with > function declarations. > > https://www.kernel.org/doc/html/v6.19-rc4/process/coding-style.html#function-prototypes > > > > > extern void dept_map_init(struct dept_map *m, struct dept_key *k, int sub_u, const char *n); > > extern void dept_map_reinit(struct dept_map *m, struct dept_key *k, int sub_u, const char *n); > > @@ -288,6 +301,7 @@ struct dept_event_site { }; > > #define dept_task_init(t) do { } while (0) > > #define dept_task_exit(t) do { } while (0) > > #define dept_free_range(s, sz) do { } while (0) > > +#define dept_mark_event_site_used(s, e) do { } while (0) > > > > #define dept_map_init(m, k, su, n) do { (void)(n); (void)(k); } while (0) > > #define dept_map_reinit(m, k, su, n) do { (void)(n); (void)(k); } while (0) > > diff --git a/include/linux/module.h b/include/linux/module.h > > index d80c3ea57472..29885ba91951 100644 > > --- a/include/linux/module.h > > +++ b/include/linux/module.h > > @@ -29,6 +29,7 @@ > > #include <linux/srcu.h> > > #include <linux/static_call_types.h> > > #include <linux/dynamic_debug.h> > > +#include <linux/dept.h> > > > > #include <linux/percpu.h> > > #include <asm/module.h> > > @@ -588,6 +589,10 @@ struct module { > > #ifdef CONFIG_DYNAMIC_DEBUG_CORE > > struct _ddebug_info dyndbg_info; > > #endif > > +#ifdef CONFIG_DEPT > > + struct dept_event_site **dept_event_sites; > > + unsigned int num_dept_event_sites; > > +#endif > > } ____cacheline_aligned __randomize_layout; > > #ifndef MODULE_ARCH_INIT > > #define MODULE_ARCH_INIT {} > > My understanding is that entries in the .dept.event_sites section are > added by the dept_event_site_used() macro and they are pointers to the > dept_event_site_init struct, not dept_event_site. > > > diff --git a/kernel/dependency/dept.c b/kernel/dependency/dept.c > > index b14400c4f83b..07d883579269 100644 > > --- a/kernel/dependency/dept.c > > +++ b/kernel/dependency/dept.c > > @@ -984,6 +984,9 @@ static void bfs(void *root, struct bfs_ops *ops, void *in, void **out) > > * event sites. > > */ > > > > +static LIST_HEAD(dept_event_sites); > > +static LIST_HEAD(dept_event_site_deps); > > + > > /* > > * Print all events in the circle. > > */ > > @@ -2043,6 +2046,33 @@ static void del_dep_rcu(struct rcu_head *rh) > > preempt_enable(); > > } > > > > +/* > > + * NOTE: Must be called with dept_lock held. > > + */ > > +static void disconnect_event_site_dep(struct dept_event_site_dep *esd) > > +{ > > + list_del_rcu(&esd->dep_node); > > + list_del_rcu(&esd->dep_rev_node); > > +} > > + > > +/* > > + * NOTE: Must be called with dept_lock held. > > + */ > > +static void disconnect_event_site(struct dept_event_site *es) > > +{ > > + struct dept_event_site_dep *esd, *next_esd; > > + > > + list_for_each_entry_safe(esd, next_esd, &es->dep_head, dep_node) { > > + list_del_rcu(&esd->dep_node); > > + list_del_rcu(&esd->dep_rev_node); > > + } > > + > > + list_for_each_entry_safe(esd, next_esd, &es->dep_rev_head, dep_rev_node) { > > + list_del_rcu(&esd->dep_node); > > + list_del_rcu(&esd->dep_rev_node); > > + } > > +} > > + > > /* > > * NOTE: Must be called with dept_lock held. > > */ > > @@ -2384,6 +2414,8 @@ void dept_free_range(void *start, unsigned int sz) > > { > > struct dept_task *dt = dept_task(); > > struct dept_class *c, *n; > > + struct dept_event_site_dep *esd, *next_esd; > > + struct dept_event_site *es, *next_es; > > unsigned long flags; > > > > if (unlikely(!dept_working())) > > @@ -2405,6 +2437,24 @@ void dept_free_range(void *start, unsigned int sz) > > while (unlikely(!dept_lock())) > > cpu_relax(); > > > > + list_for_each_entry_safe(esd, next_esd, &dept_event_site_deps, all_node) { > > + if (!within((void *)esd, start, sz)) > > + continue; > > + > > + disconnect_event_site_dep(esd); > > + list_del(&esd->all_node); > > + } > > + > > + list_for_each_entry_safe(es, next_es, &dept_event_sites, all_node) { > > + if (!within((void *)es, start, sz) && > > + !within(es->name, start, sz) && > > + !within(es->func_name, start, sz)) > > + continue; > > + > > + disconnect_event_site(es); > > + list_del(&es->all_node); > > + } > > + > > list_for_each_entry_safe(c, n, &dept_classes, all_node) { > > if (!within((void *)c->key, start, sz) && > > !within(c->name, start, sz)) > > @@ -3337,6 +3387,7 @@ void __dept_recover_event(struct dept_event_site_dep *esd, > > > > list_add(&esd->dep_node, &es->dep_head); > > list_add(&esd->dep_rev_node, &rs->dep_rev_head); > > + list_add(&esd->all_node, &dept_event_site_deps); > > check_recover_dl_bfs(esd); > > unlock: > > dept_unlock(); > > @@ -3347,6 +3398,23 @@ EXPORT_SYMBOL_GPL(__dept_recover_event); > > > > #define B2KB(B) ((B) / 1024) > > > > +void dept_mark_event_site_used(void *start, void *end) > > Nit: I suggest that dept_mark_event_site_used() take pointers to > dept_event_site_init, which would catch the type mismatch with > module::dept_event_sites. > > > +{ > > + struct dept_event_site_init **evtinitpp; > > + > > + for (evtinitpp = (struct dept_event_site_init **)start; > > + evtinitpp < (struct dept_event_site_init **)end; > > + evtinitpp++) { > > + (*evtinitpp)->evt_site->used = true; > > + (*evtinitpp)->evt_site->func_name = (*evtinitpp)->func_name; > > + list_add(&(*evtinitpp)->evt_site->all_node, &dept_event_sites); > > + > > + pr_info("dept_event_site %s@%s is initialized.\n", > > + (*evtinitpp)->evt_site->name, > > + (*evtinitpp)->evt_site->func_name); > > + } > > +} > > + > > extern char __dept_event_sites_start[], __dept_event_sites_end[]; > > Related to the above, __dept_event_sites_start and > __dept_event_sites_end can already be properly typed here. > > > > > /* > > @@ -3356,20 +3424,11 @@ extern char __dept_event_sites_start[], __dept_event_sites_end[]; > > void __init dept_init(void) > > { > > size_t mem_total = 0; > > - struct dept_event_site_init **evtinitpp; > > > > /* > > * dept recover dependency tracking works from now on. > > */ > > - for (evtinitpp = (struct dept_event_site_init **)__dept_event_sites_start; > > - evtinitpp < (struct dept_event_site_init **)__dept_event_sites_end; > > - evtinitpp++) { > > - (*evtinitpp)->evt_site->used = true; > > - (*evtinitpp)->evt_site->func_name = (*evtinitpp)->func_name; > > - pr_info("dept_event %s@%s is initialized.\n", > > - (*evtinitpp)->evt_site->name, > > - (*evtinitpp)->evt_site->func_name); > > - } > > + dept_mark_event_site_used(__dept_event_sites_start, __dept_event_sites_end); > > dept_recover_ready = true; > > > > local_irq_disable(); > > diff --git a/kernel/module/main.c b/kernel/module/main.c > > index 03ed63f2adf0..82448cdb8ed7 100644 > > --- a/kernel/module/main.c > > +++ b/kernel/module/main.c > > @@ -2720,6 +2720,11 @@ static int find_module_sections(struct module *mod, struct load_info *info) > > &mod->dyndbg_info.num_classes); > > #endif > > > > +#ifdef CONFIG_DEPT > > + mod->dept_event_sites = section_objs(info, ".dept.event_sites", > > + sizeof(*mod->dept_event_sites), > > + &mod->num_dept_event_sites); > > +#endif > > return 0; > > } > > > > @@ -3346,6 +3351,14 @@ static int early_mod_check(struct load_info *info, int flags) > > return err; > > } > > > > +static void dept_mark_event_site_used_module(struct module *mod) > > +{ > > +#ifdef CONFIG_DEPT > > + dept_mark_event_site_used(mod->dept_event_sites, > > + mod->dept_event_sites + mod->num_dept_event_sites); > > +#endif > > +} > > + > > It seems to me that the .dept.event_sites section can be discarded after > the module is initialized. In this case, the section should be prefixed > by ".init" and its address can be obtained at the point of use in > dept_mark_event_site_used_module(), without needing to store it inside > the module struct. > > Additionally, what is the reason that the dept_event_site_init data is > not stored in the .dept.event_sites section directly and it requires > a level of indirection? > > In general, for my own understanding, I also wonder whether the check to > determine that a dept_event_site is used needs to be done at runtime, or > if it could be done at build time by objtool/modpost. I appreciate your feedback and it was so helpful, but I decided to defer the part supporting recover events tracking - 33/42 ~ 35/42 in this series - to a follow-up patch later with the feedback applied, as it unnecessarily complicates the initial DEPT patchset and significantly increases the review burden. Byungchul > > /* > > * Allocate and load the module: note that size of section 0 is always > > * zero, and we rely on this for optional sections. > > @@ -3508,6 +3521,8 @@ static int load_module(struct load_info *info, const char __user *uargs, > > /* Done! */ > > trace_module_load(mod); > > > > + dept_mark_event_site_used_module(mod); > > + > > return do_init_module(mod); > > > > sysfs_cleanup: > > -- > Thanks, > Petr