linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] 2.5.39 list_head debugging
@ 2002-09-29  5:58 Zach Brown
  2002-09-29  6:12 ` Andrew Morton
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Zach Brown @ 2002-09-29  5:58 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel

Linus,

	This patch adds some straight-forward assertions that check the
validity of arguments to the list_* inlines.  It tries to simply check
that a list member is really on a doubly linked list and that the 4
links it's involved with aren't crap.  It should be constant-time on
stuff that is likely to be in cache anyway.  

	The patch already caught some list_heads that were not being
maintained properly ; list_empty was failing on them even though they
weren't on lists.  (their pointers had slab poison, were NULL, etc. ) 

	With those two errors fixed, and I think akpm is going to send
you the patches, the box appears to run fine with very light testing.

-- 
 zach

===== include/linux/list.h 1.17 vs edited =====
--- 1.17/include/linux/list.h	Mon Sep 23 10:03:52 2002
+++ linux-2.5.39/include/linux/list.h	Fri Sep 27 18:28:30 2002
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) || defined(_LVM_H_INCLUDE)
 
+#include <linux/kernel.h> /* ouch.. just for bug_on */
 #include <linux/prefetch.h>
 
 /*
@@ -28,6 +29,26 @@
 	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
 } while (0)
 
+#ifdef CONFIG_DEBUG_LIST_HEAD
+
+static inline struct list_head * __list_valid(struct list_head *list)
+{
+	BUG_ON(list == NULL);
+	BUG_ON(list->next == NULL);
+	BUG_ON(list->prev == NULL);
+	BUG_ON(list->next->prev != list);
+	BUG_ON(list->prev->next != list);
+	BUG_ON((list->next == list) && (list->prev != list));
+	BUG_ON((list->prev == list) && (list->next != list));
+
+	return list;
+}
+#else 
+
+#define __list_valid(args...)
+
+#endif
+
 /*
  * Insert a new entry between two known consecutive entries. 
  *
@@ -54,7 +75,9 @@
  */
 static inline void list_add(struct list_head *new, struct list_head *head)
 {
+	__list_valid(head);
 	__list_add(new, head, head->next);
+	__list_valid(new);
 }
 
 /**
@@ -67,7 +90,9 @@
  */
 static inline void list_add_tail(struct list_head *new, struct list_head *head)
 {
+	__list_valid(head);
 	__list_add(new, head->prev, head);
+	__list_valid(new);
 }
 
 /*
@@ -90,6 +115,7 @@
  */
 static inline void list_del(struct list_head *entry)
 {
+	__list_valid(entry);
 	__list_del(entry->prev, entry->next);
 	entry->next = (void *) 0;
 	entry->prev = (void *) 0;
@@ -101,6 +127,7 @@
  */
 static inline void list_del_init(struct list_head *entry)
 {
+	__list_valid(entry);
 	__list_del(entry->prev, entry->next);
 	INIT_LIST_HEAD(entry); 
 }
@@ -112,6 +139,7 @@
  */
 static inline void list_move(struct list_head *list, struct list_head *head)
 {
+	__list_valid(list);
         __list_del(list->prev, list->next);
         list_add(list, head);
 }
@@ -124,6 +152,7 @@
 static inline void list_move_tail(struct list_head *list,
 				  struct list_head *head)
 {
+	__list_valid(list);
         __list_del(list->prev, list->next);
         list_add_tail(list, head);
 }
@@ -134,6 +163,7 @@
  */
 static inline int list_empty(struct list_head *head)
 {
+	__list_valid(head);
 	return head->next == head;
 }
 
@@ -158,6 +188,8 @@
  */
 static inline void list_splice(struct list_head *list, struct list_head *head)
 {
+	__list_valid(list);
+	__list_valid(head);
 	if (!list_empty(list))
 		__list_splice(list, head);
 }
@@ -172,6 +204,8 @@
 static inline void list_splice_init(struct list_head *list,
 				    struct list_head *head)
 {
+	__list_valid(list);
+	__list_valid(head);
 	if (!list_empty(list)) {
 		__list_splice(list, head);
 		INIT_LIST_HEAD(list);
@@ -193,8 +227,9 @@
  * @head:	the head for your list.
  */
 #define list_for_each(pos, head) \
-	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
-        	pos = pos->next, prefetch(pos->next))
+	for (pos = (head)->next, prefetch(pos->next); \
+		__list_valid(pos), pos != (head); \
+        	__list_valid(pos), pos = pos->next, prefetch(pos->next))
 
 /**
  * __list_for_each	-	iterate over a list
@@ -207,7 +242,9 @@
  * or 1 entry) most of the time.
  */
 #define __list_for_each(pos, head) \
-	for (pos = (head)->next; pos != (head); pos = pos->next)
+	for (pos = (head)->next; \
+		__list_valid(pos), pos != (head); \
+		__list_valid(pos), pos = pos->next)
 
 /**
  * list_for_each_prev	-	iterate over a list backwards
@@ -215,8 +252,9 @@
  * @head:	the head for your list.
  */
 #define list_for_each_prev(pos, head) \
-	for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
-        	pos = pos->prev, prefetch(pos->prev))
+	for (pos = (head)->prev, prefetch(pos->prev); \
+		__list_valid(pos), pos != (head); \
+        	__list_valid(pos), pos = pos->prev, prefetch(pos->prev))
         	
 /**
  * list_for_each_safe	-	iterate over a list safe against removal of list entry
@@ -225,7 +263,8 @@
  * @head:	the head for your list.
  */
 #define list_for_each_safe(pos, n, head) \
-	for (pos = (head)->next, n = pos->next; pos != (head); \
+	for (pos = (head)->next, n = pos->next; \
+		__list_valid(pos), pos != (head); \
 		pos = n, n = pos->next)
 
 /**
@@ -237,7 +276,7 @@
 #define list_for_each_entry(pos, head, member)				\
 	for (pos = list_entry((head)->next, typeof(*pos), member),	\
 		     prefetch(pos->member.next);			\
-	     &pos->member != (head); 					\
+	     __list_valid(&pos->member), &pos->member != (head); 	\
 	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
 		     prefetch(pos->member.next))
 
===== arch/alpha/config.in 1.29 vs edited =====
--- 1.29/arch/alpha/config.in	Wed Aug 28 11:16:05 2002
+++ linux-2.5.39/arch/alpha/config.in	Fri Sep 27 18:09:38 2002
@@ -390,6 +390,7 @@
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
    bool '  Read-write spinlock debugging' CONFIG_DEBUG_RWLOCK
    bool '  Semaphore debugging' CONFIG_DEBUG_SEMAPHORE
+   bool '  struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 else
    define_tristate CONFIG_MATHEMU y
 fi
===== arch/arm/config.in 1.38 vs edited =====
--- 1.38/arch/arm/config.in	Mon Jul 15 09:54:04 2002
+++ linux-2.5.39/arch/arm/config.in	Fri Sep 27 18:10:03 2002
@@ -669,6 +669,7 @@
 dep_bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_DEBUG_KERNEL
 dep_bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK $CONFIG_DEBUG_KERNEL
 dep_bool '  Wait queue debugging' CONFIG_DEBUG_WAITQ $CONFIG_DEBUG_KERNEL
+dep_bool '  struct list_head debugging' CONFIG_DEBUG_LIST_HEAD $CONFIG_DEBUG_KERNEL
 dep_bool '  Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE $CONFIG_DEBUG_KERNEL
 dep_bool '  Verbose kernel error messages' CONFIG_DEBUG_ERRORS $CONFIG_DEBUG_KERNEL
 # These options are only for real kernel hackers who want to get their hands dirty. 
===== arch/i386/config.in 1.49 vs edited =====
--- 1.49/arch/i386/config.in	Thu Sep 26 08:27:16 2002
+++ linux-2.5.39/arch/i386/config.in	Fri Sep 27 18:10:29 2002
@@ -432,6 +432,7 @@
    bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   bool '  struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
    if [ "$CONFIG_HIGHMEM" = "y" ]; then
       bool '  Highmem debugging' CONFIG_DEBUG_HIGHMEM
    fi
===== arch/ia64/config.in 1.33 vs edited =====
--- 1.33/arch/ia64/config.in	Sat Sep 21 01:25:52 2002
+++ linux-2.5.39/arch/ia64/config.in	Fri Sep 27 18:10:42 2002
@@ -277,6 +277,7 @@
    fi
    bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   bool '  struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
    bool '  Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
    bool '  Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
 fi
===== arch/m68k/config.in 1.19 vs edited =====
--- 1.19/arch/m68k/config.in	Tue Aug 13 03:33:49 2002
+++ linux-2.5.39/arch/m68k/config.in	Fri Sep 27 18:10:57 2002
@@ -541,6 +541,7 @@
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
    bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
    bool '  Verbose BUG() reporting' CONFIG_DEBUG_BUGVERBOSE
+   bool '  struct list_head debuggiing' CONFIG_DEBUG_LIST_HEAD
 fi
 
 endmenu
===== arch/mips/config.in 1.19 vs edited =====
--- 1.19/arch/mips/config.in	Wed Aug 28 11:16:05 2002
+++ linux-2.5.39/arch/mips/config.in	Fri Sep 27 18:12:26 2002
@@ -489,6 +489,7 @@
   bool 'Low-level debugging' CONFIG_LL_DEBUG
 fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 if [ "$CONFIG_SMP" != "y" ]; then
    bool 'Run uncached' CONFIG_MIPS_UNCACHED
 fi
===== arch/mips64/config.in 1.18 vs edited =====
--- 1.18/arch/mips64/config.in	Wed Aug 28 11:16:05 2002
+++ linux-2.5.39/arch/mips64/config.in	Fri Sep 27 18:12:08 2002
@@ -243,6 +243,7 @@
 fi
 bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 if [ "$CONFIG_SMP" != "y" ]; then
    bool 'Run uncached' CONFIG_MIPS_UNCACHED
 fi
===== arch/parisc/config.in 1.12 vs edited =====
--- 1.12/arch/parisc/config.in	Sun Aug 25 15:44:57 2002
+++ linux-2.5.39/arch/parisc/config.in	Fri Sep 27 18:12:41 2002
@@ -188,6 +188,7 @@
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 endmenu
 
 source security/Config.in
===== arch/ppc/config.in 1.43 vs edited =====
--- 1.43/arch/ppc/config.in	Thu Sep 19 21:35:59 2002
+++ linux-2.5.39/arch/ppc/config.in	Fri Sep 27 18:13:11 2002
@@ -585,6 +585,7 @@
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 bool 'Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 bool 'Include kgdb kernel debugger' CONFIG_KGDB
 if [ "$CONFIG_KGDB" = "y" ]; then
    choice 'Serial Port'			\
===== arch/ppc64/config.in 1.16 vs edited =====
--- 1.16/arch/ppc64/config.in	Wed Aug 28 23:26:41 2002
+++ linux-2.5.39/arch/ppc64/config.in	Fri Sep 27 18:12:58 2002
@@ -196,6 +196,7 @@
 if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
    bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
+   bool '  struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
    bool '  Include xmon kernel debugger' CONFIG_XMON
    if [ "$CONFIG_XMON" = "y" ]; then
       bool '  Enable xmon by default' CONFIG_XMON_DEFAULT
===== arch/s390/config.in 1.10 vs edited =====
--- 1.10/arch/s390/config.in	Mon Jul 22 11:54:56 2002
+++ linux-2.5.39/arch/s390/config.in	Fri Sep 27 18:13:23 2002
@@ -73,6 +73,7 @@
 #  bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
 #fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 endmenu
 
 source security/Config.in
===== arch/s390x/config.in 1.9 vs edited =====
--- 1.9/arch/s390x/config.in	Mon Jul 22 11:54:56 2002
+++ linux-2.5.39/arch/s390x/config.in	Fri Sep 27 18:13:36 2002
@@ -76,6 +76,7 @@
 #  bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
 #fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 endmenu
 
 source security/Config.in
===== arch/sh/config.in 1.16 vs edited =====
--- 1.16/arch/sh/config.in	Sun Aug 25 15:41:58 2002
+++ linux-2.5.39/arch/sh/config.in	Fri Sep 27 18:13:50 2002
@@ -362,6 +362,7 @@
 comment 'Kernel hacking'
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 bool 'Use LinuxSH standard BIOS' CONFIG_SH_STANDARD_BIOS
 if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then
    bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
===== arch/sparc/config.in 1.24 vs edited =====
--- 1.24/arch/sparc/config.in	Wed Sep 18 16:20:23 2002
+++ linux-2.5.39/arch/sparc/config.in	Fri Sep 27 18:14:09 2002
@@ -239,6 +239,7 @@
 bool 'Debug memory allocations' CONFIG_DEBUG_SLAB
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 bool 'Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 
 endmenu
 
===== arch/sparc64/config.in 1.37 vs edited =====
--- 1.37/arch/sparc64/config.in	Wed Sep 18 16:20:23 2002
+++ linux-2.5.39/arch/sparc64/config.in	Fri Sep 27 18:13:59 2002
@@ -281,6 +281,7 @@
    bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   bool '  struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
    bool '  Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE
    bool '  D-cache flush debugging' CONFIG_DEBUG_DCFLUSH
 fi
===== arch/um/config.in 1.1 vs edited =====
--- 1.1/arch/um/config.in	Fri Sep  6 10:29:28 2002
+++ linux-2.5.39/arch/um/config.in	Fri Sep 27 18:14:22 2002
@@ -77,6 +77,7 @@
 comment 'Kernel hacking'
 bool 'Debug memory allocations' CONFIG_DEBUG_SLAB
 bool 'Enable kernel debugging symbols' CONFIG_DEBUGSYM
+bool 'struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
 if [ "$CONFIG_XTERM_CHAN" = "y" ]; then
    dep_bool 'Enable ptrace proxy' CONFIG_PT_PROXY $CONFIG_DEBUGSYM
 else 
===== arch/x86_64/config.in 1.14 vs edited =====
--- 1.14/arch/x86_64/config.in	Sun Aug 25 15:42:58 2002
+++ linux-2.5.39/arch/x86_64/config.in	Fri Sep 27 18:14:33 2002
@@ -221,6 +221,7 @@
 #   bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   bool '  struct list_head debugging' CONFIG_DEBUG_LIST_HEAD
    bool '  Additional run-time checks' CONFIG_CHECKING
    bool '  Debug __init statements' CONFIG_INIT_DEBUG
 fi

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2002-09-29 20:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-29  5:58 [PATCH] 2.5.39 list_head debugging Zach Brown
2002-09-29  6:12 ` Andrew Morton
2002-09-29  6:24   ` Zach Brown
2002-09-29  8:33 ` Ingo Molnar
2002-09-29 14:27   ` Zach Brown
2002-09-29 14:28     ` Martin J. Bligh
2002-09-29 14:30   ` Zach Brown
2002-09-29 17:22 ` Dave Jones
2002-09-29 20:22   ` Zach Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).