Merge branch 'next.autofs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull autofs updates from Al Viro:
 "autofs misuses checks for ->d_subdirs emptiness; the cursors are in
  the same lists, resulting in false negatives. It's not needed anyway,
  since autofs maintains counter in struct autofs_info, containing 0 for
  removed ones, 1 for live symlinks and 1 + number of children for live
  directories, which is precisely what we need for those checks.

  This series switches to use of that counter and untangles the crap
  around its uses (it needs not be atomic and there's a bunch of
  completely pointless "defensive" checks).

  This fell out of dcache_readdir work; the main point is to get rid of
  ->d_subdirs abuses in there. I've more followup cleanups, but I hadn't
  run those by Ian yet, so they can go next cycle"

* 'next.autofs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  autofs: don't bother with atomics for ino->count
  autofs_dir_rmdir(): check ino->count for deciding whether it's empty...
  autofs: get rid of pointless checks around ->count handling
  autofs_clear_leaf_automount_flags(): use ino->count instead of ->d_subdirs
This commit is contained in:
Linus Torvalds 2019-12-05 17:11:48 -08:00
commit b0d4beaa5a
3 changed files with 18 additions and 29 deletions

View File

@ -63,7 +63,7 @@ struct autofs_info {
struct autofs_sb_info *sbi;
unsigned long last_used;
atomic_t count;
int count;
kuid_t uid;
kgid_t gid;

View File

@ -211,7 +211,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
}
} else {
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 */
if (p == top)
@ -379,7 +379,7 @@ static struct dentry *should_expire(struct dentry *dentry,
/* Not a forced expire? */
if (!(how & AUTOFS_EXP_FORCED)) {
/* 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)
return NULL;
}
@ -396,7 +396,7 @@ static struct dentry *should_expire(struct dentry *dentry,
/* Not a forced expire? */
if (!(how & AUTOFS_EXP_FORCED)) {
/* 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)
return NULL;
}

View File

@ -569,10 +569,9 @@ static int autofs_dir_symlink(struct inode *dir,
d_add(dentry, inode);
dget(dentry);
atomic_inc(&ino->count);
ino->count++;
p_ino = autofs_dentry_ino(dentry->d_parent);
if (p_ino && !IS_ROOT(dentry))
atomic_inc(&p_ino->count);
p_ino->count++;
dir->i_mtime = current_time(dir);
@ -610,11 +609,9 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry)
if (sbi->flags & AUTOFS_SBI_CATATONIC)
return -EACCES;
if (atomic_dec_and_test(&ino->count)) {
ino->count--;
p_ino = autofs_dentry_ino(dentry->d_parent);
if (p_ino && !IS_ROOT(dentry))
atomic_dec(&p_ino->count);
}
p_ino->count--;
dput(ino->dentry);
d_inode(dentry)->i_size = 0;
@ -660,7 +657,6 @@ static void autofs_set_leaf_automount_flags(struct dentry *dentry)
static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
{
struct list_head *d_child;
struct dentry *parent;
/* flags for dentrys in the root are handled elsewhere */
@ -673,10 +669,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
/* only consider parents below dentrys in the root */
if (IS_ROOT(parent->d_parent))
return;
d_child = &dentry->d_child;
/* Set parent managed if it's becoming empty */
if (d_child->next == &parent->d_subdirs &&
d_child->prev == &parent->d_subdirs)
if (autofs_dentry_ino(parent)->count == 2)
managed_dentry_set_managed(parent);
}
@ -698,11 +691,10 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
if (sbi->flags & AUTOFS_SBI_CATATONIC)
return -EACCES;
spin_lock(&sbi->lookup_lock);
if (!simple_empty(dentry)) {
spin_unlock(&sbi->lookup_lock);
if (ino->count != 1)
return -ENOTEMPTY;
}
spin_lock(&sbi->lookup_lock);
__autofs_add_expiring(dentry);
d_drop(dentry);
spin_unlock(&sbi->lookup_lock);
@ -710,11 +702,9 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
if (sbi->version < 5)
autofs_clear_leaf_automount_flags(dentry);
if (atomic_dec_and_test(&ino->count)) {
ino->count--;
p_ino = autofs_dentry_ino(dentry->d_parent);
if (p_ino && dentry->d_parent != dentry)
atomic_dec(&p_ino->count);
}
p_ino->count--;
dput(ino->dentry);
d_inode(dentry)->i_size = 0;
clear_nlink(d_inode(dentry));
@ -760,10 +750,9 @@ static int autofs_dir_mkdir(struct inode *dir,
autofs_set_leaf_automount_flags(dentry);
dget(dentry);
atomic_inc(&ino->count);
ino->count++;
p_ino = autofs_dentry_ino(dentry->d_parent);
if (p_ino && !IS_ROOT(dentry))
atomic_inc(&p_ino->count);
p_ino->count++;
inc_nlink(dir);
dir->i_mtime = current_time(dir);