tracepoints: Code clean up

Restructure the code a bit to make it simpler, fix some formatting problems
and add READ_ONCE/WRITE_ONCE to make sure there's no compiler load/store
tearing to the variables that can be accessed across CPUs.

Started with Mathieu Desnoyers's patch:

  Link: https://lore.kernel.org/lkml/20210203175741.20665-1-mathieu.desnoyers@efficios.com/

And will keep his signature, but I will take the responsibility of this
being correct, and keep the authorship.

Link: https://lkml.kernel.org/r/20210204143004.61126582@gandalf.local.home

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
Steven Rostedt (VMware) 2021-02-04 14:30:04 -05:00
parent d9a1be1be3
commit 7211f0a257
2 changed files with 36 additions and 57 deletions

View File

@ -305,7 +305,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
rcu_dereference_raw((&__tracepoint_##_name)->funcs); \
if (it_func_ptr) { \
do { \
it_func = (it_func_ptr)->func; \
it_func = READ_ONCE((it_func_ptr)->func); \
__data = (it_func_ptr)->data; \
((void(*)(void *, proto))(it_func))(__data, args); \
} while ((++it_func_ptr)->func); \

View File

@ -136,9 +136,9 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func,
int prio)
{
struct tracepoint_func *old, *new;
int nr_probes = 0;
int stub_funcs = 0;
int pos = -1;
int iter_probes; /* Iterate over old probe array. */
int nr_probes = 0; /* Counter for probes */
int pos = -1; /* Insertion position into new array */
if (WARN_ON(!tp_func->func))
return ERR_PTR(-EINVAL);
@ -147,54 +147,38 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func,
old = *funcs;
if (old) {
/* (N -> N+1), (N != 0, 1) probes */
for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
/* Insert before probes of lower priority */
if (pos < 0 && old[nr_probes].prio < prio)
pos = nr_probes;
if (old[nr_probes].func == tp_func->func &&
old[nr_probes].data == tp_func->data)
for (iter_probes = 0; old[iter_probes].func; iter_probes++) {
if (old[iter_probes].func == tp_stub_func)
continue; /* Skip stub functions. */
if (old[iter_probes].func == tp_func->func &&
old[iter_probes].data == tp_func->data)
return ERR_PTR(-EEXIST);
if (old[nr_probes].func == tp_stub_func)
stub_funcs++;
nr_probes++;
}
}
/* + 2 : one for new probe, one for NULL func - stub functions */
new = allocate_probes(nr_probes + 2 - stub_funcs);
/* + 2 : one for new probe, one for NULL func */
new = allocate_probes(nr_probes + 2);
if (new == NULL)
return ERR_PTR(-ENOMEM);
if (old) {
if (stub_funcs) {
/* Need to copy one at a time to remove stubs */
int probes = 0;
pos = -1;
for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
if (old[nr_probes].func == tp_stub_func)
continue;
if (pos < 0 && old[nr_probes].prio < prio)
pos = probes++;
new[probes++] = old[nr_probes];
}
nr_probes = probes;
if (pos < 0)
pos = probes;
else
nr_probes--; /* Account for insertion */
} else if (pos < 0) {
pos = nr_probes;
memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
} else {
/* Copy higher priority probes ahead of the new probe */
memcpy(new, old, pos * sizeof(struct tracepoint_func));
/* Copy the rest after it. */
memcpy(new + pos + 1, old + pos,
(nr_probes - pos) * sizeof(struct tracepoint_func));
nr_probes = 0;
for (iter_probes = 0; old[iter_probes].func; iter_probes++) {
if (old[iter_probes].func == tp_stub_func)
continue;
/* Insert before probes of lower priority */
if (pos < 0 && old[iter_probes].prio < prio)
pos = nr_probes++;
new[nr_probes++] = old[iter_probes];
}
} else
if (pos < 0)
pos = nr_probes++;
/* nr_probes now points to the end of the new array */
} else {
pos = 0;
nr_probes = 1; /* must point at end of array */
}
new[pos] = *tp_func;
new[nr_probes + 1].func = NULL;
new[nr_probes].func = NULL;
*funcs = new;
debug_print_probes(*funcs);
return old;
@ -237,11 +221,12 @@ static void *func_remove(struct tracepoint_func **funcs,
/* + 1 for NULL */
new = allocate_probes(nr_probes - nr_del + 1);
if (new) {
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)
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)
new[j++] = old[i];
}
new[nr_probes - nr_del].func = NULL;
*funcs = new;
} else {
@ -249,17 +234,11 @@ static void *func_remove(struct tracepoint_func **funcs,
* Failed to allocate, replace the old function
* with calls to tp_stub_func.
*/
for (i = 0; old[i].func; i++)
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;
/* Set the prio to the next event. */
if (old[i + 1].func)
old[i].prio =
old[i + 1].prio;
else
old[i].prio = -1;
}
old[i].data == tp_func->data)
WRITE_ONCE(old[i].func, tp_stub_func);
}
*funcs = old;
}
}