[patch 1/2] Seq_file add support for sorted list

Mathieu Desnoyers
2007-08-12T15:16:22Z

[-- Attachment #1: seq_file_sorted.patch --]
[-- Type: text/plain, Size: 3172 bytes --]

Add support for sorted list in seq_file. It aims at changing the way
/proc/modules and kallsyms iterates on the module list to remove a race between
module unload and module/symbol listing.

The list is sorted by ascending list_head pointer address.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
fs/seq_file.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/linux/seq_file.h | 20 ++++++++++++++++++++
2 files changed, 60 insertions(+)

Index: linux-2.6-lttng/fs/seq_file.c
===================================================================
--- linux-2.6-lttng.orig/fs/seq_file.c 2007-07-25 01:40:13.000000000 -0400
+++ linux-2.6-lttng/fs/seq_file.c 2007-07-25 02:47:55.000000000 -0400
@@ -485,3 +485,43 @@ struct list_head *seq_list_next(void *v,
}

EXPORT_SYMBOL(seq_list_next);
+
+struct list_head *seq_sorted_list_start(struct list_head *head, void *pos)
+{
+ struct list_head *lh;
+
+ list_for_each(lh, head)
+ if ((void*)lh >= pos)
+ return lh;
+ return NULL;
+}
+
+EXPORT_SYMBOL(seq_sorted_list_start);
+
+struct list_head *seq_sorted_list_start_head(struct list_head *head, void *pos)
+{
+ struct list_head *lh;
+
+ if (!pos)
+ return head;
+ list_for_each(lh, head)
+ if ((void*)lh >= pos)
+ return lh->prev;
+ return NULL;
+}
+
+EXPORT_SYMBOL(seq_sorted_list_start_head);
+
+struct list_head *seq_sorted_list_next(void *p, struct list_head *head,
+ void **ppos)
+{
+ struct list_head *lh;
+ void *next;
+
+ lh = ((struct list_head *)p)->next;
+ next = (lh == head) ? NULL : lh;
+ *ppos = next ? next : (void*)-1UL;
+ return next;
+}
+
+EXPORT_SYMBOL(seq_sorted_list_next);
Index: linux-2.6-lttng/include/linux/seq_file.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/seq_file.h 2007-07-25 01:40:13.000000000 -0400
+++ linux-2.6-lttng/include/linux/seq_file.h 2007-07-25 02:41:22.000000000 -0400
@@ -61,5 +61,25 @@ extern struct list_head *seq_list_start_
extern struct list_head *seq_list_next(void *v, struct list_head *head,
loff_t *ppos);

+/*
+ * Helpers for iteration over a list sorted by ascending head pointer address.
+ * To be used in contexts where preemption cannot be disabled to insure to
+ * continue iteration on a modified list starting at the same location where it
+ * stopped, or at a following location. It insures that the lost information
+ * will only be in elements added/removed from the list between iterations.
+ * void *pos is only used to get the next list element and may not be a valid
+ * list_head anymore when given to seq_sorted_list_start() or
+ * seq_sorted_list_start_head().
+ */
+extern struct list_head *seq_sorted_list_start(struct list_head *head,
+ void *pos);
+extern struct list_head *seq_sorted_list_start_head(struct list_head *head,
+ void *pos);
+/*
+ * next must be called with an existing p node
+ */
+extern struct list_head *seq_sorted_list_next(void *p, struct list_head *head,
+ void **ppos);
+
#endif
#endif