Commit 850d71ac authored by Al Viro's avatar Al Viro
Browse files

autofs: don't bother with atomics for ino->count



All writers are serialized on inode->i_rwsem.  So are the readers
outside of expire.c.  And the readers in expire.c are in the
code that really doesn't care about narrow races - it's looking
for expiry candidates and its callers have to cope with the
possibility of a good candidate becoming busy right under them.

No point bothering with atomic operations - just use int and
mark the non-serialized readers with READ_ONCE().

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c3aed166
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -63,7 +63,7 @@ struct autofs_info {


	struct autofs_sb_info *sbi;
	struct autofs_sb_info *sbi;
	unsigned long last_used;
	unsigned long last_used;
	atomic_t count;
	int count;


	kuid_t uid;
	kuid_t uid;
	kgid_t gid;
	kgid_t gid;
+3 −3
Original line number Original line Diff line number Diff line
@@ -211,7 +211,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
			}
			}
		} else {
		} else {
			struct autofs_info *ino = autofs_dentry_ino(p);
			struct autofs_info *ino = autofs_dentry_ino(p);
			unsigned int ino_count = atomic_read(&ino->count);
			unsigned int ino_count = READ_ONCE(ino->count);


			/* allow for dget above and top is already dgot */
			/* allow for dget above and top is already dgot */
			if (p == top)
			if (p == top)
@@ -379,7 +379,7 @@ static struct dentry *should_expire(struct dentry *dentry,
		/* Not a forced expire? */
		/* Not a forced expire? */
		if (!(how & AUTOFS_EXP_FORCED)) {
		if (!(how & AUTOFS_EXP_FORCED)) {
			/* ref-walk currently on this dentry? */
			/* ref-walk currently on this dentry? */
			ino_count = atomic_read(&ino->count) + 1;
			ino_count = READ_ONCE(ino->count) + 1;
			if (d_count(dentry) > ino_count)
			if (d_count(dentry) > ino_count)
				return NULL;
				return NULL;
		}
		}
@@ -396,7 +396,7 @@ static struct dentry *should_expire(struct dentry *dentry,
		/* Not a forced expire? */
		/* Not a forced expire? */
		if (!(how & AUTOFS_EXP_FORCED)) {
		if (!(how & AUTOFS_EXP_FORCED)) {
			/* ref-walk currently on this dentry? */
			/* ref-walk currently on this dentry? */
			ino_count = atomic_read(&ino->count) + 1;
			ino_count = READ_ONCE(ino->count) + 1;
			if (d_count(dentry) > ino_count)
			if (d_count(dentry) > ino_count)
				return NULL;
				return NULL;
		}
		}
+10 −10
Original line number Original line Diff line number Diff line
@@ -569,9 +569,9 @@ static int autofs_dir_symlink(struct inode *dir,
	d_add(dentry, inode);
	d_add(dentry, inode);


	dget(dentry);
	dget(dentry);
	atomic_inc(&ino->count);
	ino->count++;
	p_ino = autofs_dentry_ino(dentry->d_parent);
	p_ino = autofs_dentry_ino(dentry->d_parent);
	atomic_inc(&p_ino->count);
	p_ino->count++;


	dir->i_mtime = current_time(dir);
	dir->i_mtime = current_time(dir);


@@ -609,9 +609,9 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry)
	if (sbi->flags & AUTOFS_SBI_CATATONIC)
	if (sbi->flags & AUTOFS_SBI_CATATONIC)
		return -EACCES;
		return -EACCES;


	atomic_dec(&ino->count);
	ino->count--;
	p_ino = autofs_dentry_ino(dentry->d_parent);
	p_ino = autofs_dentry_ino(dentry->d_parent);
	atomic_dec(&p_ino->count);
	p_ino->count--;
	dput(ino->dentry);
	dput(ino->dentry);


	d_inode(dentry)->i_size = 0;
	d_inode(dentry)->i_size = 0;
@@ -669,7 +669,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
	/* only consider parents below dentrys in the root */
	/* only consider parents below dentrys in the root */
	if (IS_ROOT(parent->d_parent))
	if (IS_ROOT(parent->d_parent))
		return;
		return;
	if (atomic_read(&autofs_dentry_ino(parent)->count) == 2)
	if (autofs_dentry_ino(parent)->count == 2)
		managed_dentry_set_managed(parent);
		managed_dentry_set_managed(parent);
}
}


@@ -691,7 +691,7 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
	if (sbi->flags & AUTOFS_SBI_CATATONIC)
	if (sbi->flags & AUTOFS_SBI_CATATONIC)
		return -EACCES;
		return -EACCES;


	if (atomic_read(&ino->count) != 1)
	if (ino->count != 1)
		return -ENOTEMPTY;
		return -ENOTEMPTY;


	spin_lock(&sbi->lookup_lock);
	spin_lock(&sbi->lookup_lock);
@@ -702,9 +702,9 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
	if (sbi->version < 5)
	if (sbi->version < 5)
		autofs_clear_leaf_automount_flags(dentry);
		autofs_clear_leaf_automount_flags(dentry);


	atomic_dec(&ino->count);
	ino->count--;
	p_ino = autofs_dentry_ino(dentry->d_parent);
	p_ino = autofs_dentry_ino(dentry->d_parent);
	atomic_dec(&p_ino->count);
	p_ino->count--;
	dput(ino->dentry);
	dput(ino->dentry);
	d_inode(dentry)->i_size = 0;
	d_inode(dentry)->i_size = 0;
	clear_nlink(d_inode(dentry));
	clear_nlink(d_inode(dentry));
@@ -750,9 +750,9 @@ static int autofs_dir_mkdir(struct inode *dir,
		autofs_set_leaf_automount_flags(dentry);
		autofs_set_leaf_automount_flags(dentry);


	dget(dentry);
	dget(dentry);
	atomic_inc(&ino->count);
	ino->count++;
	p_ino = autofs_dentry_ino(dentry->d_parent);
	p_ino = autofs_dentry_ino(dentry->d_parent);
	atomic_inc(&p_ino->count);
	p_ino->count++;
	inc_nlink(dir);
	inc_nlink(dir);
	dir->i_mtime = current_time(dir);
	dir->i_mtime = current_time(dir);