diff mbox series

[3/4] ovl: decide if revalidate needed on a per-dentry bases

Message ID 20200131115004.17410-4-mszeredi@redhat.com (mailing list archive)
State New, archived
Headers show
Series ovl: allow virtiofs as upper | expand

Commit Message

Miklos Szeredi Jan. 31, 2020, 11:50 a.m. UTC
Allow completely skipping ->revalidate() on a per-dentry bases, in case the
underlying layers used for a dentry do not themselves have ->revalidate().

E.g. negative overlay dentry has no underlying layers, hence revalidate is
unnecessary.  Or if lower layer is remote but overlay dentry is pure-upper,
then can skip revalidate.

The following places need to update whether the dentry needs revalidate or
not:

 - fill-super (root dentry)
 - lookup
 - create
 - fh_to_dentry

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
 fs/overlayfs/dir.c       |  3 +++
 fs/overlayfs/export.c    |  2 ++
 fs/overlayfs/namei.c     |  3 +++
 fs/overlayfs/overlayfs.h |  3 ++-
 fs/overlayfs/super.c     | 23 +++++++----------------
 fs/overlayfs/util.c      | 15 ++++++++++++---
 6 files changed, 29 insertions(+), 20 deletions(-)

Comments

Amir Goldstein Jan. 31, 2020, 2:53 p.m. UTC | #1
On Fri, Jan 31, 2020 at 1:51 PM Miklos Szeredi <mszeredi@redhat.com> wrote:
>
> Allow completely skipping ->revalidate() on a per-dentry bases, in case the
> underlying layers used for a dentry do not themselves have ->revalidate().
>
> E.g. negative overlay dentry has no underlying layers, hence revalidate is
> unnecessary.  Or if lower layer is remote but overlay dentry is pure-upper,
> then can skip revalidate.
>
> The following places need to update whether the dentry needs revalidate or
> not:
>
>  - fill-super (root dentry)
>  - lookup
>  - create
>  - fh_to_dentry
>
> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> ---
>  fs/overlayfs/dir.c       |  3 +++
>  fs/overlayfs/export.c    |  2 ++
>  fs/overlayfs/namei.c     |  3 +++
>  fs/overlayfs/overlayfs.h |  3 ++-
>  fs/overlayfs/super.c     | 23 +++++++----------------
>  fs/overlayfs/util.c      | 15 ++++++++++++---
>  6 files changed, 29 insertions(+), 20 deletions(-)
>
> diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> index 8e57d5372b8f..b3471ef51440 100644
> --- a/fs/overlayfs/dir.c
> +++ b/fs/overlayfs/dir.c
> @@ -243,6 +243,9 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
>
>         ovl_dir_modified(dentry->d_parent, false);
>         ovl_dentry_set_upper_alias(dentry);
> +       ovl_dentry_update_reval(dentry, newdentry,
> +                       DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
> +
>         if (!hardlink) {
>                 /*
>                  * ovl_obtain_alias() can be called after ovl_create_real()
> diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
> index 6f54d70cef27..a58b3d9b06b9 100644
> --- a/fs/overlayfs/export.c
> +++ b/fs/overlayfs/export.c
> @@ -324,6 +324,8 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
>                 if (upper_alias)
>                         ovl_dentry_set_upper_alias(dentry);
>         }
> +       ovl_dentry_update_reval(dentry, upper,
> +                       DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
>
>         return d_instantiate_anon(dentry, inode);
>
> diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
> index a5b998a93a24..76e61cc27822 100644
> --- a/fs/overlayfs/namei.c
> +++ b/fs/overlayfs/namei.c
> @@ -1077,6 +1077,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>                         goto out_free_oe;
>         }
>
> +       ovl_dentry_update_reval(dentry, upperdentry,
> +                       DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
> +
>         revert_creds(old_cred);
>         if (origin_path) {
>                 dput(origin_path->dentry);
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index 3623d28aa4fa..68124a4f8f9b 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -229,7 +229,8 @@ struct dentry *ovl_indexdir(struct super_block *sb);
>  bool ovl_index_all(struct super_block *sb);
>  bool ovl_verify_lower(struct super_block *sb);
>  struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
> -bool ovl_dentry_remote(struct dentry *dentry);
> +void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *upperdentry,
> +                            unsigned int mask);
>  bool ovl_dentry_weird(struct dentry *dentry);
>  enum ovl_path_type ovl_path_type(struct dentry *dentry);
>  void ovl_path_upper(struct dentry *dentry, struct path *path);
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index 7e294bf719ff..26d4153240a8 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -158,11 +158,6 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
>  static const struct dentry_operations ovl_dentry_operations = {
>         .d_release = ovl_dentry_release,
>         .d_real = ovl_d_real,
> -};
> -
> -static const struct dentry_operations ovl_reval_dentry_operations = {
> -       .d_release = ovl_dentry_release,
> -       .d_real = ovl_d_real,
>         .d_revalidate = ovl_dentry_revalidate,
>         .d_weak_revalidate = ovl_dentry_weak_revalidate,
>  };
> @@ -779,7 +774,7 @@ static int ovl_check_namelen(struct path *path, struct ovl_fs *ofs,
>  }
>
>  static int ovl_lower_dir(const char *name, struct path *path,
> -                        struct ovl_fs *ofs, int *stack_depth, bool *remote)
> +                        struct ovl_fs *ofs, int *stack_depth)
>  {
>         int fh_type;
>         int err;
> @@ -794,9 +789,6 @@ static int ovl_lower_dir(const char *name, struct path *path,
>
>         *stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth);
>
> -       if (ovl_dentry_remote(path->dentry))
> -               *remote = true;
> -
>         /*
>          * The inodes index feature and NFS export need to encode and decode
>          * file handles, so they require that all layers support them.
> @@ -1439,7 +1431,6 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
>         char *lowertmp, *lower;
>         struct path *stack = NULL;
>         unsigned int stacklen, numlower = 0, i;
> -       bool remote = false;
>         struct ovl_entry *oe;
>
>         err = -ENOMEM;
> @@ -1471,7 +1462,7 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
>         lower = lowertmp;
>         for (numlower = 0; numlower < stacklen; numlower++) {
>                 err = ovl_lower_dir(lower, &stack[numlower], ofs,
> -                                   &sb->s_stack_depth, &remote);
> +                                   &sb->s_stack_depth);
>                 if (err)
>                         goto out_err;
>
> @@ -1499,11 +1490,6 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
>                 oe->lowerstack[i].layer = &ofs->layers[i+1];
>         }
>
> -       if (remote)
> -               sb->s_d_op = &ovl_reval_dentry_operations;
> -       else
> -               sb->s_d_op = &ovl_dentry_operations;
> -
>  out:
>         for (i = 0; i < numlower; i++)
>                 path_put(&stack[i]);
> @@ -1597,6 +1583,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
>         struct cred *cred;
>         int err;
>
> +       sb->s_d_op = &ovl_dentry_operations;
> +
>         err = -ENOMEM;
>         ofs = kzalloc(sizeof(struct ovl_fs), GFP_KERNEL);
>         if (!ofs)
> @@ -1724,6 +1712,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
>         ovl_inode_init(d_inode(root_dentry), upperpath.dentry,
>                        ovl_dentry_lower(root_dentry), NULL);
>
> +       ovl_dentry_update_reval(root_dentry, upperpath.dentry,
> +                               DCACHE_OP_WEAK_REVALIDATE);
> +
>         sb->s_root = root_dentry;
>
>         return 0;
> diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> index 67cd2866aaa2..3ad8fb291f7d 100644
> --- a/fs/overlayfs/util.c
> +++ b/fs/overlayfs/util.c
> @@ -90,10 +90,19 @@ struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
>         return oe;
>  }
>
> -bool ovl_dentry_remote(struct dentry *dentry)

Removed too early. It still has users.
Otherwise looks ok.

Thanks,
Amir.
Miklos Szeredi Jan. 31, 2020, 3:15 p.m. UTC | #2
> > diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> > index 67cd2866aaa2..3ad8fb291f7d 100644
> > --- a/fs/overlayfs/util.c
> > +++ b/fs/overlayfs/util.c
> > @@ -90,10 +90,19 @@ struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
> >         return oe;
> >  }
> >
> > -bool ovl_dentry_remote(struct dentry *dentry)
>
> Removed too early. It still has users.
> Otherwise looks ok.

Thanks, fixed ones pushed to @ovl-remote-upper-v2.

Thanks,
Miklos
diff mbox series

Patch

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 8e57d5372b8f..b3471ef51440 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -243,6 +243,9 @@  static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
 
 	ovl_dir_modified(dentry->d_parent, false);
 	ovl_dentry_set_upper_alias(dentry);
+	ovl_dentry_update_reval(dentry, newdentry,
+			DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
+
 	if (!hardlink) {
 		/*
 		 * ovl_obtain_alias() can be called after ovl_create_real()
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
index 6f54d70cef27..a58b3d9b06b9 100644
--- a/fs/overlayfs/export.c
+++ b/fs/overlayfs/export.c
@@ -324,6 +324,8 @@  static struct dentry *ovl_obtain_alias(struct super_block *sb,
 		if (upper_alias)
 			ovl_dentry_set_upper_alias(dentry);
 	}
+	ovl_dentry_update_reval(dentry, upper,
+			DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
 
 	return d_instantiate_anon(dentry, inode);
 
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index a5b998a93a24..76e61cc27822 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -1077,6 +1077,9 @@  struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 			goto out_free_oe;
 	}
 
+	ovl_dentry_update_reval(dentry, upperdentry,
+			DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
+
 	revert_creds(old_cred);
 	if (origin_path) {
 		dput(origin_path->dentry);
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 3623d28aa4fa..68124a4f8f9b 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -229,7 +229,8 @@  struct dentry *ovl_indexdir(struct super_block *sb);
 bool ovl_index_all(struct super_block *sb);
 bool ovl_verify_lower(struct super_block *sb);
 struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
-bool ovl_dentry_remote(struct dentry *dentry);
+void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *upperdentry,
+			     unsigned int mask);
 bool ovl_dentry_weird(struct dentry *dentry);
 enum ovl_path_type ovl_path_type(struct dentry *dentry);
 void ovl_path_upper(struct dentry *dentry, struct path *path);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 7e294bf719ff..26d4153240a8 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -158,11 +158,6 @@  static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
 static const struct dentry_operations ovl_dentry_operations = {
 	.d_release = ovl_dentry_release,
 	.d_real = ovl_d_real,
-};
-
-static const struct dentry_operations ovl_reval_dentry_operations = {
-	.d_release = ovl_dentry_release,
-	.d_real = ovl_d_real,
 	.d_revalidate = ovl_dentry_revalidate,
 	.d_weak_revalidate = ovl_dentry_weak_revalidate,
 };
@@ -779,7 +774,7 @@  static int ovl_check_namelen(struct path *path, struct ovl_fs *ofs,
 }
 
 static int ovl_lower_dir(const char *name, struct path *path,
-			 struct ovl_fs *ofs, int *stack_depth, bool *remote)
+			 struct ovl_fs *ofs, int *stack_depth)
 {
 	int fh_type;
 	int err;
@@ -794,9 +789,6 @@  static int ovl_lower_dir(const char *name, struct path *path,
 
 	*stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth);
 
-	if (ovl_dentry_remote(path->dentry))
-		*remote = true;
-
 	/*
 	 * The inodes index feature and NFS export need to encode and decode
 	 * file handles, so they require that all layers support them.
@@ -1439,7 +1431,6 @@  static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 	char *lowertmp, *lower;
 	struct path *stack = NULL;
 	unsigned int stacklen, numlower = 0, i;
-	bool remote = false;
 	struct ovl_entry *oe;
 
 	err = -ENOMEM;
@@ -1471,7 +1462,7 @@  static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 	lower = lowertmp;
 	for (numlower = 0; numlower < stacklen; numlower++) {
 		err = ovl_lower_dir(lower, &stack[numlower], ofs,
-				    &sb->s_stack_depth, &remote);
+				    &sb->s_stack_depth);
 		if (err)
 			goto out_err;
 
@@ -1499,11 +1490,6 @@  static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 		oe->lowerstack[i].layer = &ofs->layers[i+1];
 	}
 
-	if (remote)
-		sb->s_d_op = &ovl_reval_dentry_operations;
-	else
-		sb->s_d_op = &ovl_dentry_operations;
-
 out:
 	for (i = 0; i < numlower; i++)
 		path_put(&stack[i]);
@@ -1597,6 +1583,8 @@  static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 	struct cred *cred;
 	int err;
 
+	sb->s_d_op = &ovl_dentry_operations;
+
 	err = -ENOMEM;
 	ofs = kzalloc(sizeof(struct ovl_fs), GFP_KERNEL);
 	if (!ofs)
@@ -1724,6 +1712,9 @@  static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 	ovl_inode_init(d_inode(root_dentry), upperpath.dentry,
 		       ovl_dentry_lower(root_dentry), NULL);
 
+	ovl_dentry_update_reval(root_dentry, upperpath.dentry,
+				DCACHE_OP_WEAK_REVALIDATE);
+
 	sb->s_root = root_dentry;
 
 	return 0;
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 67cd2866aaa2..3ad8fb291f7d 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -90,10 +90,19 @@  struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
 	return oe;
 }
 
-bool ovl_dentry_remote(struct dentry *dentry)
+void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *upperdentry,
+			     unsigned int mask)
 {
-	return dentry->d_flags &
-		(DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
+	struct ovl_entry *oe = OVL_E(dentry);
+	unsigned int i, flags = 0;
+
+	for (i = 0; i < oe->numlower; i++)
+		flags |= oe->lowerstack[i].dentry->d_flags;
+
+	spin_lock(&dentry->d_lock);
+	dentry->d_flags &= ~mask;
+	dentry->d_flags |= flags & mask;
+	spin_unlock(&dentry->d_lock);
 }
 
 bool ovl_dentry_weird(struct dentry *dentry)