Skip to content

Commit b0d4bea

Browse files
committed
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
2 parents da73fcd + 850d71a commit b0d4bea

File tree

3 files changed

+18
-29
lines changed

3 files changed

+18
-29
lines changed

fs/autofs/autofs_i.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct autofs_info {
6363

6464
struct autofs_sb_info *sbi;
6565
unsigned long last_used;
66-
atomic_t count;
66+
int count;
6767

6868
kuid_t uid;
6969
kgid_t gid;

fs/autofs/expire.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
211211
}
212212
} else {
213213
struct autofs_info *ino = autofs_dentry_ino(p);
214-
unsigned int ino_count = atomic_read(&ino->count);
214+
unsigned int ino_count = READ_ONCE(ino->count);
215215

216216
/* allow for dget above and top is already dgot */
217217
if (p == top)
@@ -379,7 +379,7 @@ static struct dentry *should_expire(struct dentry *dentry,
379379
/* Not a forced expire? */
380380
if (!(how & AUTOFS_EXP_FORCED)) {
381381
/* ref-walk currently on this dentry? */
382-
ino_count = atomic_read(&ino->count) + 1;
382+
ino_count = READ_ONCE(ino->count) + 1;
383383
if (d_count(dentry) > ino_count)
384384
return NULL;
385385
}
@@ -396,7 +396,7 @@ static struct dentry *should_expire(struct dentry *dentry,
396396
/* Not a forced expire? */
397397
if (!(how & AUTOFS_EXP_FORCED)) {
398398
/* ref-walk currently on this dentry? */
399-
ino_count = atomic_read(&ino->count) + 1;
399+
ino_count = READ_ONCE(ino->count) + 1;
400400
if (d_count(dentry) > ino_count)
401401
return NULL;
402402
}

fs/autofs/root.c

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -569,10 +569,9 @@ static int autofs_dir_symlink(struct inode *dir,
569569
d_add(dentry, inode);
570570

571571
dget(dentry);
572-
atomic_inc(&ino->count);
572+
ino->count++;
573573
p_ino = autofs_dentry_ino(dentry->d_parent);
574-
if (p_ino && !IS_ROOT(dentry))
575-
atomic_inc(&p_ino->count);
574+
p_ino->count++;
576575

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

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

613-
if (atomic_dec_and_test(&ino->count)) {
614-
p_ino = autofs_dentry_ino(dentry->d_parent);
615-
if (p_ino && !IS_ROOT(dentry))
616-
atomic_dec(&p_ino->count);
617-
}
612+
ino->count--;
613+
p_ino = autofs_dentry_ino(dentry->d_parent);
614+
p_ino->count--;
618615
dput(ino->dentry);
619616

620617
d_inode(dentry)->i_size = 0;
@@ -660,7 +657,6 @@ static void autofs_set_leaf_automount_flags(struct dentry *dentry)
660657

661658
static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
662659
{
663-
struct list_head *d_child;
664660
struct dentry *parent;
665661

666662
/* flags for dentrys in the root are handled elsewhere */
@@ -673,10 +669,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
673669
/* only consider parents below dentrys in the root */
674670
if (IS_ROOT(parent->d_parent))
675671
return;
676-
d_child = &dentry->d_child;
677-
/* Set parent managed if it's becoming empty */
678-
if (d_child->next == &parent->d_subdirs &&
679-
d_child->prev == &parent->d_subdirs)
672+
if (autofs_dentry_ino(parent)->count == 2)
680673
managed_dentry_set_managed(parent);
681674
}
682675

@@ -698,23 +691,20 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
698691
if (sbi->flags & AUTOFS_SBI_CATATONIC)
699692
return -EACCES;
700693

701-
spin_lock(&sbi->lookup_lock);
702-
if (!simple_empty(dentry)) {
703-
spin_unlock(&sbi->lookup_lock);
694+
if (ino->count != 1)
704695
return -ENOTEMPTY;
705-
}
696+
697+
spin_lock(&sbi->lookup_lock);
706698
__autofs_add_expiring(dentry);
707699
d_drop(dentry);
708700
spin_unlock(&sbi->lookup_lock);
709701

710702
if (sbi->version < 5)
711703
autofs_clear_leaf_automount_flags(dentry);
712704

713-
if (atomic_dec_and_test(&ino->count)) {
714-
p_ino = autofs_dentry_ino(dentry->d_parent);
715-
if (p_ino && dentry->d_parent != dentry)
716-
atomic_dec(&p_ino->count);
717-
}
705+
ino->count--;
706+
p_ino = autofs_dentry_ino(dentry->d_parent);
707+
p_ino->count--;
718708
dput(ino->dentry);
719709
d_inode(dentry)->i_size = 0;
720710
clear_nlink(d_inode(dentry));
@@ -760,10 +750,9 @@ static int autofs_dir_mkdir(struct inode *dir,
760750
autofs_set_leaf_automount_flags(dentry);
761751

762752
dget(dentry);
763-
atomic_inc(&ino->count);
753+
ino->count++;
764754
p_ino = autofs_dentry_ino(dentry->d_parent);
765-
if (p_ino && !IS_ROOT(dentry))
766-
atomic_inc(&p_ino->count);
755+
p_ino->count++;
767756
inc_nlink(dir);
768757
dir->i_mtime = current_time(dir);
769758

0 commit comments

Comments
 (0)