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 |
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 --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)
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(-)