Implement list.h wrapper for hlist in older kernels
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 2 Apr 2015 19:26:56 +0000 (15:26 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 2 Apr 2015 19:26:56 +0000 (15:26 -0400)
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 <mathieu.desnoyers@efficios.com>
LICENSE
lttng-events.c
lttng-tracepoint.c
lttng-tracker-pid.c
wrapper/list.h [new file with mode: 0644]

diff --git a/LICENSE b/LICENSE
index c416f3ffb11ce6fcd52b1a219d26294af75d65ad..2453f716f3a8a5b9c33826a99b8c9bc679619d80 100644 (file)
--- 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
 
index d7efd425e88c9b2ed109ee11d12fbf919f67eba3..7055c3ed05af5f812edf319d8d7323a93b4a3c84 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -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;
                        }
index 13f9c247d440ca3dc7d69e44a995ec8b90f99370..f8a9cedcd74b9b61a6b3a4fe8af0e50e7bb182f4 100644 (file)
@@ -20,7 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
 #include <linux/notifier.h>
@@ -30,6 +29,7 @@
 #include <linux/module.h>
 
 #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);
index a62ec4e459343ea9ea615f58e78651dd7697a9e9..eeee9d55a5b844106178d5186c37ef61012aa2e3 100644 (file)
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/stringify.h>
-#include <linux/rculist.h>
 #include <linux/hash.h>
 #include <linux/rcupdate.h>
 
 #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 (file)
index 0000000..c816684
--- /dev/null
@@ -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 <mathieu.desnoyers@efficios.com>
+ *
+ * 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 <linux/list.h>
+#include <linux/rculist.h>
+
+#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 */
This page took 0.030384 seconds and 4 git commands to generate.