get rid of restarts in sync_filesystems()

At the same time we can kill s_need_restart and local mutex in there.
__put_super() made public for a while; will be gone later.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/fs/super.c b/fs/super.c
index 0390461..ba99524 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -130,7 +130,7 @@
  * Drop a superblock's refcount.  Returns non-zero if the superblock was
  * destroyed.  The caller must hold sb_lock.
  */
-static int __put_super(struct super_block *sb)
+int __put_super(struct super_block *sb)
 {
 	int ret = 0;
 
diff --git a/fs/sync.c b/fs/sync.c
index ad6691b..f3f0a0e 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -80,35 +80,15 @@
 /*
  * Sync all the data for all the filesystems (called by sys_sync() and
  * emergency sync)
- *
- * This operation is careful to avoid the livelock which could easily happen
- * if two or more filesystems are being continuously dirtied.  s_need_sync
- * is used only here.  We set it against all filesystems and then clear it as
- * we sync them.  So redirtied filesystems are skipped.
- *
- * But if process A is currently running sync_filesystems and then process B
- * calls sync_filesystems as well, process B will set all the s_need_sync
- * flags again, which will cause process A to resync everything.  Fix that with
- * a local mutex.
  */
 static void sync_filesystems(int wait)
 {
-	struct super_block *sb;
-	static DEFINE_MUTEX(mutex);
+	struct super_block *sb, *n;
 
-	mutex_lock(&mutex);		/* Could be down_interruptible */
 	spin_lock(&sb_lock);
-	list_for_each_entry(sb, &super_blocks, s_list)
-		if (!list_empty(&sb->s_instances))
-			sb->s_need_sync = 1;
-
-restart:
-	list_for_each_entry(sb, &super_blocks, s_list) {
+	list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
 		if (list_empty(&sb->s_instances))
 			continue;
-		if (!sb->s_need_sync)
-			continue;
-		sb->s_need_sync = 0;
 		sb->s_count++;
 		spin_unlock(&sb_lock);
 
@@ -119,11 +99,9 @@
 
 		/* restart only when sb is no longer on the list */
 		spin_lock(&sb_lock);
-		if (__put_super_and_need_restart(sb))
-			goto restart;
+		__put_super(sb);
 	}
 	spin_unlock(&sb_lock);
-	mutex_unlock(&mutex);
 }
 
 /*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 62f84d9..e1c7427 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1332,7 +1332,6 @@
 	struct rw_semaphore	s_umount;
 	struct mutex		s_lock;
 	int			s_count;
-	int			s_need_sync;
 	atomic_t		s_active;
 #ifdef CONFIG_SECURITY
 	void                    *s_security;
@@ -1780,6 +1779,7 @@
 	struct vfsmount *mnt);
 extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
 int __put_super_and_need_restart(struct super_block *sb);
+int __put_super(struct super_block *sb);
 void put_super(struct super_block *sb);
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */