diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2014-09-19 14:09:51 +0200 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2014-10-28 14:42:35 +0100 |
commit | 88ffc75a690481a20bf8dd2b864f3ba91a698532 (patch) | |
tree | d96581eb47712c03b0b015eabe250ad2a781e28c /fs | |
parent | 5fc897d5626f59d7fcda45d41401f0baaf558c1f (diff) |
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
Diffstat (limited to 'fs')
-rw-r--r-- | fs/yaffs2/yaffs_vfs.c | 16 |
1 files changed, 15 insertions, 1 deletions
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; } } |