summaryrefslogtreecommitdiff
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
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
-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;
}
}