From: Carsten Otte Stephen wrote: > The orphan list entry should persist only as long > as inode->i_count is raised, and if it's raised, there should be no risk > of the struct getting reused. I tried the following *dirty* debugging patch that triggers in iput_final() exactly when i_count is lowered to zero while the orphan list entry does still persist. I have not been able to startup my system, panic output shows the sys_unlink() path -like fully described in the initial mail starting this thread- causes running into the panic() --- fs/fs-writeback.c | 9 +++++++++ fs/inode.c | 11 ++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff -puN fs/inode.c~ext3-dirty-debug-patch fs/inode.c --- 25/fs/inode.c~ext3-dirty-debug-patch 2004-02-26 02:40:39.000000000 -0800 +++ 25-akpm/fs/inode.c 2004-02-26 02:40:39.000000000 -0800 @@ -20,6 +20,7 @@ #include #include #include +#include /* * This is needed for the following functions: @@ -1019,6 +1020,14 @@ static void generic_forget_inode(struct if (!hlist_unhashed(&inode->i_hash)) { if (!(inode->i_state & (I_DIRTY|I_LOCK))) { + if (!strcmp(inode->i_sb->s_type->name, "ext3")) { + struct ext3_inode_info *ext3_i; + ext3_i = container_of(inode, + struct ext3_inode_info, + vfs_inode); + if (!list_empty(&ext3_i->i_orphan)) + WARN_ON(1); + } list_del(&inode->i_list); list_add(&inode->i_list, &inode_unused); } @@ -1066,7 +1075,7 @@ static void generic_drop_inode(struct in * held, and the drop function is supposed to release * the lock! */ -static inline void iput_final(struct inode *inode) +static void iput_final(struct inode *inode) { struct super_operations *op = inode->i_sb->s_op; void (*drop)(struct inode *) = generic_drop_inode; diff -puN fs/fs-writeback.c~ext3-dirty-debug-patch fs/fs-writeback.c --- 25/fs/fs-writeback.c~ext3-dirty-debug-patch 2004-02-26 02:40:39.000000000 -0800 +++ 25-akpm/fs/fs-writeback.c 2004-02-26 02:41:13.000000000 -0800 @@ -22,6 +22,7 @@ #include #include #include +#include extern struct super_block *blockdev_superblock; @@ -185,6 +186,14 @@ __sync_single_inode(struct inode *inode, } else if (atomic_read(&inode->i_count)) { list_move(&inode->i_list, &inode_in_use); } else { + if (!strcmp(inode->i_sb->s_type->name, "ext3")) { + struct ext3_inode_info *ext3_i; + ext3_i = container_of(inode, + struct ext3_inode_info, + vfs_inode); + if (!list_empty(&ext3_i->i_orphan)) + WARN_ON(1); + } list_move(&inode->i_list, &inode_unused); } } _