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:
Коммит
b0d4beaa5a
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче