[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250805-tonyk-overlayfs-v2-1-0e54281da318@igalia.com>
Date: Tue, 05 Aug 2025 00:09:05 -0300
From: André Almeida <andrealmeid@...lia.com>
To: Miklos Szeredi <miklos@...redi.hu>, Amir Goldstein <amir73il@...il.com>,
Theodore Tso <tytso@....edu>, Gabriel Krisman Bertazi <krisman@...nel.org>
Cc: linux-unionfs@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-fsdevel@...r.kernel.org, Alexander Viro <viro@...iv.linux.org.uk>,
Christian Brauner <brauner@...nel.org>, Jan Kara <jack@...e.cz>,
kernel-dev@...lia.com,
André Almeida <andrealmeid@...lia.com>
Subject: [PATCH RFC v2 1/8] olv: Store casefold name for case-insentive
dentries
In order to make case-insentive mounting points work, overlayfs needs
the casefolded version of its dentries so the search and insertion in
the struct ovl_readdir_data's red-black compares the dentry names in a
case-insentive fashion.
If a dentry is casefolded, compute and store it's casefolded name and
it's Unicode map. If utf8_casefold() fails, set it's name pointer as
NULL so it can be ignored and fallback to the original name.
Signed-off-by: André Almeida <andrealmeid@...lia.com>
---
fs/overlayfs/readdir.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index b65cdfce31ce27172d28d879559f1008b9c87320..83bca1bcb0488461b08effa70b32ff2fefba134e 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -16,6 +16,8 @@
#include <linux/overflow.h>
#include "overlayfs.h"
+#define OVL_NAME_LEN 255
+
struct ovl_cache_entry {
unsigned int len;
unsigned int type;
@@ -27,6 +29,9 @@ struct ovl_cache_entry {
bool is_upper;
bool is_whiteout;
bool check_xwhiteout;
+ struct unicode_map *map;
+ char *cf_name;
+ int cf_len;
char name[];
};
@@ -50,6 +55,7 @@ struct ovl_readdir_data {
bool is_upper;
bool d_type_supported;
bool in_xwhiteouts_dir;
+ struct unicode_map *map;
};
struct ovl_dir_file {
@@ -166,6 +172,29 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd,
p->is_whiteout = false;
/* Defer check for overlay.whiteout to ovl_iterate() */
p->check_xwhiteout = rdd->in_xwhiteouts_dir && d_type == DT_REG;
+ p->map = rdd->map;
+ p->cf_name = NULL;
+
+ if (p->map && !is_dot_dotdot(name, len)) {
+ const struct qstr str = { .name = name, .len = len };
+ int ret;
+
+ p->cf_name = kmalloc(OVL_NAME_LEN, GFP_KERNEL);
+
+ if (!p->cf_name) {
+ kfree(p);
+ return NULL;
+ }
+
+ ret = utf8_casefold(p->map, &str, p->cf_name, OVL_NAME_LEN);
+
+ if (ret < 0) {
+ kfree(p->cf_name);
+ p->cf_name = NULL;
+ } else {
+ p->cf_len = ret;
+ }
+ }
if (d_type == DT_CHR) {
p->next_maybe_whiteout = rdd->first_maybe_whiteout;
@@ -223,8 +252,10 @@ void ovl_cache_free(struct list_head *list)
struct ovl_cache_entry *p;
struct ovl_cache_entry *n;
- list_for_each_entry_safe(p, n, list, l_node)
+ list_for_each_entry_safe(p, n, list, l_node) {
+ kfree(p->cf_name);
kfree(p);
+ }
INIT_LIST_HEAD(list);
}
@@ -357,12 +388,19 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list,
.list = list,
.root = root,
.is_lowest = false,
+ .map = NULL,
};
int idx, next;
const struct ovl_layer *layer;
for (idx = 0; idx != -1; idx = next) {
next = ovl_path_next(idx, dentry, &realpath, &layer);
+
+#if IS_ENABLED(CONFIG_UNICODE)
+ if (ovl_dentry_casefolded(realpath.dentry))
+ rdd.map = realpath.dentry->d_sb->s_encoding;
+#endif
+
rdd.is_upper = ovl_dentry_upper(dentry) == realpath.dentry;
rdd.in_xwhiteouts_dir = layer->has_xwhiteouts &&
ovl_dentry_has_xwhiteouts(dentry);
--
2.50.1
Powered by blists - more mailing lists