From 88ffc75a690481a20bf8dd2b864f3ba91a698532 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 19 Sep 2014 14:09:51 +0200 Subject: yaffs: fix spinning when flush inodes 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 --- 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 6d4136dcff7a..16502e629eee 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; } } -- cgit v1.2.3