lkml.org 
[lkml]   [2022]   [Jun]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH 6/6] autofs: manage dentry info mount trigger flags better
From
Date
The autofs managed dentry flags are left set for dentries in an
autofs mount directory regardless of whether the dentry should
trigger a mount (a non-empty directory or a symlink doesn't).

But properly managing these flags can sometimes provide the loop
termination condition needed when following mounts which now uses
an -EISDIR return.

Signed-off-by: Ian Kent <raven@themaw.net>
---
fs/autofs/root.c | 97 +++++++++++++++++++++++-------------------------------
1 file changed, 42 insertions(+), 55 deletions(-)

diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index ca03c1cae2be..d140d06c5bc6 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -529,9 +529,8 @@ static struct dentry *autofs_lookup(struct inode *dir,

spin_lock(&sbi->lookup_lock);
spin_lock(&dentry->d_lock);
- /* Mark entries in the root as mount triggers */
- if (IS_ROOT(dentry->d_parent) &&
- autofs_type_indirect(sbi->type))
+ /* Mark indirect mount entries as mount triggers */
+ if (autofs_type_indirect(sbi->type))
__managed_dentry_set_managed(dentry);
dentry->d_fsdata = ino;
ino->dentry = dentry;
@@ -567,7 +566,9 @@ static int autofs_dir_symlink(struct user_namespace *mnt_userns,
struct inode *dir, struct dentry *dentry,
const char *symname)
{
+ struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
struct autofs_info *ino = autofs_dentry_ino(dentry);
+ struct dentry *parent = dentry->d_parent;
struct autofs_info *p_ino;
struct inode *inode;
size_t size = strlen(symname);
@@ -602,6 +603,16 @@ static int autofs_dir_symlink(struct user_namespace *mnt_userns,

dir->i_mtime = current_time(dir);

+ /* Symlinks don't trigger mounts */
+ managed_dentry_clear_managed(dentry);
+ /* Clear containing directory flags if it's no longer empty */
+ if (autofs_dentry_ino(parent)->count == 2) {
+ /* Don't set or clear type indirect root */
+ if (!IS_ROOT(parent) ||
+ !autofs_type_indirect(sbi->type))
+ managed_dentry_clear_managed(parent);
+ }
+
return 0;
}

@@ -624,12 +635,21 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
struct autofs_info *ino = autofs_dentry_ino(dentry);
+ struct dentry *parent = dentry->d_parent;
struct autofs_info *p_ino;

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

+ /* Set containing directory flags if it's now empty */
+ if (autofs_dentry_ino(parent)->count == 1) {
+ /* Don't set or clear type indirect root */
+ if (!IS_ROOT(parent) ||
+ !autofs_type_indirect(sbi->type))
+ managed_dentry_set_managed(parent);
+ }
+
d_inode(dentry)->i_size = 0;
clear_nlink(d_inode(dentry));

@@ -643,56 +663,11 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry)
return 0;
}

-/*
- * Version 4 of autofs provides a pseudo direct mount implementation
- * that relies on directories at the leaves of a directory tree under
- * an indirect mount to trigger mounts. To allow for this we need to
- * set the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags on the leaves
- * of the directory tree. There is no need to clear the automount flag
- * following a mount or restore it after an expire because these mounts
- * are always covered. However, it is necessary to ensure that these
- * flags are clear on non-empty directories to avoid unnecessary calls
- * during path walks.
- */
-static void autofs_set_leaf_automount_flags(struct dentry *dentry)
-{
- struct dentry *parent;
-
- /* root and dentrys in the root are already handled */
- if (IS_ROOT(dentry->d_parent))
- return;
-
- managed_dentry_set_managed(dentry);
-
- parent = dentry->d_parent;
- /* only consider parents below dentrys in the root */
- if (IS_ROOT(parent->d_parent))
- return;
- managed_dentry_clear_managed(parent);
-}
-
-static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
-{
- struct dentry *parent;
-
- /* flags for dentrys in the root are handled elsewhere */
- if (IS_ROOT(dentry->d_parent))
- return;
-
- managed_dentry_clear_managed(dentry);
-
- parent = dentry->d_parent;
- /* only consider parents below dentrys in the root */
- if (IS_ROOT(parent->d_parent))
- return;
- if (autofs_dentry_ino(parent)->count == 2)
- managed_dentry_set_managed(parent);
-}
-
static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
struct autofs_info *ino = autofs_dentry_ino(dentry);
+ struct dentry *parent = dentry->d_parent;
struct autofs_info *p_ino;

pr_debug("dentry %p, removing %pd\n", dentry, dentry);
@@ -705,15 +680,20 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
d_drop(dentry);
spin_unlock(&sbi->lookup_lock);

- if (sbi->version < 5)
- autofs_clear_leaf_automount_flags(dentry);
-
p_ino = autofs_dentry_ino(dentry->d_parent);
p_ino->count--;
dput(ino->dentry);
d_inode(dentry)->i_size = 0;
clear_nlink(d_inode(dentry));

+ /* Set containing directory flags if it's now empty */
+ if (autofs_dentry_ino(parent)->count == 1) {
+ /* Don't set or clear type indirect root */
+ if (!IS_ROOT(parent) ||
+ !autofs_type_indirect(sbi->type))
+ managed_dentry_set_managed(parent);
+ }
+
if (dir->i_nlink)
drop_nlink(dir);

@@ -726,6 +706,7 @@ static int autofs_dir_mkdir(struct user_namespace *mnt_userns,
{
struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
struct autofs_info *ino = autofs_dentry_ino(dentry);
+ struct dentry *parent = dentry->d_parent;
struct autofs_info *p_ino;
struct inode *inode;

@@ -742,15 +723,21 @@ static int autofs_dir_mkdir(struct user_namespace *mnt_userns,
return -ENOMEM;
d_add(dentry, inode);

- if (sbi->version < 5)
- autofs_set_leaf_automount_flags(dentry);
-
dget(dentry);
p_ino = autofs_dentry_ino(dentry->d_parent);
p_ino->count++;
inc_nlink(dir);
dir->i_mtime = current_time(dir);

+ managed_dentry_set_managed(dentry);
+ /* Clear containing directory flags if it's no longer empty */
+ if (autofs_dentry_ino(parent)->count == 2) {
+ /* Don't set or clear type indirect root */
+ if (!IS_ROOT(parent) ||
+ !autofs_type_indirect(sbi->type))
+ managed_dentry_clear_managed(parent);
+ }
+
return 0;
}


\
 
 \ /
  Last update: 2022-06-17 07:37    [W:0.035 / U:0.084 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site