diff mbox series

[2/3] ovl: Make ovl_dentry_weird() accept casefold dentries

Message ID 20250409-tonyk-overlayfs-v1-2-3991616fe9a3@igalia.com (mailing list archive)
State New
Headers show
Series ovl: Enable support for casefold filesystems | expand

Commit Message

André Almeida April 9, 2025, 3 p.m. UTC
ovl_dentry_weird() is used to avoid problems with filesystems that has
their d_hash and d_compare implementations. Create an exception for this
function, where only casefold filesystems are eligible to use their own
d_hash and d_compare functions, allowing to support casefold
filesystems.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 fs/overlayfs/namei.c     | 11 ++++++-----
 fs/overlayfs/overlayfs.h |  2 +-
 fs/overlayfs/params.c    |  3 ++-
 fs/overlayfs/util.c      | 12 +++++++-----
 4 files changed, 16 insertions(+), 12 deletions(-)

Comments

Amir Goldstein April 9, 2025, 5:11 p.m. UTC | #1
On Wed, Apr 9, 2025 at 5:01 PM André Almeida <andrealmeid@igalia.com> wrote:
>
> ovl_dentry_weird() is used to avoid problems with filesystems that has
> their d_hash and d_compare implementations. Create an exception for this
> function, where only casefold filesystems are eligible to use their own
> d_hash and d_compare functions, allowing to support casefold
> filesystems.

What do you mean by this sentence?
Any casefold fs can be on any layer?
All layers on the same casefold sb? same casefold fstype?


>
> Signed-off-by: André Almeida <andrealmeid@igalia.com>
> ---
>  fs/overlayfs/namei.c     | 11 ++++++-----
>  fs/overlayfs/overlayfs.h |  2 +-
>  fs/overlayfs/params.c    |  3 ++-
>  fs/overlayfs/util.c      | 12 +++++++-----
>  4 files changed, 16 insertions(+), 12 deletions(-)
>
> diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
> index be5c65d6f8484b1fba6b3fee379ba1d034c0df8a..140bc609ffebe00151cbb446720f5106dbeb2ef2 100644
> --- a/fs/overlayfs/namei.c
> +++ b/fs/overlayfs/namei.c
> @@ -192,7 +192,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
>                 return real;
>         }
>
> -       if (ovl_dentry_weird(real)) {
> +       if (ovl_dentry_weird(real, ofs)) {
>                 dput(real);
>                 return NULL;
>         }
> @@ -244,7 +244,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
>                 goto out_err;
>         }
>
> -       if (ovl_dentry_weird(this)) {
> +       if (ovl_dentry_weird(this, ofs)) {
>                 /* Don't support traversing automounts and other weirdness */
>                 err = -EREMOTE;
>                 goto out_err;
> @@ -365,6 +365,7 @@ static int ovl_lookup_data_layer(struct dentry *dentry, const char *redirect,
>                                  struct path *datapath)
>  {
>         int err;
> +       struct ovl_fs *ovl = OVL_FS(layer->fs->sb);

ofs please

>
>         err = vfs_path_lookup(layer->mnt->mnt_root, layer->mnt, redirect,
>                         LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS | LOOKUP_NO_XDEV,
> @@ -376,7 +377,7 @@ static int ovl_lookup_data_layer(struct dentry *dentry, const char *redirect,
>                 return err;
>
>         err = -EREMOTE;
> -       if (ovl_dentry_weird(datapath->dentry))
> +       if (ovl_dentry_weird(datapath->dentry, ovl))
>                 goto out_path_put;
>
>         err = -ENOENT;
> @@ -767,7 +768,7 @@ struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh)
>
>         if (ovl_is_whiteout(index))
>                 err = -ESTALE;
> -       else if (ovl_dentry_weird(index))
> +       else if (ovl_dentry_weird(index, ofs))
>                 err = -EIO;
>         else
>                 return index;
> @@ -815,7 +816,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
>                 dput(index);
>                 index = ERR_PTR(-ESTALE);
>                 goto out;
> -       } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) ||
> +       } else if (ovl_dentry_weird(index, ofs) || ovl_is_whiteout(index) ||
>                    inode_wrong_type(inode, d_inode(origin)->i_mode)) {
>                 /*
>                  * Index should always be of the same file type as origin
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index 6f2f8f4cfbbc177fbd5441483395d7ff72efe332..f3de013517598c44c15ca9f950f6c2f0a5c2084b 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -445,7 +445,7 @@ void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry,
>                            struct ovl_entry *oe);
>  void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
>                            struct ovl_entry *oe, unsigned int mask);
> -bool ovl_dentry_weird(struct dentry *dentry);
> +bool ovl_dentry_weird(struct dentry *dentry, struct ovl_fs *ovl);
>  enum ovl_path_type ovl_path_type(struct dentry *dentry);
>  void ovl_path_upper(struct dentry *dentry, struct path *path);
>  void ovl_path_lower(struct dentry *dentry, struct path *path);
> diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
> index 6759f7d040c89d3b3c01572579c854a900411157..459e8bddf1777c12c9fa0bdfc150e2ea22eaafc3 100644
> --- a/fs/overlayfs/params.c
> +++ b/fs/overlayfs/params.c
> @@ -277,6 +277,7 @@ static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
>                                enum ovl_opt layer, const char *name, bool upper)
>  {
>         struct ovl_fs_context *ctx = fc->fs_private;
> +       struct ovl_fs *ovl = fc->s_fs_info;

ofs pls

>
>         if (!d_is_dir(path->dentry))
>                 return invalfc(fc, "%s is not a directory", name);
> @@ -290,7 +291,7 @@ static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
>         if (sb_has_encoding(path->mnt->mnt_sb))
>                 return invalfc(fc, "case-insensitive capable filesystem on %s not supported", name);
>
> -       if (ovl_dentry_weird(path->dentry))
> +       if (ovl_dentry_weird(path->dentry, ovl))
>                 return invalfc(fc, "filesystem on %s not supported", name);
>
>         /*
> diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> index 0819c739cc2ffce0dfefa84d3ff8f9f103eec191..4dd523a1a13ab0a6cf51d967d0b712873e6d8580 100644
> --- a/fs/overlayfs/util.c
> +++ b/fs/overlayfs/util.c
> @@ -200,15 +200,17 @@ void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
>         spin_unlock(&dentry->d_lock);
>  }
>
> -bool ovl_dentry_weird(struct dentry *dentry)
> +bool ovl_dentry_weird(struct dentry *dentry, struct ovl_fs *ovl)

ovl_fs *ofs as first argument please

>  {
> +       int flags = DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT;
> +
> +       if (!ovl->casefold)
> +               flags |= DCACHE_OP_HASH | DCACHE_OP_COMPARE;
> +
>         if (!d_can_lookup(dentry) && !d_is_file(dentry) && !d_is_symlink(dentry))
>                 return true;
>
> -       return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
> -                                 DCACHE_MANAGE_TRANSIT |
> -                                 DCACHE_OP_HASH |
> -                                 DCACHE_OP_COMPARE);
> +       return dentry->d_flags & flags;
>  }
>
>  enum ovl_path_type ovl_path_type(struct dentry *dentry)
>
> --
> 2.49.0
>
diff mbox series

Patch

diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index be5c65d6f8484b1fba6b3fee379ba1d034c0df8a..140bc609ffebe00151cbb446720f5106dbeb2ef2 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -192,7 +192,7 @@  struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
 		return real;
 	}
 
-	if (ovl_dentry_weird(real)) {
+	if (ovl_dentry_weird(real, ofs)) {
 		dput(real);
 		return NULL;
 	}
@@ -244,7 +244,7 @@  static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
 		goto out_err;
 	}
 
-	if (ovl_dentry_weird(this)) {
+	if (ovl_dentry_weird(this, ofs)) {
 		/* Don't support traversing automounts and other weirdness */
 		err = -EREMOTE;
 		goto out_err;
@@ -365,6 +365,7 @@  static int ovl_lookup_data_layer(struct dentry *dentry, const char *redirect,
 				 struct path *datapath)
 {
 	int err;
+	struct ovl_fs *ovl = OVL_FS(layer->fs->sb);
 
 	err = vfs_path_lookup(layer->mnt->mnt_root, layer->mnt, redirect,
 			LOOKUP_BENEATH | LOOKUP_NO_SYMLINKS | LOOKUP_NO_XDEV,
@@ -376,7 +377,7 @@  static int ovl_lookup_data_layer(struct dentry *dentry, const char *redirect,
 		return err;
 
 	err = -EREMOTE;
-	if (ovl_dentry_weird(datapath->dentry))
+	if (ovl_dentry_weird(datapath->dentry, ovl))
 		goto out_path_put;
 
 	err = -ENOENT;
@@ -767,7 +768,7 @@  struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh)
 
 	if (ovl_is_whiteout(index))
 		err = -ESTALE;
-	else if (ovl_dentry_weird(index))
+	else if (ovl_dentry_weird(index, ofs))
 		err = -EIO;
 	else
 		return index;
@@ -815,7 +816,7 @@  struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
 		dput(index);
 		index = ERR_PTR(-ESTALE);
 		goto out;
-	} else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) ||
+	} else if (ovl_dentry_weird(index, ofs) || ovl_is_whiteout(index) ||
 		   inode_wrong_type(inode, d_inode(origin)->i_mode)) {
 		/*
 		 * Index should always be of the same file type as origin
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 6f2f8f4cfbbc177fbd5441483395d7ff72efe332..f3de013517598c44c15ca9f950f6c2f0a5c2084b 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -445,7 +445,7 @@  void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry,
 			   struct ovl_entry *oe);
 void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
 			   struct ovl_entry *oe, unsigned int mask);
-bool ovl_dentry_weird(struct dentry *dentry);
+bool ovl_dentry_weird(struct dentry *dentry, struct ovl_fs *ovl);
 enum ovl_path_type ovl_path_type(struct dentry *dentry);
 void ovl_path_upper(struct dentry *dentry, struct path *path);
 void ovl_path_lower(struct dentry *dentry, struct path *path);
diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
index 6759f7d040c89d3b3c01572579c854a900411157..459e8bddf1777c12c9fa0bdfc150e2ea22eaafc3 100644
--- a/fs/overlayfs/params.c
+++ b/fs/overlayfs/params.c
@@ -277,6 +277,7 @@  static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
 			       enum ovl_opt layer, const char *name, bool upper)
 {
 	struct ovl_fs_context *ctx = fc->fs_private;
+	struct ovl_fs *ovl = fc->s_fs_info;
 
 	if (!d_is_dir(path->dentry))
 		return invalfc(fc, "%s is not a directory", name);
@@ -290,7 +291,7 @@  static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
 	if (sb_has_encoding(path->mnt->mnt_sb))
 		return invalfc(fc, "case-insensitive capable filesystem on %s not supported", name);
 
-	if (ovl_dentry_weird(path->dentry))
+	if (ovl_dentry_weird(path->dentry, ovl))
 		return invalfc(fc, "filesystem on %s not supported", name);
 
 	/*
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 0819c739cc2ffce0dfefa84d3ff8f9f103eec191..4dd523a1a13ab0a6cf51d967d0b712873e6d8580 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -200,15 +200,17 @@  void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
 	spin_unlock(&dentry->d_lock);
 }
 
-bool ovl_dentry_weird(struct dentry *dentry)
+bool ovl_dentry_weird(struct dentry *dentry, struct ovl_fs *ovl)
 {
+	int flags = DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT;
+
+	if (!ovl->casefold)
+		flags |= DCACHE_OP_HASH | DCACHE_OP_COMPARE;
+
 	if (!d_can_lookup(dentry) && !d_is_file(dentry) && !d_is_symlink(dentry))
 		return true;
 
-	return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
-				  DCACHE_MANAGE_TRANSIT |
-				  DCACHE_OP_HASH |
-				  DCACHE_OP_COMPARE);
+	return dentry->d_flags & flags;
 }
 
 enum ovl_path_type ovl_path_type(struct dentry *dentry)