Skip to content

Commit

Permalink
seq_file: add RCU versions of new hlist/list iterators (v3)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
stephen hemminger authored and davem330 committed Feb 22, 2010
1 parent 35e2da4 commit 1cc5232
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 4 deletions.
71 changes: 71 additions & 0 deletions fs/seq_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,3 +750,74 @@ struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
return node->next;
}
EXPORT_SYMBOL(seq_hlist_next);

/**
* seq_hlist_start_rcu - start an iteration of a hlist protected by RCU
* @head: the head of the hlist
* @pos: the start position of the sequence
*
* Called at seq_file->op->start().
*
* 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().
*/
struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
loff_t pos)
{
struct hlist_node *node;

__hlist_for_each_rcu(node, head)
if (pos-- == 0)
return node;
return NULL;
}
EXPORT_SYMBOL(seq_hlist_start_rcu);

/**
* seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU
* @head: the head of the hlist
* @pos: the start position of the sequence
*
* Called at seq_file->op->start(). Call this function if you want to
* print a header at the top of the output.
*
* 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().
*/
struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
loff_t pos)
{
if (!pos)
return SEQ_START_TOKEN;

return seq_hlist_start_rcu(head, pos - 1);
}
EXPORT_SYMBOL(seq_hlist_start_head_rcu);

/**
* seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
* @v: the current iterator
* @head: the head of the hlist
* @pos: the current posision
*
* Called at seq_file->op->next().
*
* 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().
*/
struct hlist_node *seq_hlist_next_rcu(void *v,
struct hlist_head *head,
loff_t *ppos)
{
struct hlist_node *node = v;

++*ppos;
if (v == SEQ_START_TOKEN)
return rcu_dereference(head->first);
else
return rcu_dereference(node->next);
}
EXPORT_SYMBOL(seq_hlist_next_rcu);
5 changes: 5 additions & 0 deletions include/linux/rculist.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,11 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
n->next->pprev = &n->next;
}

#define __hlist_for_each_rcu(pos, head) \
for (pos = rcu_dereference((head)->first); \
pos && ({ prefetch(pos->next); 1; }); \
pos = rcu_dereference(pos->next))

/**
* hlist_for_each_entry_rcu - iterate over rcu list of given type
* @tpos: the type * to use as a loop cursor.
Expand Down
15 changes: 11 additions & 4 deletions include/linux/seq_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,17 @@ extern struct list_head *seq_list_next(void *v, struct list_head *head,
*/

extern struct hlist_node *seq_hlist_start(struct hlist_head *head,
loff_t pos);
loff_t pos);
extern struct hlist_node *seq_hlist_start_head(struct hlist_head *head,
loff_t pos);
loff_t pos);
extern struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
loff_t *ppos);

loff_t *ppos);

extern struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
loff_t pos);
extern struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
loff_t pos);
extern struct hlist_node *seq_hlist_next_rcu(void *v,
struct hlist_head *head,
loff_t *ppos);
#endif

0 comments on commit 1cc5232

Please sign in to comment.