Message ID | 20130605020341.GA27240@logfs.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Jun 04, 2013 at 10:03:41PM -0400, Jörn Engel wrote: > I have seen a lot of boilerplate code that either follows the pattern of > while (!list_empty(head)) { > pos = list_entry(head->next, struct foo, list); > list_del(pos->list); > ... > } > or some variant thereof. > > With this patch in, people can use > while_list_drain_entry(pos, head, list) { > ... > } The while_list_drain_entry way changes the semantics: the list link is deleted before the {...} body starts, so it's not possible to access the list anymore. None of the code you've converted uses this, from that point it's safe, but if this is about to be a public interface, it should be (at least) documented. Macro trickery to postpone list_del after the {...} finishes does not work if kfree/kmem_cache_free/rcu_string_free/... is used. david -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/list.h b/include/linux/list.h index 6a1f8df..ab39c7d 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -557,6 +557,24 @@ static inline void list_splice_tail_init(struct list_head *list, #define list_safe_reset_next(pos, n, member) \ n = list_entry(pos->member.next, typeof(*pos), member) +/** + * while_list_drain - removes an entry from the list until it is empty + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head of your list. + */ +#define while_list_drain(pos, head) \ + while (list_empty(head) ? 0 : (pos = (head)->next, list_del(pos), 1)) + +/** + * while_list_drain_entry - removes an entry from the list until it is empty + * @pos: the type * to use as loop cursor. + * @head: the head of your list. + * @member: the name of the list_struct within the struct + */ +#define while_list_drain_entry(pos, head, member) \ + while (list_empty(head) && (pos = list_first_entry((head), \ + typeof(*pos), member), list_del((head)->next), 1)) + /* * Double linked lists with a single pointer list head. * Mostly useful for hash tables where the two pointer list head is
I have seen a lot of boilerplate code that either follows the pattern of while (!list_empty(head)) { pos = list_entry(head->next, struct foo, list); list_del(pos->list); ... } or some variant thereof. With this patch in, people can use while_list_drain_entry(pos, head, list) { ... } The patch also adds a while_list_drain variant, even though I have only found a single user for that one so far. Signed-off-by: Joern Engel <joern@logfs.org> --- include/linux/list.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)