Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8edd64bd authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 551de6f3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ static inline void destroy_super(struct super_block *s)
 * 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;

+3 −25
Original line number Diff line number Diff line
@@ -80,35 +80,15 @@ EXPORT_SYMBOL_GPL(sync_filesystem);
/*
 * 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 @@ static void sync_filesystems(int wait)

		/* 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);
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -1332,7 +1332,6 @@ struct super_block {
	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 @@ extern int get_sb_pseudo(struct file_system_type *, char *,
	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 */