From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757055AbZCEX0B (ORCPT ); Thu, 5 Mar 2009 18:26:01 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756579AbZCEXZs (ORCPT ); Thu, 5 Mar 2009 18:25:48 -0500 Received: from smtp.polymtl.ca ([132.207.4.11]:33401 "EHLO smtp.polymtl.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757425AbZCEXZq (ORCPT ); Thu, 5 Mar 2009 18:25:46 -0500 Message-Id: <20090305225515.754674167@polymtl.ca> References: <20090305224728.947235917@polymtl.ca> User-Agent: quilt/0.46-1 Date: Thu, 05 Mar 2009 17:47:46 -0500 From: Mathieu Desnoyers To: Linus Torvalds , Ingo Molnar , linux-kernel@vger.kernel.org, Andrew Morton , Steven Rostedt , ltt-dev@lists.casi.polymtl.ca, Peter Zijlstra , Frederic Weisbecker , Arjan van de Ven , Pekka Paalanen , Arnaldo Carvalho de Melo , "H. Peter Anvin" , Martin Bligh , "Frank Ch. Eigler" , Tom Zanussi , Masami Hiramatsu , KOSAKI Motohiro , Jason Baron , Christoph Hellwig , Jiaying Zhang , Eduard - Gabriel Munteanu , mrubin@google.com, md@google.com Cc: Mathieu Desnoyers Subject: [RFC patch 18/41] Seq_file add support for sorted list Content-Disposition: inline; filename=seq_file_sorted.patch X-Poly-FromMTA: (test.casi.polymtl.ca [132.207.72.60]) at Thu, 5 Mar 2009 23:14:12 +0000 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Changelog: When reading the data by small chunks (i.e. byte by byte), the index (ppos) is incremented by seq_read() directly and no "next" callback is called when going to the next module. Therefore, use ppos instead of m->private to deal with the fact that this index is incremented directly to pass to the next module in seq_read() after the buffer has been emptied. Signed-off-by: Mathieu Desnoyers --- fs/seq_file.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/seq_file.h | 20 ++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) Index: linux-2.6-lttng/fs/seq_file.c =================================================================== --- linux-2.6-lttng.orig/fs/seq_file.c 2009-03-05 15:44:04.000000000 -0500 +++ linux-2.6-lttng/fs/seq_file.c 2009-03-05 15:44:36.000000000 -0500 @@ -671,5 +671,48 @@ struct list_head *seq_list_next(void *v, ++*ppos; return lh == head ? NULL : lh; } - EXPORT_SYMBOL(seq_list_next); + +struct list_head *seq_sorted_list_start(struct list_head *head, loff_t *ppos) +{ + struct list_head *lh; + + list_for_each(lh, head) + if ((unsigned long)lh >= *ppos) { + *ppos = (unsigned long)lh; + return lh; + } + return NULL; +} +EXPORT_SYMBOL(seq_sorted_list_start); + +struct list_head *seq_sorted_list_start_head(struct list_head *head, + loff_t *ppos) +{ + struct list_head *lh; + + if (!*ppos) { + *ppos = (unsigned long)head; + return head; + } + list_for_each(lh, head) + if ((unsigned long)lh >= *ppos) { + *ppos = (long)lh->prev; + 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, + loff_t *ppos) +{ + struct list_head *lh; + void *next; + + lh = ((struct list_head *)p)->next; + next = (lh == head) ? NULL : lh; + *ppos = next ? ((unsigned long)next) : (-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 2009-03-05 15:44:04.000000000 -0500 +++ linux-2.6-lttng/include/linux/seq_file.h 2009-03-05 15:44:05.000000000 -0500 @@ -95,4 +95,24 @@ 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, + loff_t *ppos); +extern struct list_head *seq_sorted_list_start_head(struct list_head *head, + loff_t *ppos); +/* + * next must be called with an existing p node + */ +extern struct list_head *seq_sorted_list_next(void *p, struct list_head *head, + loff_t *ppos); + #endif -- Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68