On Mon, 16 Nov 2020 15:44:37 -0500 Steven Rostedt <rostedt@xxxxxxxxxxx> wrote: > If you use a stub function, it shouldn't affect anything. And the worse > that would happen is that you have a slight overhead of calling the stub > until you can properly remove the callback. Something like this: (haven't compiled it yet, I'm about to though). -- Steve diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 3f659f855074..8eab40f9d388 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -53,10 +53,16 @@ struct tp_probes { struct tracepoint_func probes[]; }; -static inline void *allocate_probes(int count) +/* Called in removal of a func but failed to allocate a new tp_funcs */ +static void tp_stub_func(void) +{ + return; +} + +static inline void *allocate_probes(int count, gfp_t extra_flags) { struct tp_probes *p = kmalloc(struct_size(p, probes, count), - GFP_KERNEL); + GFP_KERNEL | extra_flags); return p == NULL ? NULL : p->probes; } @@ -150,7 +156,7 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, } } /* + 2 : one for new probe, one for NULL func */ - new = allocate_probes(nr_probes + 2); + new = allocate_probes(nr_probes + 2, 0); if (new == NULL) return ERR_PTR(-ENOMEM); if (old) { @@ -188,8 +194,9 @@ static void *func_remove(struct tracepoint_func **funcs, /* (N -> M), (N > 1, M >= 0) probes */ if (tp_func->func) { for (nr_probes = 0; old[nr_probes].func; nr_probes++) { - if (old[nr_probes].func == tp_func->func && - old[nr_probes].data == tp_func->data) + if ((old[nr_probes].func == tp_func->func && + old[nr_probes].data == tp_func->data) || + old[nr_probes].func == tp_stub_func) nr_del++; } } @@ -207,15 +214,20 @@ static void *func_remove(struct tracepoint_func **funcs, int j = 0; /* N -> M, (N > 1, M > 0) */ /* + 1 for NULL */ - new = allocate_probes(nr_probes - nr_del + 1); - if (new == NULL) - return ERR_PTR(-ENOMEM); - for (i = 0; old[i].func; i++) - if (old[i].func != tp_func->func - || old[i].data != tp_func->data) - new[j++] = old[i]; - new[nr_probes - nr_del].func = NULL; - *funcs = new; + new = allocate_probes(nr_probes - nr_del + 1, __GFP_NOFAIL); + if (new) { + for (i = 0; old[i].func; i++) + if (old[i].func != tp_func->func + || old[i].data != tp_func->data) + new[j++] = old[i]; + new[nr_probes - nr_del].func = NULL; + } else { + for (i = 0; old[i].func; i++) + if (old[i].func == tp_func->func && + old[i].data == tp_func->data) + old[i].func = tp_stub_func; + } + *funcs = old; } debug_print_probes(*funcs); return old; @@ -300,6 +312,10 @@ static int tracepoint_remove_func(struct tracepoint *tp, return PTR_ERR(old); } + if (tp_funcs == old) + /* Failed allocating new tp_funcs, replaced func with stub */ + return 0; + if (!tp_funcs) { /* Removed last function */ if (tp->unregfunc && static_key_enabled(&tp->key))