From: Mathieu Desnoyers Date: Thu, 2 Apr 2015 19:26:56 +0000 (-0400) Subject: Implement list.h wrapper for hlist in older kernels X-Git-Tag: v2.7.0-rc1~78 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=f934e302d314d76563484f31caed56ad680eb17b;p=lttng-modules.git Implement list.h wrapper for hlist in older kernels The hlist API has changed between kernels 3.2 and recent (e.g. 3.19.2) kernels. Implement a wrapper header to implement the macros missing from older kernels that we support. Signed-off-by: Mathieu Desnoyers --- diff --git a/LICENSE b/LICENSE index c416f3ff..2453f716 100644 --- a/LICENSE +++ b/LICENSE @@ -17,6 +17,7 @@ lib/ringbuffer/ring_buffer_splice.c lib/ringbuffer/ring_buffer_mmap.c instrumentation/events/mainline/*.h instrumentation/events/lttng-modules/*.h +wrapper/list.h * MIT-style license diff --git a/lttng-events.c b/lttng-events.c index d7efd425..7055c3ed 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -21,7 +21,6 @@ */ #include -#include #include #include #include @@ -36,6 +35,7 @@ #include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ #include "wrapper/random.h" #include "wrapper/tracepoint.h" +#include "wrapper/list.h" #include "lttng-kernel-version.h" #include "lttng-events.h" #include "lttng-tracer.h" @@ -678,7 +678,7 @@ void *pid_list_start(struct seq_file *m, loff_t *pos) for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { struct hlist_head *head = &lpf->pid_hash[i]; - hlist_for_each_entry(e, head, hlist) { + lttng_hlist_for_each_entry(e, head, hlist) { if (iter++ >= *pos) return e; } @@ -709,7 +709,7 @@ void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos) for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { struct hlist_head *head = &lpf->pid_hash[i]; - hlist_for_each_entry(e, head, hlist) { + lttng_hlist_for_each_entry(e, head, hlist) { if (iter++ >= *ppos) return e; } diff --git a/lttng-tracepoint.c b/lttng-tracepoint.c index 13f9c247..f8a9cedc 100644 --- a/lttng-tracepoint.c +++ b/lttng-tracepoint.c @@ -20,7 +20,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include @@ -30,6 +29,7 @@ #include #include "lttng-tracepoint.h" +#include "wrapper/list.h" /* * Protect the tracepoint table. lttng_tracepoint_mutex nests within @@ -119,7 +119,7 @@ struct tracepoint_entry *get_tracepoint(const char *name) u32 hash = jhash(name, strlen(name), 0); head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)]; - hlist_for_each_entry(e, head, hlist) { + lttng_hlist_for_each_entry(e, head, hlist) { if (!strcmp(name, e->name)) return e; } @@ -139,7 +139,7 @@ struct tracepoint_entry *add_tracepoint(const char *name) u32 hash = jhash(name, name_len - 1, 0); head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)]; - hlist_for_each_entry(e, head, hlist) { + lttng_hlist_for_each_entry(e, head, hlist) { if (!strcmp(name, e->name)) { printk(KERN_NOTICE "tracepoint %s busy\n", name); diff --git a/lttng-tracker-pid.c b/lttng-tracker-pid.c index a62ec4e4..eeee9d55 100644 --- a/lttng-tracker-pid.c +++ b/lttng-tracker-pid.c @@ -25,11 +25,11 @@ #include #include #include -#include #include #include #include "wrapper/tracepoint.h" +#include "wrapper/list.h" #include "lttng-events.h" /* @@ -59,7 +59,7 @@ bool lttng_pid_tracker_lookup(struct lttng_pid_tracker *lpf, int pid) uint32_t hash = hash_32(pid, 32); head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - hlist_for_each_entry_rcu_notrace(e, head, hlist) { + lttng_hlist_for_each_entry_rcu_notrace(e, head, hlist) { if (pid == e->pid) return 1; /* Found */ } @@ -77,7 +77,7 @@ int lttng_pid_tracker_add(struct lttng_pid_tracker *lpf, int pid) uint32_t hash = hash_32(pid, 32); head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - hlist_for_each_entry(e, head, hlist) { + lttng_hlist_for_each_entry(e, head, hlist) { if (pid == e->pid) return -EEXIST; } @@ -127,7 +127,7 @@ int lttng_pid_tracker_del(struct lttng_pid_tracker *lpf, int pid) * No need of _safe iteration, because we stop traversal as soon * as we remove the entry. */ - hlist_for_each_entry(e, head, hlist) { + lttng_hlist_for_each_entry(e, head, hlist) { if (pid == e->pid) { pid_tracker_del_node_rcu(e); return 0; @@ -150,7 +150,7 @@ void lttng_pid_tracker_destroy(struct lttng_pid_tracker *lpf) struct lttng_pid_hash_node *e; struct hlist_node *tmp; - hlist_for_each_entry_safe(e, tmp, head, hlist) + lttng_hlist_for_each_entry_safe(e, tmp, head, hlist) pid_tracker_del_node(e); } kfree(lpf); diff --git a/wrapper/list.h b/wrapper/list.h new file mode 100644 index 00000000..c816684d --- /dev/null +++ b/wrapper/list.h @@ -0,0 +1,84 @@ +#ifndef _LTTNG_WRAPPER_LIST_H +#define _LTTNG_WRAPPER_LIST_H + +/* + * wrapper/list.h + * + * wrapper around linux/list.h. + * + * Copyright (C) 2015 Mathieu Desnoyers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This wrapper code is derived from Linux 3.19.2 include/linux/list.h + * and include/linux/rculist.h, hence the GPLv2 license applied to this + * file. + */ + +#include +#include + +#define lttng_hlist_entry_safe(ptr, type, member) \ + ({ typeof(ptr) ____ptr = (ptr); \ + ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + }) + +/** + * lttng_hlist_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define lttng_hlist_for_each_entry(pos, head, member) \ + for (pos = lttng_hlist_entry_safe((head)->first, typeof(*(pos)), member);\ + pos; \ + pos = lttng_hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +/** + * lttng_hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define lttng_hlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = lttng_hlist_entry_safe((head)->first, typeof(*pos), member);\ + pos && ({ n = pos->member.next; 1; }); \ + pos = lttng_hlist_entry_safe(n, typeof(*pos), member)) + +#ifndef rcu_dereference_raw_notrace +#define rcu_dereference_raw_notrace(p) rcu_dereference_raw(p) +#endif + +/** + * lttng_hlist_for_each_entry_rcu_notrace - iterate over rcu list of given type (for tracing) + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_head_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + * + * This is the same as hlist_for_each_entry_rcu() except that it does + * not do any RCU debugging or tracing. + */ +#define lttng_hlist_for_each_entry_rcu_notrace(pos, head, member) \ + for (pos = lttng_hlist_entry_safe (rcu_dereference_raw_notrace(hlist_first_rcu(head)),\ + typeof(*(pos)), member); \ + pos; \ + pos = lttng_hlist_entry_safe(rcu_dereference_raw_notrace(hlist_next_rcu(\ + &(pos)->member)), typeof(*(pos)), member)) + +#endif /* _LTTNG_WRAPPER_LIST_H */