From: Keith Busch kbusch@kernel.org
Provide a helper to remove elements from a list to the end, and place those elements in a new list.
Signed-off-by: Keith Busch kbusch@kernel.org --- include/linux/list.h | 20 ++++++++++++++++++++ lib/list-test.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+)
diff --git a/include/linux/list.h b/include/linux/list.h index 5f4b0a39cf46a..f22850e854820 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -520,6 +520,26 @@ static inline void list_cut_before(struct list_head *list, entry->prev = head; }
+/** + * list_cut - cut a list into two from the entry + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * + * This helper removes elements from @head starting at @entry until the end, + * and appends them to @lists. + */ +static inline void list_cut(struct list_head *list, + struct list_head *head, struct list_head *entry) +{ + list->next = entry; + list->prev = head->prev; + head->prev = entry->prev; + entry->prev->next = head; + entry->prev = list; + list->prev->next = list; +} + static inline void __list_splice(const struct list_head *list, struct list_head *prev, struct list_head *next) diff --git a/lib/list-test.c b/lib/list-test.c index 0cc27de9cec88..1507f46cf1ade 100644 --- a/lib/list-test.c +++ b/lib/list-test.c @@ -382,6 +382,34 @@ static void list_test_list_is_singular(struct kunit *test) KUNIT_EXPECT_FALSE(test, list_is_singular(&list)); }
+static void list_test_list_cut(struct kunit *test) +{ + struct list_head entries[3], *cur; + LIST_HEAD(list1); + LIST_HEAD(list2); + int i = 0; + + list_add_tail(&entries[0], &list1); + list_add_tail(&entries[1], &list1); + list_add_tail(&entries[2], &list1); + + /* before: [list1] -> entries[0] -> entries[1] -> entries[2] */ + list_cut(&list2, &list1, &entries[1]); + /* after: [list1] -> entries[0], [list2] -> entries[1] -> entries[2] */ + + list_for_each(cur, &list1) { + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); + i++; + } + + KUNIT_EXPECT_EQ(test, i, 1); + + list_for_each(cur, &list2) { + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); + i++; + } +} + static void list_test_list_cut_position(struct kunit *test) { struct list_head entries[3], *cur; @@ -780,6 +808,7 @@ static struct kunit_case list_test_cases[] = { KUNIT_CASE(list_test_list_is_singular), KUNIT_CASE(list_test_list_cut_position), KUNIT_CASE(list_test_list_cut_before), + KUNIT_CASE(list_test_list_cut), KUNIT_CASE(list_test_list_splice), KUNIT_CASE(list_test_list_splice_tail), KUNIT_CASE(list_test_list_splice_init),