Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1cc52327 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller
Browse files

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: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 35e2da46
Loading
Loading
Loading
Loading
+71 −0
Original line number Original line Diff line number Diff line
@@ -750,3 +750,74 @@ struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
		return node->next;
		return node->next;
}
}
EXPORT_SYMBOL(seq_hlist_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 −0
Original line number Original line Diff line number Diff line
@@ -406,6 +406,11 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
		n->next->pprev = &n->next;
		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
 * hlist_for_each_entry_rcu - iterate over rcu list of given type
 * @tpos:	the type * to use as a loop cursor.
 * @tpos:	the type * to use as a loop cursor.
+11 −4
Original line number Original line Diff line number Diff line
@@ -146,4 +146,11 @@ extern struct hlist_node *seq_hlist_start_head(struct hlist_head *head,
extern struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
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
#endif