diff options
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); | ||