While in list_for_each_entry() of yaffs_flush_inodes, the fs code can delete inodes. This leads to an endless loop which causes a softlockup. Typically this happend in sync_supers when creating and deleting files while under CPU load. This fix checks whether we get twice the same inode. If this is true, we just retry again. This is an alternative fix to the proposed fix Jisheng Zhang: yaffs: fix softlockup cauesed by inode deleted when scanning s_inodes list http://www.aleph1.co.uk/lurker/message/20110831.075307.3cfeacdf.fr.html --- Hi, I sent this email already some weeks ago, however it did not make it through to the list. Hence this resend. I can see Jisheng's issue (see link above) on a Tegra 2 device (Colibri T20) using 3.1 L4T (Linux for Tegra) Kernel. The devices which show the error had multiple YAFFS2 partitions. I could successfully reproduce the issue by using bonnie++ on two independent partitions formatted YAFFS2. After some hours (3-5) the sync_supers kernel thread starts to loop in the list_for_each_entry of the yaffs_flush_inodes function. I also set the dirty_writeback_centiseconds to 1, but I'm not sure if this really forces the error to happen more often. echo 1 > /proc/sys/vm/dirty_writeback_centisecs However, JiSheng's patch leads to different errors on my setup, e.g. kernel BUG at ../fs/inode.c:1359! kernel BUG at ../fs/inode.c:431! This is a rather ugly fix which just works around the actual symptoms, but it solved the problem for me so far. -- Stefan fs/yaffs2/yaffs_vfs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c index 6d4136d..16502e6 100644 --- a/fs/yaffs2/yaffs_vfs.c +++ b/fs/yaffs2/yaffs_vfs.c @@ -1520,9 +1520,11 @@ static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) static void yaffs_flush_inodes(struct super_block *sb) { - struct inode *iptr; + struct inode *iptr, *iptr_tmp; struct yaffs_obj *obj; +retry: + iptr_tmp = NULL; list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) { obj = yaffs_inode_to_obj(iptr); if (obj) { @@ -1530,6 +1532,18 @@ static void yaffs_flush_inodes(struct super_block *sb) "flushing obj %d", obj->obj_id); yaffs_flush_file(obj, 1, 0); } + + /* + * HACK: if we get the same iptr twice, someone removed (?) + * this inode while we are iterating. Start over again + */ + if (iptr_tmp == iptr) { + printk(KERN_ERR "yaffs: Got twice the same inode %p\n", + iptr); + goto retry; + } + + iptr_tmp = iptr; } } -- 2.1.2