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

Commit 79893c17 authored by Al Viro's avatar Al Viro
Browse files

fix prune_dcache()/umount() race



... and get rid of the last __put_super_and_need_restart() caller

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent df40c01a
Loading
Loading
Loading
Loading
+6 −11
Original line number Diff line number Diff line
@@ -536,7 +536,7 @@ static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags)
 */
static void prune_dcache(int count)
{
	struct super_block *sb;
	struct super_block *sb, *n;
	int w_count;
	int unused = dentry_stat.nr_unused;
	int prune_ratio;
@@ -545,13 +545,12 @@ static void prune_dcache(int count)
	if (unused == 0 || count == 0)
		return;
	spin_lock(&dcache_lock);
restart:
	if (count >= unused)
		prune_ratio = 1;
	else
		prune_ratio = unused / count;
	spin_lock(&sb_lock);
	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_nr_dentry_unused == 0)
@@ -592,14 +591,10 @@ static void prune_dcache(int count)
		}
		spin_lock(&sb_lock);
		count -= pruned;
		/*
		 * restart only when sb is no longer on the list and
		 * we have more work to do.
		 */
		if (__put_super_and_need_restart(sb) && count > 0) {
			spin_unlock(&sb_lock);
			goto restart;
		}
		__put_super(sb);
		/* more work left to do? */
		if (count <= 0)
			break;
	}
	spin_unlock(&sb_lock);
	spin_unlock(&dcache_lock);