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 <torvalds@linux-foundation.org>

+35 -16
+9 -3
include/linux/list.h
··· 96 * in an undefined state. 97 */ 98 #ifndef CONFIG_DEBUG_LIST 99 static inline void list_del(struct list_head *entry) 100 { 101 __list_del(entry->prev, entry->next); ··· 108 entry->prev = LIST_POISON2; 109 } 110 #else 111 extern void list_del(struct list_head *entry); 112 #endif 113 ··· 141 */ 142 static inline void list_del_init(struct list_head *entry) 143 { 144 - __list_del(entry->prev, entry->next); 145 INIT_LIST_HEAD(entry); 146 } 147 ··· 152 */ 153 static inline void list_move(struct list_head *list, struct list_head *head) 154 { 155 - __list_del(list->prev, list->next); 156 list_add(list, head); 157 } 158 ··· 164 static inline void list_move_tail(struct list_head *list, 165 struct list_head *head) 166 { 167 - __list_del(list->prev, list->next); 168 list_add_tail(list, head); 169 } 170
··· 96 * in an undefined state. 97 */ 98 #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 + 104 static inline void list_del(struct list_head *entry) 105 { 106 __list_del(entry->prev, entry->next); ··· 103 entry->prev = LIST_POISON2; 104 } 105 #else 106 + extern void __list_del_entry(struct list_head *entry); 107 extern void list_del(struct list_head *entry); 108 #endif 109 ··· 135 */ 136 static inline void list_del_init(struct list_head *entry) 137 { 138 + __list_del_entry(entry); 139 INIT_LIST_HEAD(entry); 140 } 141 ··· 146 */ 147 static inline void list_move(struct list_head *list, struct list_head *head) 148 { 149 + __list_del_entry(list); 150 list_add(list, head); 151 } 152 ··· 158 static inline void list_move_tail(struct list_head *list, 159 struct list_head *head) 160 { 161 + __list_del_entry(list); 162 list_add_tail(list, head); 163 } 164
+26 -13
lib/list_debug.c
··· 35 } 36 EXPORT_SYMBOL(__list_add); 37 38 /** 39 * list_del - deletes entry from list. 40 * @entry: the element to delete from the list. ··· 68 */ 69 void list_del(struct list_head *entry) 70 { 71 - WARN(entry->next == LIST_POISON1, 72 - "list_del corruption, next is LIST_POISON1 (%p)\n", 73 - LIST_POISON1); 74 - WARN(entry->next != LIST_POISON1 && entry->prev == LIST_POISON2, 75 - "list_del corruption, prev is LIST_POISON2 (%p)\n", 76 - LIST_POISON2); 77 - WARN(entry->prev->next != entry, 78 - "list_del corruption. prev->next should be %p, " 79 - "but was %p\n", entry, entry->prev->next); 80 - WARN(entry->next->prev != entry, 81 - "list_del corruption. next->prev should be %p, " 82 - "but was %p\n", entry, entry->next->prev); 83 - __list_del(entry->prev, entry->next); 84 entry->next = LIST_POISON1; 85 entry->prev = LIST_POISON2; 86 }
··· 35 } 36 EXPORT_SYMBOL(__list_add); 37 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 + 63 /** 64 * list_del - deletes entry from list. 65 * @entry: the element to delete from the list. ··· 43 */ 44 void list_del(struct list_head *entry) 45 { 46 + __list_del_entry(entry); 47 entry->next = LIST_POISON1; 48 entry->prev = LIST_POISON2; 49 }