Skip to content

Commit 3c18d4d

Browse files
committed
Expand CONFIG_DEBUG_LIST to several other list operations
When list debugging is enabled, we aim to readably show list corruption errors, and the basic list_add/list_del operations end up having extra debugging code in them to do some basic validation of the list entries. However, "list_del_init()" and "list_move[_tail]()" ended up avoiding the debug code due to how they were written. This fixes that. So the _next_ time we have list_move() problems with stale list entries, we'll hopefully have an easier time finding them.. Signed-off-by: Linus Torvalds <[email protected]>
1 parent 2a324ce commit 3c18d4d

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

include/linux/list.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,19 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
9696
* in an undefined state.
9797
*/
9898
#ifndef CONFIG_DEBUG_LIST
99+
static inline void __list_del_entry(struct list_head *entry)
100+
{
101+
__list_del(entry->prev, entry->next);
102+
}
103+
99104
static inline void list_del(struct list_head *entry)
100105
{
101106
__list_del(entry->prev, entry->next);
102107
entry->next = LIST_POISON1;
103108
entry->prev = LIST_POISON2;
104109
}
105110
#else
111+
extern void __list_del_entry(struct list_head *entry);
106112
extern void list_del(struct list_head *entry);
107113
#endif
108114

@@ -135,7 +141,7 @@ static inline void list_replace_init(struct list_head *old,
135141
*/
136142
static inline void list_del_init(struct list_head *entry)
137143
{
138-
__list_del(entry->prev, entry->next);
144+
__list_del_entry(entry);
139145
INIT_LIST_HEAD(entry);
140146
}
141147

@@ -146,7 +152,7 @@ static inline void list_del_init(struct list_head *entry)
146152
*/
147153
static inline void list_move(struct list_head *list, struct list_head *head)
148154
{
149-
__list_del(list->prev, list->next);
155+
__list_del_entry(list);
150156
list_add(list, head);
151157
}
152158

@@ -158,7 +164,7 @@ static inline void list_move(struct list_head *list, struct list_head *head)
158164
static inline void list_move_tail(struct list_head *list,
159165
struct list_head *head)
160166
{
161-
__list_del(list->prev, list->next);
167+
__list_del_entry(list);
162168
list_add_tail(list, head);
163169
}
164170

lib/list_debug.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,31 @@ void __list_add(struct list_head *new,
3535
}
3636
EXPORT_SYMBOL(__list_add);
3737

38+
void __list_del_entry(struct list_head *entry)
39+
{
40+
struct list_head *prev, *next;
41+
42+
prev = entry->prev;
43+
next = entry->next;
44+
45+
if (WARN(next == LIST_POISON1,
46+
"list_del corruption, %p->next is LIST_POISON1 (%p)\n",
47+
entry, LIST_POISON1) ||
48+
WARN(prev == LIST_POISON2,
49+
"list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
50+
entry, LIST_POISON2) ||
51+
WARN(prev->next != entry,
52+
"list_del corruption. prev->next should be %p, "
53+
"but was %p\n", entry, prev->next) ||
54+
WARN(next->prev != entry,
55+
"list_del corruption. next->prev should be %p, "
56+
"but was %p\n", entry, next->prev))
57+
return;
58+
59+
__list_del(prev, next);
60+
}
61+
EXPORT_SYMBOL(__list_del_entry);
62+
3863
/**
3964
* list_del - deletes entry from list.
4065
* @entry: the element to delete from the list.
@@ -43,19 +68,7 @@ EXPORT_SYMBOL(__list_add);
4368
*/
4469
void list_del(struct list_head *entry)
4570
{
46-
WARN(entry->next == LIST_POISON1,
47-
"list_del corruption, next is LIST_POISON1 (%p)\n",
48-
LIST_POISON1);
49-
WARN(entry->next != LIST_POISON1 && entry->prev == LIST_POISON2,
50-
"list_del corruption, prev is LIST_POISON2 (%p)\n",
51-
LIST_POISON2);
52-
WARN(entry->prev->next != entry,
53-
"list_del corruption. prev->next should be %p, "
54-
"but was %p\n", entry, entry->prev->next);
55-
WARN(entry->next->prev != entry,
56-
"list_del corruption. next->prev should be %p, "
57-
"but was %p\n", entry, entry->next->prev);
58-
__list_del(entry->prev, entry->next);
71+
__list_del_entry(entry);
5972
entry->next = LIST_POISON1;
6073
entry->prev = LIST_POISON2;
6174
}

0 commit comments

Comments
 (0)