diff options
author | stephen hemminger <shemminger@vyatta.com> | 2010-02-22 02:57:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-22 18:45:54 -0500 |
commit | 1cc523271ef0b6305c565a143e3d48f6fff826dd (patch) | |
tree | 8acfcce42d5d81e4ce993c078985bfc3789bf2c5 /fs/seq_file.c | |
parent | 35e2da46d25a53e0e19956f533cc29272a6cceb2 (diff) |
seq_file: add RCU versions of new hlist/list iterators (v3)
Many usages of seq_file use RCU protected lists, so non RCU
iterators will not work safely.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/seq_file.c')
-rw-r--r-- | fs/seq_file.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/fs/seq_file.c b/fs/seq_file.c index f65b16f02da3..5afd554efad3 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -750,3 +750,74 @@ struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head, | |||
750 | return node->next; | 750 | return node->next; |
751 | } | 751 | } |
752 | EXPORT_SYMBOL(seq_hlist_next); | 752 | EXPORT_SYMBOL(seq_hlist_next); |
753 | |||
754 | /** | ||
755 | * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU | ||
756 | * @head: the head of the hlist | ||
757 | * @pos: the start position of the sequence | ||
758 | * | ||
759 | * Called at seq_file->op->start(). | ||
760 | * | ||
761 | * This list-traversal primitive may safely run concurrently with | ||
762 | * the _rcu list-mutation primitives such as hlist_add_head_rcu() | ||
763 | * as long as the traversal is guarded by rcu_read_lock(). | ||
764 | */ | ||
765 | struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, | ||
766 | loff_t pos) | ||
767 | { | ||
768 | struct hlist_node *node; | ||
769 | |||
770 | __hlist_for_each_rcu(node, head) | ||
771 | if (pos-- == 0) | ||
772 | return node; | ||
773 | return NULL; | ||
774 | } | ||
775 | EXPORT_SYMBOL(seq_hlist_start_rcu); | ||
776 | |||
777 | /** | ||
778 | * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU | ||
779 | * @head: the head of the hlist | ||
780 | * @pos: the start position of the sequence | ||
781 | * | ||
782 | * Called at seq_file->op->start(). Call this function if you want to | ||
783 | * print a header at the top of the output. | ||
784 | * | ||
785 | * This list-traversal primitive may safely run concurrently with | ||
786 | * the _rcu list-mutation primitives such as hlist_add_head_rcu() | ||
787 | * as long as the traversal is guarded by rcu_read_lock(). | ||
788 | */ | ||
789 | struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, | ||
790 | loff_t pos) | ||
791 | { | ||
792 | if (!pos) | ||
793 | return SEQ_START_TOKEN; | ||
794 | |||
795 | return seq_hlist_start_rcu(head, pos - 1); | ||
796 | } | ||
797 | EXPORT_SYMBOL(seq_hlist_start_head_rcu); | ||
798 | |||
799 | /** | ||
800 | * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU | ||
801 | * @v: the current iterator | ||
802 | * @head: the head of the hlist | ||
803 | * @pos: the current posision | ||
804 | * | ||
805 | * Called at seq_file->op->next(). | ||
806 | * | ||
807 | * This list-traversal primitive may safely run concurrently with | ||
808 | * the _rcu list-mutation primitives such as hlist_add_head_rcu() | ||
809 | * as long as the traversal is guarded by rcu_read_lock(). | ||
810 | */ | ||
811 | struct hlist_node *seq_hlist_next_rcu(void *v, | ||
812 | struct hlist_head *head, | ||
813 | loff_t *ppos) | ||
814 | { | ||
815 | struct hlist_node *node = v; | ||
816 | |||
817 | ++*ppos; | ||
818 | if (v == SEQ_START_TOKEN) | ||
819 | return rcu_dereference(head->first); | ||
820 | else | ||
821 | return rcu_dereference(node->next); | ||
822 | } | ||
823 | EXPORT_SYMBOL(seq_hlist_next_rcu); | ||