summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2014-09-19 14:09:51 +0200
committerStefan Agner <stefan.agner@toradex.com>2014-10-28 14:42:35 +0100
commit88ffc75a690481a20bf8dd2b864f3ba91a698532 (patch)
treed96581eb47712c03b0b015eabe250ad2a781e28c /fs
parent5fc897d5626f59d7fcda45d41401f0baaf558c1f (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.c16
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;
}
}