linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs
@ 2024-09-02 22:55 André Almeida
  2024-09-02 22:55 ` [PATCH v2 1/8] unicode: Fix utf8_load() error path André Almeida
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida

Hi,

This series is based on [0].

This patchset adds support for case-insesitive file names lookups in tmpfs. The
main difference from other casefold filesystems is that tmpfs has no information
on disk, just on RAM, so we can't use mkfs to create a case-insensitive tmpfs.
For this implementation, I opted to have a mount option for casefolding. The
rest of the patchset follows a similar approach as ext4 and f2fs.

* Use case (from the original cover letter)

The use case for this feature is similar to the use case for ext4, to
better support compatibility layers (like Wine), particularly in
combination with sandboxing/container tools (like Flatpak). Those
containerization tools can share a subset of the host filesystem with an
application. In the container, the root directory and any parent
directories required for a shared directory are on tmpfs, with the
shared directories bind-mounted into the container's view of the
filesystem.

If the host filesystem is using case-insensitive directories, then the
application can do lookups inside those directories in a
case-insensitive way, without this needing to be implemented in
user-space. However, if the host is only sharing a subset of a
case-insensitive directory with the application, then the parent
directories of the mount point will be part of the container's root
tmpfs. When the application tries to do case-insensitive lookups of
those parent directories on a case-sensitive tmpfs, the lookup will
fail.

For example, if /srv/games is a case-insensitive directory on the host,
then applications will expect /srv/games/Steam/Half-Life and
/srv/games/steam/half-life to be interchangeable; but if the
container framework is only sharing /srv/games/Steam/Half-Life and
/srv/games/Steam/Portal (and not the rest of /srv/games) with the
container, with /srv, /srv/games and /srv/games/Steam as part of the
container's tmpfs root, then making /srv/games a case-insensitive
directory inside the container would be necessary to meet that
expectation.

* Testing

I send a patch for xfstests to enable the casefold test (generic/556) for tmpfs.[1]
The test succeed.

You can test this patchset using:

  sudo mount -t tmpfs -o casefold=utf8-12.1.0 tmpfs mnt/

And making a dir case-insesitive:

  mkdir mnt/dir
  chattr +F mnt/dir

[0] https://lore.kernel.org/linux-fsdevel/20210323195941.69720-1-andrealmeid@collabora.com/
[1] https://lore.kernel.org/fstests/20240823173008.280917-1-andrealmeid@igalia.com/

Changes in v2:
 - Found and fixed a bug in utf8_load()
 - Created a helper for checking strict file names (Krisman)
 - Merged patch 1/ and 3/ together (Krisman)
 - Reworded the explanation about d_compare (Krisman)
 - Removed bool casefold from shmem_sb_info (Krisman)
 - Reworked d_add(dentry, NULL) to be called as d_add(dentry, inode) (Krisman)
 - Moved utf8_parse_version to common unicode code
 - Fixed some smatch/sparse warnings (kernel test bot/Dan Carpenter)
 v1: https://lore.kernel.org/linux-fsdevel/20240823173332.281211-1-andrealmeid@igalia.com/

André Almeida (8):
  unicode: Fix utf8_load() error path
  unicode: Create utf8_check_strict_name
  ext4: Use utf8_check_strict_name helper
  unicode: Recreate utf8_parse_version()
  tmpfs: Add casefold lookup support
  tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
  tmpfs: Expose filesystem features via sysfs
  docs: tmpfs: Add casefold options

 Documentation/filesystems/tmpfs.rst |  37 ++++++
 fs/ext4/namei.c                     |   3 +-
 fs/unicode/utf8-core.c              |  58 ++++++++-
 include/linux/shmem_fs.h            |   6 +-
 include/linux/unicode.h             |   5 +
 mm/shmem.c                          | 192 ++++++++++++++++++++++++++--
 6 files changed, 284 insertions(+), 17 deletions(-)

-- 
2.46.0


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v2 1/8] unicode: Fix utf8_load() error path
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-03 11:40   ` Theodore Ts'o
  2024-09-03 16:48   ` Gabriel Krisman Bertazi
  2024-09-02 22:55 ` [PATCH v2 2/8] unicode: Create utf8_check_strict_name André Almeida
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida

utf8_load() requests the symbol "utf8_data_table" and then checks if the
requested UTF-8 version is supported. If it's unsupported, it tries to
put the data table using symbol_put(). If an unsupported version is
requested, symbol_put() fails like this:

 kernel BUG at kernel/module/main.c:786!
 RIP: 0010:__symbol_put+0x93/0xb0
 Call Trace:
  <TASK>
  ? __die_body.cold+0x19/0x27
  ? die+0x2e/0x50
  ? do_trap+0xca/0x110
  ? do_error_trap+0x65/0x80
  ? __symbol_put+0x93/0xb0
  ? exc_invalid_op+0x51/0x70
  ? __symbol_put+0x93/0xb0
  ? asm_exc_invalid_op+0x1a/0x20
  ? __pfx_cmp_name+0x10/0x10
  ? __symbol_put+0x93/0xb0
  ? __symbol_put+0x62/0xb0
  utf8_load+0xf8/0x150

That happens because symbol_put() expects the unique string that
identify the symbol, instead of a pointer to the loaded symbol. Fix that
by using such string.

Fixes: 2b3d04787012 ("unicode: Add utf8-data module")
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 fs/unicode/utf8-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c
index 8395066341a4..0400824ef493 100644
--- a/fs/unicode/utf8-core.c
+++ b/fs/unicode/utf8-core.c
@@ -198,7 +198,7 @@ struct unicode_map *utf8_load(unsigned int version)
 	return um;
 
 out_symbol_put:
-	symbol_put(um->tables);
+	symbol_put(utf8_data_table);
 out_free_um:
 	kfree(um);
 	return ERR_PTR(-EINVAL);
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 2/8] unicode: Create utf8_check_strict_name
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
  2024-09-02 22:55 ` [PATCH v2 1/8] unicode: Fix utf8_load() error path André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-03  9:04   ` kernel test robot
                     ` (2 more replies)
  2024-09-02 22:55 ` [PATCH v2 3/8] ext4: Use utf8_check_strict_name helper André Almeida
                   ` (5 subsequent siblings)
  7 siblings, 3 replies; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida,
	Gabriel Krisman Bertazi

Create a helper function for filesystems do the checks required for
casefold directories and strict enconding.

Suggested-by: Gabriel Krisman Bertazi <gabriel@krisman.be>
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 fs/unicode/utf8-core.c  | 26 ++++++++++++++++++++++++++
 include/linux/unicode.h |  2 ++
 2 files changed, 28 insertions(+)

diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c
index 0400824ef493..4966e175ed71 100644
--- a/fs/unicode/utf8-core.c
+++ b/fs/unicode/utf8-core.c
@@ -214,3 +214,29 @@ void utf8_unload(struct unicode_map *um)
 }
 EXPORT_SYMBOL(utf8_unload);
 
+/**
+ * utf8_check_strict_name - Check if a given name is suitable for a directory
+ *
+ * This functions checks if the proposed filename is suitable for the parent
+ * directory. That means that only valid UTF-8 filenames will be accepted for
+ * casefold directories from filesystems created with the strict enconding flags.
+ * That also means that any name will be accepted for directories that doesn't
+ * have casefold enabled, or aren't being strict with the enconding.
+ *
+ * @inode: inode of the directory where the new file will be created
+ * @d_name: name of the new file
+ *
+ * Returns:
+ *  * True if the filename is suitable for this directory. It can be true if a
+ *  given name is not suitable for a strict enconding directory, but the
+ *  directory being used isn't strict
+ *  * False if the filename isn't suitable for this directory. This only happens
+ *  when a directory is casefolded and is strict about its encoding.
+ */
+bool utf8_check_strict_name(struct inode *dir, struct qstr *d_name)
+{
+	return !(IS_CASEFOLDED(dir) && dir->i_sb->s_encoding &&
+	       sb_has_strict_encoding(dir->i_sb) &&
+	       utf8_validate(dir->i_sb->s_encoding, d_name));
+}
+EXPORT_SYMBOL(utf8_check_strict_name);
diff --git a/include/linux/unicode.h b/include/linux/unicode.h
index 4d39e6e11a95..fb56fb5e686c 100644
--- a/include/linux/unicode.h
+++ b/include/linux/unicode.h
@@ -76,4 +76,6 @@ int utf8_casefold_hash(const struct unicode_map *um, const void *salt,
 struct unicode_map *utf8_load(unsigned int version);
 void utf8_unload(struct unicode_map *um);
 
+bool utf8_check_strict_name(struct inode *dir, struct qstr *d_name);
+
 #endif /* _LINUX_UNICODE_H */
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 3/8] ext4: Use utf8_check_strict_name helper
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
  2024-09-02 22:55 ` [PATCH v2 1/8] unicode: Fix utf8_load() error path André Almeida
  2024-09-02 22:55 ` [PATCH v2 2/8] unicode: Create utf8_check_strict_name André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-03 11:37   ` Theodore Ts'o
  2024-09-02 22:55 ` [PATCH v2 4/8] unicode: Recreate utf8_parse_version() André Almeida
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida,
	Gabriel Krisman Bertazi

Use the helper function to check the requeriments for casefold
directories using strict enconding.

Suggested-by: Gabriel Krisman Bertazi <gabriel@krisman.be>
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 fs/ext4/namei.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 6a95713f9193..067face4dc41 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2394,8 +2394,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
 		return -ENOKEY;
 
 #if IS_ENABLED(CONFIG_UNICODE)
-	if (sb_has_strict_encoding(sb) && IS_CASEFOLDED(dir) &&
-	    utf8_validate(sb->s_encoding, &dentry->d_name))
+	if (!utf8_check_strict_name(dir, &dentry->d_name))
 		return -EINVAL;
 #endif
 
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 4/8] unicode: Recreate utf8_parse_version()
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
                   ` (2 preceding siblings ...)
  2024-09-02 22:55 ` [PATCH v2 3/8] ext4: Use utf8_check_strict_name helper André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-03 11:41   ` Theodore Ts'o
  2024-09-02 22:55 ` [PATCH v2 5/8] tmpfs: Add casefold lookup support André Almeida
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida

All filesystems that currently support UTF-8 casefold can fetch the
UTF-8 version from the filesystem metadata stored on disk. They can get
the data stored and directly match it to a integer, so they can skip the
string parsing step, which motivated the removal of this function in the
first place.

However, for tmpfs, the only way to tell the kernel which UTF-8 version
we are about to use is via mount options, using a string. Re-introduce
utf8_parse_version() to be used by tmpfs.

This version differs from the original by skipping the intermediate step
of copying the version string to an auxiliary string before calling
match_token(). This versions calls match_token() in the argument string.

utf8_parse_version() was created by 9d53690f0d4 ("unicode: implement
higher level API for string handling") and later removed by 49bd03cc7e9
("unicode: pass a UNICODE_AGE() tripple to utf8_load").

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 fs/unicode/utf8-core.c  | 30 ++++++++++++++++++++++++++++++
 include/linux/unicode.h |  3 +++
 2 files changed, 33 insertions(+)

diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c
index 4966e175ed71..3e8afd637b28 100644
--- a/fs/unicode/utf8-core.c
+++ b/fs/unicode/utf8-core.c
@@ -240,3 +240,33 @@ bool utf8_check_strict_name(struct inode *dir, struct qstr *d_name)
 	       utf8_validate(dir->i_sb->s_encoding, d_name));
 }
 EXPORT_SYMBOL(utf8_check_strict_name);
+
+/**
+ * utf8_parse_version - Parse a UTF-8 version number from a string
+ *
+ * @version: input string
+ * @maj: output major version number
+ * @min: output minor version number
+ * @rev: output minor revision number
+ *
+ * Returns 0 on success, negative code on error
+ */
+int utf8_parse_version(char *version, unsigned int *maj,
+		       unsigned int *min, unsigned int *rev)
+{
+	substring_t args[3];
+	static const struct match_token token[] = {
+		{1, "%d.%d.%d"},
+		{0, NULL}
+	};
+
+	if (match_token(version, token, args) != 1)
+		return -EINVAL;
+
+	if (match_int(&args[0], maj) || match_int(&args[1], min) ||
+	    match_int(&args[2], rev))
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(utf8_parse_version);
diff --git a/include/linux/unicode.h b/include/linux/unicode.h
index fb56fb5e686c..724db2cd709d 100644
--- a/include/linux/unicode.h
+++ b/include/linux/unicode.h
@@ -78,4 +78,7 @@ void utf8_unload(struct unicode_map *um);
 
 bool utf8_check_strict_name(struct inode *dir, struct qstr *d_name);
 
+int utf8_parse_version(char *version, unsigned int *maj, unsigned int *min,
+		       unsigned int *rev);
+
 #endif /* _LINUX_UNICODE_H */
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 5/8] tmpfs: Add casefold lookup support
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
                   ` (3 preceding siblings ...)
  2024-09-02 22:55 ` [PATCH v2 4/8] unicode: Recreate utf8_parse_version() André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-03 16:08   ` Gabriel Krisman Bertazi
  2024-09-02 22:55 ` [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs André Almeida
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida

Enable casefold lookup in tmpfs, based on the enconding defined by
userspace. That means that instead of comparing byte per byte a file
name, it compares to a case-insensitive equivalent of the Unicode
string.

* Dcache handling

There's a special need when dealing with case-insensitive dentries.
First of all, we currently invalidated every negative casefold dentries.
That happens because currently VFS code has no proper support to deal
with that, giving that it could incorrectly reuse a previous filename
for a new file that has a casefold match. For instance, this could
happen:

$ mkdir DIR
$ rm -r DIR
$ mkdir dir
$ ls
DIR/

And would be perceived as inconsistency from userspace point of view,
because even that we match files in a case-insensitive manner, we still
honor whatever is the initial filename.

Along with that, tmpfs stores only the first equivalent name dentry used
in the dcache, preventing duplications of dentries in the dcache. The
d_compare() version for casefold files uses a normalized string, so the
filename under lookup will be compared to another normalized string for
the existing file, achieving a casefolded lookup.

* Enabling casefold via mount options

Most filesystems have their data stored in disk, so casefold option need
to be enabled when building a filesystem on a device (via mkfs).
However, as tmpfs is a RAM backed filesystem, there's no disk
information and thus no mkfs to store information about casefold.

For tmpfs, create casefold options for mounting. Userspace can then
enable casefold support for a mount point using:

$ mount -t tmpfs -o casefold=utf8-12.1.0 fs_name mount_dir/

Userspace must set what Unicode standard is aiming to. The available
options depends on what the kernel Unicode subsystem supports.

And for strict encoding:

$ mount -t tmpfs -o casefold=utf8-12.1.0,strict_encoding fs_name mount_dir/

Strict encoding means that tmpfs will refuse to create invalid UTF-8
sequences. When this option is not enabled, any invalid sequence will be
treated as an opaque byte sequence, ignoring the encoding thus not being
able to be looked up in a case-insensitive way.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 mm/shmem.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 111 insertions(+), 4 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 5a77acf6ac6a..0f918010bc54 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -40,6 +40,8 @@
 #include <linux/fs_parser.h>
 #include <linux/swapfile.h>
 #include <linux/iversion.h>
+#include <linux/unicode.h>
+#include <linux/parser.h>
 #include "swap.h"
 
 static struct vfsmount *shm_mnt __ro_after_init;
@@ -123,6 +125,8 @@ struct shmem_options {
 	bool noswap;
 	unsigned short quota_types;
 	struct shmem_quota_limits qlimits;
+	struct unicode_map *encoding;
+	bool strict_encoding;
 #define SHMEM_SEEN_BLOCKS 1
 #define SHMEM_SEEN_INODES 2
 #define SHMEM_SEEN_HUGE 4
@@ -3427,6 +3431,11 @@ shmem_mknod(struct mnt_idmap *idmap, struct inode *dir,
 	if (IS_ERR(inode))
 		return PTR_ERR(inode);
 
+#if IS_ENABLED(CONFIG_UNICODE)
+	if (!utf8_check_strict_name(dir, &dentry->d_name))
+		return -EINVAL;
+#endif
+
 	error = simple_acl_create(dir, inode);
 	if (error)
 		goto out_iput;
@@ -3442,7 +3451,12 @@ shmem_mknod(struct mnt_idmap *idmap, struct inode *dir,
 	dir->i_size += BOGO_DIRENT_SIZE;
 	inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
 	inode_inc_iversion(dir);
-	d_instantiate(dentry, inode);
+
+	if (IS_CASEFOLDED(dir))
+		d_add(dentry, inode);
+	else
+		d_instantiate(dentry, inode);
+
 	dget(dentry); /* Extra count - pin the dentry in core */
 	return error;
 
@@ -3533,7 +3547,10 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir,
 	inc_nlink(inode);
 	ihold(inode);	/* New dentry reference */
 	dget(dentry);	/* Extra pinning count for the created dentry */
-	d_instantiate(dentry, inode);
+	if (IS_CASEFOLDED(dir))
+		d_add(dentry, inode);
+	else
+		d_instantiate(dentry, inode);
 out:
 	return ret;
 }
@@ -3553,6 +3570,14 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
 	inode_inc_iversion(dir);
 	drop_nlink(inode);
 	dput(dentry);	/* Undo the count from "create" - does all the work */
+
+	/*
+	 * For now, VFS can't deal with case-insensitive negative dentries, so
+	 * we invalidate them
+	 */
+	if (IS_CASEFOLDED(dir))
+		d_invalidate(dentry);
+
 	return 0;
 }
 
@@ -3697,7 +3722,10 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	dir->i_size += BOGO_DIRENT_SIZE;
 	inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
 	inode_inc_iversion(dir);
-	d_instantiate(dentry, inode);
+	if (IS_CASEFOLDED(dir))
+		d_add(dentry, inode);
+	else
+		d_instantiate(dentry, inode);
 	dget(dentry);
 	return 0;
 
@@ -4050,6 +4078,8 @@ enum shmem_param {
 	Opt_usrquota_inode_hardlimit,
 	Opt_grpquota_block_hardlimit,
 	Opt_grpquota_inode_hardlimit,
+	Opt_casefold,
+	Opt_strict_encoding,
 };
 
 static const struct constant_table shmem_param_enums_huge[] = {
@@ -4081,9 +4111,47 @@ const struct fs_parameter_spec shmem_fs_parameters[] = {
 	fsparam_string("grpquota_block_hardlimit", Opt_grpquota_block_hardlimit),
 	fsparam_string("grpquota_inode_hardlimit", Opt_grpquota_inode_hardlimit),
 #endif
+	fsparam_string("casefold",	Opt_casefold),
+	fsparam_flag  ("strict_encoding", Opt_strict_encoding),
 	{}
 };
 
+#if IS_ENABLED(CONFIG_UNICODE)
+static int shmem_parse_opt_casefold(struct fs_context *fc, struct fs_parameter *param)
+{
+	struct shmem_options *ctx = fc->fs_private;
+	unsigned int maj = 0, min = 0, rev = 0, version_number;
+	char version[10];
+	int ret;
+	struct unicode_map *encoding;
+
+	if (strncmp(param->string, "utf8-", 5))
+		return invalfc(fc, "Only utf8 encondings are supported");
+	ret = strscpy(version, param->string + 5, sizeof(version));
+	if (ret < 0)
+		return invalfc(fc, "Invalid enconding argument: %s",
+			       param->string);
+
+	ret = utf8_parse_version(version, &maj, &min, &rev);
+	if (ret)
+		return invalfc(fc, "Invalid utf8 version: %s", version);
+	version_number = UNICODE_AGE(maj, min, rev);
+	encoding = utf8_load(version_number);
+	if (IS_ERR(encoding))
+		return invalfc(fc, "Invalid utf8 version: %s", version);
+	pr_info("tmpfs: Using encoding provided by mount options: %s\n",
+		param->string);
+	ctx->encoding = encoding;
+
+	return 0;
+}
+#else
+static int shmem_parse_opt_casefold(struct fs_context *fc, struct fs_parameter *param)
+{
+	return invalfc(fc, "tmpfs: No kernel support for casefold filesystems\n");
+}
+#endif
+
 static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
 {
 	struct shmem_options *ctx = fc->fs_private;
@@ -4242,6 +4310,11 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
 				       "Group quota inode hardlimit too large.");
 		ctx->qlimits.grpquota_ihardlimit = size;
 		break;
+	case Opt_casefold:
+		return shmem_parse_opt_casefold(fc, param);
+	case Opt_strict_encoding:
+		ctx->strict_encoding = true;
+		break;
 	}
 	return 0;
 
@@ -4471,6 +4544,11 @@ static void shmem_put_super(struct super_block *sb)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 
+#if IS_ENABLED(CONFIG_UNICODE)
+	if (sb->s_encoding)
+		utf8_unload(sb->s_encoding);
+#endif
+
 #ifdef CONFIG_TMPFS_QUOTA
 	shmem_disable_quotas(sb);
 #endif
@@ -4515,6 +4593,16 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
 	}
 	sb->s_export_op = &shmem_export_ops;
 	sb->s_flags |= SB_NOSEC | SB_I_VERSION;
+
+#if IS_ENABLED(CONFIG_UNICODE)
+	if (ctx->encoding) {
+		sb->s_encoding = ctx->encoding;
+		generic_set_sb_d_ops(sb);
+		if (ctx->strict_encoding)
+			sb->s_encoding_flags = SB_ENC_STRICT_MODE_FL;
+	}
+#endif
+
 #else
 	sb->s_flags |= SB_NOUSER;
 #endif
@@ -4704,11 +4792,28 @@ static const struct inode_operations shmem_inode_operations = {
 #endif
 };
 
+static struct dentry *shmem_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
+	if (dentry->d_name.len > NAME_MAX)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	/*
+	 * For now, VFS can't deal with case-insensitive negative dentries, so
+	 * we prevent them from being created
+	 */
+	if (IS_CASEFOLDED(dir))
+		return NULL;
+
+	d_add(dentry, NULL);
+
+	return NULL;
+}
+
 static const struct inode_operations shmem_dir_inode_operations = {
 #ifdef CONFIG_TMPFS
 	.getattr	= shmem_getattr,
 	.create		= shmem_create,
-	.lookup		= simple_lookup,
+	.lookup		= shmem_lookup,
 	.link		= shmem_link,
 	.unlink		= shmem_unlink,
 	.symlink	= shmem_symlink,
@@ -4791,6 +4896,8 @@ int shmem_init_fs_context(struct fs_context *fc)
 	ctx->uid = current_fsuid();
 	ctx->gid = current_fsgid();
 
+	ctx->encoding = NULL;
+
 	fc->fs_private = ctx;
 	fc->ops = &shmem_fs_context_ops;
 	return 0;
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
                   ` (4 preceding siblings ...)
  2024-09-02 22:55 ` [PATCH v2 5/8] tmpfs: Add casefold lookup support André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-03  9:04   ` kernel test robot
                     ` (2 more replies)
  2024-09-02 22:55 ` [PATCH v2 7/8] tmpfs: Expose filesystem features via sysfs André Almeida
  2024-09-02 22:55 ` [PATCH v2 8/8] docs: tmpfs: Add casefold options André Almeida
  7 siblings, 3 replies; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida

Enable setting flag FS_CASEFOLD_FL for tmpfs directories, when tmpfs is
mounted with casefold support. A special check is need for this flag,
since it can't be set for non-empty directories.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 include/linux/shmem_fs.h |  6 +++---
 mm/shmem.c               | 40 +++++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 1d06b1e5408a..8367ca2b99d9 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -42,10 +42,10 @@ struct shmem_inode_info {
 	struct inode		vfs_inode;
 };
 
-#define SHMEM_FL_USER_VISIBLE		FS_FL_USER_VISIBLE
+#define SHMEM_FL_USER_VISIBLE		(FS_FL_USER_VISIBLE | FS_CASEFOLD_FL)
 #define SHMEM_FL_USER_MODIFIABLE \
-	(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL)
-#define SHMEM_FL_INHERITED		(FS_NODUMP_FL | FS_NOATIME_FL)
+	(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL | FS_CASEFOLD_FL)
+#define SHMEM_FL_INHERITED		(FS_NODUMP_FL | FS_NOATIME_FL | FS_CASEFOLD_FL)
 
 struct shmem_quota_limits {
 	qsize_t usrquota_bhardlimit; /* Default user quota block hard limit */
diff --git a/mm/shmem.c b/mm/shmem.c
index 0f918010bc54..9a0fc7636629 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2617,9 +2617,26 @@ static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
  * chattr's fsflags are unrelated to extended attributes,
  * but tmpfs has chosen to enable them under the same config option.
  */
-static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
+static int shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
 {
-	unsigned int i_flags = 0;
+	unsigned int i_flags = 0, old = inode->i_flags;
+	struct super_block *sb = inode->i_sb;
+
+	if (fsflags & FS_CASEFOLD_FL) {
+		if (!sb->s_encoding)
+			return -EOPNOTSUPP;
+
+		if (!S_ISDIR(inode->i_mode))
+			return -ENOTDIR;
+
+		if (dentry && !simple_empty(dentry))
+			return -ENOTEMPTY;
+
+		i_flags |= S_CASEFOLD;
+	} else if (old & S_CASEFOLD) {
+		if (dentry && !simple_empty(dentry))
+			return -ENOTEMPTY;
+	}
 
 	if (fsflags & FS_NOATIME_FL)
 		i_flags |= S_NOATIME;
@@ -2630,10 +2647,12 @@ static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
 	/*
 	 * But FS_NODUMP_FL does not require any action in i_flags.
 	 */
-	inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE);
+	inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE | S_CASEFOLD);
+
+	return 0;
 }
 #else
-static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
+static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
 {
 }
 #define shmem_initxattrs NULL
@@ -2680,7 +2699,7 @@ static struct inode *__shmem_get_inode(struct mnt_idmap *idmap,
 	info->fsflags = (dir == NULL) ? 0 :
 		SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
 	if (info->fsflags)
-		shmem_set_inode_flags(inode, info->fsflags);
+		shmem_set_inode_flags(inode, info->fsflags, NULL);
 	INIT_LIST_HEAD(&info->shrinklist);
 	INIT_LIST_HEAD(&info->swaplist);
 	simple_xattrs_init(&info->xattrs);
@@ -3790,16 +3809,23 @@ static int shmem_fileattr_set(struct mnt_idmap *idmap,
 {
 	struct inode *inode = d_inode(dentry);
 	struct shmem_inode_info *info = SHMEM_I(inode);
+	int ret, flags;
 
 	if (fileattr_has_fsx(fa))
 		return -EOPNOTSUPP;
 	if (fa->flags & ~SHMEM_FL_USER_MODIFIABLE)
 		return -EOPNOTSUPP;
 
-	info->fsflags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
+	flags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
 		(fa->flags & SHMEM_FL_USER_MODIFIABLE);
 
-	shmem_set_inode_flags(inode, info->fsflags);
+	ret = shmem_set_inode_flags(inode, flags, dentry);
+
+	if (ret)
+		return ret;
+
+	info->fsflags = flags;
+
 	inode_set_ctime_current(inode);
 	inode_inc_iversion(inode);
 	return 0;
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 7/8] tmpfs: Expose filesystem features via sysfs
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
                   ` (5 preceding siblings ...)
  2024-09-02 22:55 ` [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-02 22:55 ` [PATCH v2 8/8] docs: tmpfs: Add casefold options André Almeida
  7 siblings, 0 replies; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida

Expose filesystem features through sysfs, so userspace can query if
tmpfs support casefold.

This follows the same setup as defined by ext4 and f2fs to expose
casefold support to userspace.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 mm/shmem.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/mm/shmem.c b/mm/shmem.c
index 9a0fc7636629..fdaae7543d1a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -5365,3 +5365,40 @@ struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 	return page;
 }
 EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp);
+
+#if defined(CONFIG_SYSFS) && defined(CONFIG_TMPFS)
+#if IS_ENABLED(CONFIG_UNICODE)
+static DEVICE_STRING_ATTR_RO(casefold, 0444, "supported");
+#endif
+
+static struct attribute *tmpfs_attributes[] = {
+#if IS_ENABLED(CONFIG_UNICODE)
+	&dev_attr_casefold.attr.attr,
+#endif
+	NULL
+};
+
+static const struct attribute_group tmpfs_attribute_group = {
+	.attrs = tmpfs_attributes,
+	.name = "features"
+};
+
+static struct kobject *tmpfs_kobj;
+
+static int __init tmpfs_sysfs_init(void)
+{
+	int ret;
+
+	tmpfs_kobj = kobject_create_and_add("tmpfs", fs_kobj);
+	if (!tmpfs_kobj)
+		return -ENOMEM;
+
+	ret = sysfs_create_group(tmpfs_kobj, &tmpfs_attribute_group);
+	if (ret)
+		kobject_put(tmpfs_kobj);
+
+	return ret;
+}
+
+fs_initcall(tmpfs_sysfs_init);
+#endif /* CONFIG_SYSFS && CONFIG_TMPFS */
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 8/8] docs: tmpfs: Add casefold options
  2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
                   ` (6 preceding siblings ...)
  2024-09-02 22:55 ` [PATCH v2 7/8] tmpfs: Expose filesystem features via sysfs André Almeida
@ 2024-09-02 22:55 ` André Almeida
  2024-09-03 16:38   ` Gabriel Krisman Bertazi
  7 siblings, 1 reply; 22+ messages in thread
From: André Almeida @ 2024-09-02 22:55 UTC (permalink / raw)
  To: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman
  Cc: linux-mm, linux-kernel, linux-fsdevel, kernel-dev,
	Daniel Rosenberg, smcv, Christoph Hellwig, André Almeida

Document mounting options for casefold support in tmpfs.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 Documentation/filesystems/tmpfs.rst | 37 +++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst
index 56a26c843dbe..ce24fb16979a 100644
--- a/Documentation/filesystems/tmpfs.rst
+++ b/Documentation/filesystems/tmpfs.rst
@@ -241,6 +241,41 @@ So 'mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs'
 will give you tmpfs instance on /mytmpfs which can allocate 10GB
 RAM/SWAP in 10240 inodes and it is only accessible by root.
 
+tmpfs has the following mounting options for case-insesitive lookups support:
+
+================= ==============================================================
+casefold          Enable casefold support at this mount point using the given
+                  argument as the encoding standard. Currently only utf8
+                  encodings are supported.
+strict_encoding   Enable strict encoding at this mount point (disabled by
+                  default). This means that invalid sequences will be rejected
+                  by the file system.
+================= ==============================================================
+
+Note that this option doesn't enable casefold by default; one needs to set
+casefold flag per directory, setting the +F attribute in an empty directory. New
+directories within a casefolded one will inherit the flag.
+
+Example::
+
+    $ mount -t tmpfs -o casefold=utf8-12.1.0,cf_strict fs_name /mytmpfs
+    $ cd /mytmpfs # case-sensitive by default
+    $ touch a; touch A
+    $ ls
+    A  a
+    $ mkdir B
+    $ cd b
+    cd: The directory 'b' does not exist
+    $ mkdir casefold_dir
+    $ chattr +F casefold_dir/ # marking it as case-insensitive
+    $ cd
+    $ touch dir/a; touch dir/A
+    $ ls dir
+    a
+    $ mkdir B
+    $ cd b
+    $ pwd
+    /home/user/mytmpfs/casefold_dir/B
 
 :Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
@@ -250,3 +285,5 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
    KOSAKI Motohiro, 16 Mar 2010
 :Updated:
    Chris Down, 13 July 2020
+:Updated:
+   André Almeida, 23 Aug 2024
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
  2024-09-02 22:55 ` [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs André Almeida
@ 2024-09-03  9:04   ` kernel test robot
  2024-09-03  9:04   ` kernel test robot
  2024-09-03 16:15   ` Gabriel Krisman Bertazi
  2 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2024-09-03  9:04 UTC (permalink / raw)
  To: André Almeida, Hugh Dickins, Andrew Morton, Alexander Viro,
	Christian Brauner, Jan Kara, krisman
  Cc: llvm, oe-kbuild-all, Linux Memory Management List, linux-kernel,
	linux-fsdevel, kernel-dev, Daniel Rosenberg, smcv,
	Christoph Hellwig, André Almeida

Hi André,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on tytso-ext4/dev brauner-vfs/vfs.all linus/master v6.11-rc6 next-20240903]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/unicode-Fix-utf8_load-error-path/20240903-070149
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20240902225511.757831-7-andrealmeid%40igalia.com
patch subject: [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
config: i386-buildonly-randconfig-005-20240903 (https://download.01.org/0day-ci/archive/20240903/202409031620.BOshMDgn-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240903/202409031620.BOshMDgn-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409031620.BOshMDgn-lkp@intel.com/

All errors (new ones prefixed by >>):

>> mm/shmem.c:2771:12: error: no member named 's_encoding' in 'struct super_block'
    2771 |                 if (!sb->s_encoding)
         |                      ~~  ^
   1 error generated.


vim +2771 mm/shmem.c

  2760	
  2761	/*
  2762	 * chattr's fsflags are unrelated to extended attributes,
  2763	 * but tmpfs has chosen to enable them under the same config option.
  2764	 */
  2765	static int shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
  2766	{
  2767		unsigned int i_flags = 0, old = inode->i_flags;
  2768		struct super_block *sb = inode->i_sb;
  2769	
  2770		if (fsflags & FS_CASEFOLD_FL) {
> 2771			if (!sb->s_encoding)
  2772				return -EOPNOTSUPP;
  2773	
  2774			if (!S_ISDIR(inode->i_mode))
  2775				return -ENOTDIR;
  2776	
  2777			if (dentry && !simple_empty(dentry))
  2778				return -ENOTEMPTY;
  2779	
  2780			i_flags |= S_CASEFOLD;
  2781		} else if (old & S_CASEFOLD) {
  2782			if (dentry && !simple_empty(dentry))
  2783				return -ENOTEMPTY;
  2784		}
  2785	
  2786		if (fsflags & FS_NOATIME_FL)
  2787			i_flags |= S_NOATIME;
  2788		if (fsflags & FS_APPEND_FL)
  2789			i_flags |= S_APPEND;
  2790		if (fsflags & FS_IMMUTABLE_FL)
  2791			i_flags |= S_IMMUTABLE;
  2792		/*
  2793		 * But FS_NODUMP_FL does not require any action in i_flags.
  2794		 */
  2795		inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE | S_CASEFOLD);
  2796	
  2797		return 0;
  2798	}
  2799	#else
  2800	static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
  2801	{
  2802	}
  2803	#define shmem_initxattrs NULL
  2804	#endif
  2805	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 2/8] unicode: Create utf8_check_strict_name
  2024-09-02 22:55 ` [PATCH v2 2/8] unicode: Create utf8_check_strict_name André Almeida
@ 2024-09-03  9:04   ` kernel test robot
  2024-09-03 11:36   ` Theodore Ts'o
  2024-09-03 15:34   ` Gabriel Krisman Bertazi
  2 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2024-09-03  9:04 UTC (permalink / raw)
  To: André Almeida, Hugh Dickins, Andrew Morton, Alexander Viro,
	Christian Brauner, Jan Kara, krisman
  Cc: oe-kbuild-all, Linux Memory Management List, linux-kernel,
	linux-fsdevel, kernel-dev, Daniel Rosenberg, smcv,
	Christoph Hellwig, André Almeida, Gabriel Krisman Bertazi

Hi André,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on tytso-ext4/dev brauner-vfs/vfs.all linus/master v6.11-rc6 next-20240903]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/unicode-Fix-utf8_load-error-path/20240903-070149
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20240902225511.757831-3-andrealmeid%40igalia.com
patch subject: [PATCH v2 2/8] unicode: Create utf8_check_strict_name
config: powerpc64-randconfig-r073-20240903 (https://download.01.org/0day-ci/archive/20240903/202409031655.gO1eC1AL-lkp@intel.com/config)
compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project dc19b59ea2502193c0e7bc16bb7d711c8053edcf)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240903/202409031655.gO1eC1AL-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409031655.gO1eC1AL-lkp@intel.com/

All errors (new ones prefixed by >>):

>> fs/unicode/utf8-core.c:238:11: error: call to undeclared function 'IS_CASEFOLDED'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
     238 |         return !(IS_CASEFOLDED(dir) && dir->i_sb->s_encoding &&
         |                  ^
>> fs/unicode/utf8-core.c:238:36: error: incomplete definition of type 'struct inode'
     238 |         return !(IS_CASEFOLDED(dir) && dir->i_sb->s_encoding &&
         |                                        ~~~^
   include/linux/uprobes.h:21:8: note: forward declaration of 'struct inode'
      21 | struct inode;
         |        ^
>> fs/unicode/utf8-core.c:239:9: error: call to undeclared function 'sb_has_strict_encoding'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
     239 |                sb_has_strict_encoding(dir->i_sb) &&
         |                ^
   fs/unicode/utf8-core.c:239:35: error: incomplete definition of type 'struct inode'
     239 |                sb_has_strict_encoding(dir->i_sb) &&
         |                                       ~~~^
   include/linux/uprobes.h:21:8: note: forward declaration of 'struct inode'
      21 | struct inode;
         |        ^
   fs/unicode/utf8-core.c:240:26: error: incomplete definition of type 'struct inode'
     240 |                utf8_validate(dir->i_sb->s_encoding, d_name));
         |                              ~~~^
   include/linux/uprobes.h:21:8: note: forward declaration of 'struct inode'
      21 | struct inode;
         |        ^
   5 errors generated.


vim +/IS_CASEFOLDED +238 fs/unicode/utf8-core.c

   216	
   217	/**
   218	 * utf8_check_strict_name - Check if a given name is suitable for a directory
   219	 *
   220	 * This functions checks if the proposed filename is suitable for the parent
   221	 * directory. That means that only valid UTF-8 filenames will be accepted for
   222	 * casefold directories from filesystems created with the strict enconding flags.
   223	 * That also means that any name will be accepted for directories that doesn't
   224	 * have casefold enabled, or aren't being strict with the enconding.
   225	 *
   226	 * @inode: inode of the directory where the new file will be created
   227	 * @d_name: name of the new file
   228	 *
   229	 * Returns:
   230	 *  * True if the filename is suitable for this directory. It can be true if a
   231	 *  given name is not suitable for a strict enconding directory, but the
   232	 *  directory being used isn't strict
   233	 *  * False if the filename isn't suitable for this directory. This only happens
   234	 *  when a directory is casefolded and is strict about its encoding.
   235	 */
   236	bool utf8_check_strict_name(struct inode *dir, struct qstr *d_name)
   237	{
 > 238		return !(IS_CASEFOLDED(dir) && dir->i_sb->s_encoding &&
 > 239		       sb_has_strict_encoding(dir->i_sb) &&

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
  2024-09-02 22:55 ` [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs André Almeida
  2024-09-03  9:04   ` kernel test robot
@ 2024-09-03  9:04   ` kernel test robot
  2024-09-03 16:15   ` Gabriel Krisman Bertazi
  2 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2024-09-03  9:04 UTC (permalink / raw)
  To: André Almeida, Hugh Dickins, Andrew Morton, Alexander Viro,
	Christian Brauner, Jan Kara, krisman
  Cc: oe-kbuild-all, Linux Memory Management List, linux-kernel,
	linux-fsdevel, kernel-dev, Daniel Rosenberg, smcv,
	Christoph Hellwig, André Almeida

Hi André,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on tytso-ext4/dev brauner-vfs/vfs.all linus/master v6.11-rc6 next-20240903]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/unicode-Fix-utf8_load-error-path/20240903-070149
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20240902225511.757831-7-andrealmeid%40igalia.com
patch subject: [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
config: i386-buildonly-randconfig-002-20240903 (https://download.01.org/0day-ci/archive/20240903/202409031642.6kP6Ra8c-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240903/202409031642.6kP6Ra8c-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409031642.6kP6Ra8c-lkp@intel.com/

All errors (new ones prefixed by >>):

   mm/shmem.c: In function 'shmem_set_inode_flags':
>> mm/shmem.c:2771:24: error: 'struct super_block' has no member named 's_encoding'
    2771 |                 if (!sb->s_encoding)
         |                        ^~


vim +2771 mm/shmem.c

  2760	
  2761	/*
  2762	 * chattr's fsflags are unrelated to extended attributes,
  2763	 * but tmpfs has chosen to enable them under the same config option.
  2764	 */
  2765	static int shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
  2766	{
  2767		unsigned int i_flags = 0, old = inode->i_flags;
  2768		struct super_block *sb = inode->i_sb;
  2769	
  2770		if (fsflags & FS_CASEFOLD_FL) {
> 2771			if (!sb->s_encoding)
  2772				return -EOPNOTSUPP;
  2773	
  2774			if (!S_ISDIR(inode->i_mode))
  2775				return -ENOTDIR;
  2776	
  2777			if (dentry && !simple_empty(dentry))
  2778				return -ENOTEMPTY;
  2779	
  2780			i_flags |= S_CASEFOLD;
  2781		} else if (old & S_CASEFOLD) {
  2782			if (dentry && !simple_empty(dentry))
  2783				return -ENOTEMPTY;
  2784		}
  2785	
  2786		if (fsflags & FS_NOATIME_FL)
  2787			i_flags |= S_NOATIME;
  2788		if (fsflags & FS_APPEND_FL)
  2789			i_flags |= S_APPEND;
  2790		if (fsflags & FS_IMMUTABLE_FL)
  2791			i_flags |= S_IMMUTABLE;
  2792		/*
  2793		 * But FS_NODUMP_FL does not require any action in i_flags.
  2794		 */
  2795		inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE | S_CASEFOLD);
  2796	
  2797		return 0;
  2798	}
  2799	#else
  2800	static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
  2801	{
  2802	}
  2803	#define shmem_initxattrs NULL
  2804	#endif
  2805	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 2/8] unicode: Create utf8_check_strict_name
  2024-09-02 22:55 ` [PATCH v2 2/8] unicode: Create utf8_check_strict_name André Almeida
  2024-09-03  9:04   ` kernel test robot
@ 2024-09-03 11:36   ` Theodore Ts'o
  2024-09-03 15:34   ` Gabriel Krisman Bertazi
  2 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2024-09-03 11:36 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig,
	Gabriel Krisman Bertazi

I'd suggest using the one-line summary:

unicode: create the helper function utf8_check_strict_name()

so that it's a bit more descriptive.

On Mon, Sep 02, 2024 at 07:55:04PM -0300, André Almeida wrote:
> +/**
> + * utf8_check_strict_name - Check if a given name is suitable for a directory
> + *
> + * This functions checks if the proposed filename is suitable for the parent
> + * directory. That means that only valid UTF-8 filenames will be accepted for
> + * casefold directories from filesystems created with the strict enconding flags.
> + * That also means that any name will be accepted for directories that doesn't
> + * have casefold enabled, or aren't being strict with the enconding.

I also suggest wrapping with a fill column of 72 characters, instead
of 80.

						- Ted
						

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 3/8] ext4: Use utf8_check_strict_name helper
  2024-09-02 22:55 ` [PATCH v2 3/8] ext4: Use utf8_check_strict_name helper André Almeida
@ 2024-09-03 11:37   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2024-09-03 11:37 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig,
	Gabriel Krisman Bertazi

On Mon, Sep 02, 2024 at 07:55:05PM -0300, André Almeida wrote:
> Use the helper function to check the requeriments for casefold
> directories using strict enconding.
> 
> Suggested-by: Gabriel Krisman Bertazi <gabriel@krisman.be>
> Signed-off-by: André Almeida <andrealmeid@igalia.com>

Acked-by: Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 1/8] unicode: Fix utf8_load() error path
  2024-09-02 22:55 ` [PATCH v2 1/8] unicode: Fix utf8_load() error path André Almeida
@ 2024-09-03 11:40   ` Theodore Ts'o
  2024-09-03 16:48   ` Gabriel Krisman Bertazi
  1 sibling, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2024-09-03 11:40 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig

On Mon, Sep 02, 2024 at 07:55:03PM -0300, André Almeida wrote:
> utf8_load() requests the symbol "utf8_data_table" and then checks if the
> requested UTF-8 version is supported. If it's unsupported, it tries to
> put the data table using symbol_put(). If an unsupported version is
> requested, symbol_put() fails like this:
> 
>  kernel BUG at kernel/module/main.c:786!
>  RIP: 0010:__symbol_put+0x93/0xb0
>  Call Trace:
>   <TASK>
>   ? __die_body.cold+0x19/0x27
>   ? die+0x2e/0x50
>   ? do_trap+0xca/0x110
>   ? do_error_trap+0x65/0x80
>   ? __symbol_put+0x93/0xb0
>   ? exc_invalid_op+0x51/0x70
>   ? __symbol_put+0x93/0xb0
>   ? asm_exc_invalid_op+0x1a/0x20
>   ? __pfx_cmp_name+0x10/0x10
>   ? __symbol_put+0x93/0xb0
>   ? __symbol_put+0x62/0xb0
>   utf8_load+0xf8/0x150
> 
> That happens because symbol_put() expects the unique string that
> identify the symbol, instead of a pointer to the loaded symbol. Fix that
> by using such string.
> 
> Fixes: 2b3d04787012 ("unicode: Add utf8-data module")
> Signed-off-by: André Almeida <andrealmeid@igalia.com>

Nice catch!

Reviewed-by: Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 4/8] unicode: Recreate utf8_parse_version()
  2024-09-02 22:55 ` [PATCH v2 4/8] unicode: Recreate utf8_parse_version() André Almeida
@ 2024-09-03 11:41   ` Theodore Ts'o
  0 siblings, 0 replies; 22+ messages in thread
From: Theodore Ts'o @ 2024-09-03 11:41 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig

On Mon, Sep 02, 2024 at 07:55:06PM -0300, André Almeida wrote:
> All filesystems that currently support UTF-8 casefold can fetch the
> UTF-8 version from the filesystem metadata stored on disk. They can get
> the data stored and directly match it to a integer, so they can skip the
> string parsing step, which motivated the removal of this function in the
> first place.
> 
> However, for tmpfs, the only way to tell the kernel which UTF-8 version
> we are about to use is via mount options, using a string. Re-introduce
> utf8_parse_version() to be used by tmpfs.
> 
> This version differs from the original by skipping the intermediate step
> of copying the version string to an auxiliary string before calling
> match_token(). This versions calls match_token() in the argument string.
> 
> utf8_parse_version() was created by 9d53690f0d4 ("unicode: implement
> higher level API for string handling") and later removed by 49bd03cc7e9
> ("unicode: pass a UNICODE_AGE() tripple to utf8_load").
> 
> Signed-off-by: André Almeida <andrealmeid@igalia.com>

Reviewed-by: Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 2/8] unicode: Create utf8_check_strict_name
  2024-09-02 22:55 ` [PATCH v2 2/8] unicode: Create utf8_check_strict_name André Almeida
  2024-09-03  9:04   ` kernel test robot
  2024-09-03 11:36   ` Theodore Ts'o
@ 2024-09-03 15:34   ` Gabriel Krisman Bertazi
  2 siblings, 0 replies; 22+ messages in thread
From: Gabriel Krisman Bertazi @ 2024-09-03 15:34 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig,
	Gabriel Krisman Bertazi

André Almeida <andrealmeid@igalia.com> writes:

> Create a helper function for filesystems do the checks required for
> casefold directories and strict enconding.
>
> Suggested-by: Gabriel Krisman Bertazi <gabriel@krisman.be>
> Signed-off-by: André Almeida <andrealmeid@igalia.com>
> ---
>  fs/unicode/utf8-core.c  | 26 ++++++++++++++++++++++++++
>  include/linux/unicode.h |  2 ++
>  2 files changed, 28 insertions(+)
>
> diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c
> index 0400824ef493..4966e175ed71 100644
> --- a/fs/unicode/utf8-core.c
> +++ b/fs/unicode/utf8-core.c

I don't think this belongs in fs/unicode. it is filesystem semantics whether
they don't allow invalid utf8 names and, while fs/unicode provides
utf8_validate to verify if a string is valid, it has no business looking
into superblock and inode flags.

It would be better placed as a libfs helper.

> @@ -214,3 +214,29 @@ void utf8_unload(struct unicode_map *um)
>  }
>  EXPORT_SYMBOL(utf8_unload);
>  
> +/**
> + * utf8_check_strict_name - Check if a given name is suitable for a directory

To follow the namespace in libfs, we could call it

generic_ci_validate_strict_name

> + *
> + * This functions checks if the proposed filename is suitable for the parent

suitable => valid

> + * directory. That means that only valid UTF-8 filenames will be accepted for
> + * casefold directories from filesystems created with the strict enconding flags.

enconding flags => encoding flag

> + * That also means that any name will be accepted for directories that doesn't
> + * have casefold enabled, or aren't being strict with the enconding.

encoding

> + *
> + * @inode: inode of the directory where the new file will be created
> + * @d_name: name of the new file

d_name means 'dentry name'. just 'name' is enough here since it doesn't
matter if the qstr is coming from the dentry.

> + *
> + * Returns:
> + *  * True if the filename is suitable for this directory. It can be true if a
> + *  given name is not suitable for a strict enconding directory, but the
> + *  directory being used isn't strict
> + *  * False if the filename isn't suitable for this directory. This only happens
> + *  when a directory is casefolded and is strict about its encoding.
> + */
> +bool utf8_check_strict_name(struct inode *dir, struct qstr *d_name)
> +{
> +	return !(IS_CASEFOLDED(dir) && dir->i_sb->s_encoding &&
> +	       sb_has_strict_encoding(dir->i_sb) &&
> +	       utf8_validate(dir->i_sb->s_encoding, d_name));
> +}

Now that it is a helper, it could now be unfolded to something more
readable:

if (!IS_CASEFOLDED(dir) || !sb_has_strict_encoding(dir->i_sb)))
   return true;

/* Should never happen.  Unless the filesystem is corrupt. */
if (WARN_ON_ONCE(!dir->i_sb->s_encoding))
   return true;

return utf8_validate(...)

> +EXPORT_SYMBOL(utf8_check_strict_name);
> diff --git a/include/linux/unicode.h b/include/linux/unicode.h
> index 4d39e6e11a95..fb56fb5e686c 100644
> --- a/include/linux/unicode.h
> +++ b/include/linux/unicode.h
> @@ -76,4 +76,6 @@ int utf8_casefold_hash(const struct unicode_map *um, const void *salt,
>  struct unicode_map *utf8_load(unsigned int version);
>  void utf8_unload(struct unicode_map *um);
>  
> +bool utf8_check_strict_name(struct inode *dir, struct qstr *d_name);
> +
>  #endif /* _LINUX_UNICODE_H */

-- 
Gabriel Krisman Bertazi

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 5/8] tmpfs: Add casefold lookup support
  2024-09-02 22:55 ` [PATCH v2 5/8] tmpfs: Add casefold lookup support André Almeida
@ 2024-09-03 16:08   ` Gabriel Krisman Bertazi
  0 siblings, 0 replies; 22+ messages in thread
From: Gabriel Krisman Bertazi @ 2024-09-03 16:08 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig

André Almeida <andrealmeid@igalia.com> writes:

> Enable casefold lookup in tmpfs, based on the enconding defined by
> userspace. That means that instead of comparing byte per byte a file
> name, it compares to a case-insensitive equivalent of the Unicode
> string.
>
> * Dcache handling
>
> There's a special need when dealing with case-insensitive dentries.
> First of all, we currently invalidated every negative casefold dentries.
> That happens because currently VFS code has no proper support to deal
> with that, giving that it could incorrectly reuse a previous filename
> for a new file that has a casefold match. For instance, this could
> happen:
>
> $ mkdir DIR
> $ rm -r DIR
> $ mkdir dir
> $ ls
> DIR/
>
> And would be perceived as inconsistency from userspace point of view,
> because even that we match files in a case-insensitive manner, we still
> honor whatever is the initial filename.
>
> Along with that, tmpfs stores only the first equivalent name dentry used
> in the dcache, preventing duplications of dentries in the dcache. The
> d_compare() version for casefold files uses a normalized string, so the
> filename under lookup will be compared to another normalized string for
> the existing file, achieving a casefolded lookup.
>
> * Enabling casefold via mount options
>
> Most filesystems have their data stored in disk, so casefold option need
> to be enabled when building a filesystem on a device (via mkfs).
> However, as tmpfs is a RAM backed filesystem, there's no disk
> information and thus no mkfs to store information about casefold.
>
> For tmpfs, create casefold options for mounting. Userspace can then
> enable casefold support for a mount point using:
>
> $ mount -t tmpfs -o casefold=utf8-12.1.0 fs_name mount_dir/
>
> Userspace must set what Unicode standard is aiming to. The available
> options depends on what the kernel Unicode subsystem supports.
>
> And for strict encoding:
>
> $ mount -t tmpfs -o casefold=utf8-12.1.0,strict_encoding fs_name mount_dir/
>
> Strict encoding means that tmpfs will refuse to create invalid UTF-8
> sequences. When this option is not enabled, any invalid sequence will be
> treated as an opaque byte sequence, ignoring the encoding thus not being
> able to be looked up in a case-insensitive way.
>
> Signed-off-by: André Almeida <andrealmeid@igalia.com>
> ---
>  mm/shmem.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 111 insertions(+), 4 deletions(-)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 5a77acf6ac6a..0f918010bc54 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -40,6 +40,8 @@
>  #include <linux/fs_parser.h>
>  #include <linux/swapfile.h>
>  #include <linux/iversion.h>
> +#include <linux/unicode.h>
> +#include <linux/parser.h>
>  #include "swap.h"
>  
>  static struct vfsmount *shm_mnt __ro_after_init;
> @@ -123,6 +125,8 @@ struct shmem_options {
>  	bool noswap;
>  	unsigned short quota_types;
>  	struct shmem_quota_limits qlimits;
> +	struct unicode_map *encoding;
> +	bool strict_encoding;
>  #define SHMEM_SEEN_BLOCKS 1
>  #define SHMEM_SEEN_INODES 2
>  #define SHMEM_SEEN_HUGE 4
> @@ -3427,6 +3431,11 @@ shmem_mknod(struct mnt_idmap *idmap, struct inode *dir,
>  	if (IS_ERR(inode))
>  		return PTR_ERR(inode);
>  
> +#if IS_ENABLED(CONFIG_UNICODE)
> +	if (!utf8_check_strict_name(dir, &dentry->d_name))
> +		return -EINVAL;
> +#endif

Please, fold it into the code when possible:

if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))

> +
>  	error = simple_acl_create(dir, inode);
>  	if (error)
>  		goto out_iput;
> @@ -3442,7 +3451,12 @@ shmem_mknod(struct mnt_idmap *idmap, struct inode *dir,
>  	dir->i_size += BOGO_DIRENT_SIZE;
>  	inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
>  	inode_inc_iversion(dir);
> -	d_instantiate(dentry, inode);
> +
> +	if (IS_CASEFOLDED(dir))

If you have if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))

It can be  optimized out when CONFIG_UNICODE=n.

> +		d_add(dentry, inode);
> +	else
> +		d_instantiate(dentry, inode);
>  	dget(dentry); /* Extra count - pin the dentry in core */
>  	return error;
>  
> @@ -3533,7 +3547,10 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir,
>  	inc_nlink(inode);
>  	ihold(inode);	/* New dentry reference */
>  	dget(dentry);	/* Extra pinning count for the created dentry */
> -	d_instantiate(dentry, inode);
> +	if (IS_CASEFOLDED(dir))
> +		d_add(dentry, inode);
> +	else
> +		d_instantiate(dentry, inode);
>  out:
>  	return ret;
>  }
> @@ -3553,6 +3570,14 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
>  	inode_inc_iversion(dir);
>  	drop_nlink(inode);
>  	dput(dentry);	/* Undo the count from "create" - does all the work */
> +
> +	/*
> +	 * For now, VFS can't deal with case-insensitive negative dentries, so
> +	 * we invalidate them
> +	 */
> +	if (IS_CASEFOLDED(dir))
> +		d_invalidate(dentry);
> +

likewise and also below.

>  	return 0;
>  }
>  
> @@ -3697,7 +3722,10 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
>  	dir->i_size += BOGO_DIRENT_SIZE;
>  	inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
>  	inode_inc_iversion(dir);
> -	d_instantiate(dentry, inode);
> +	if (IS_CASEFOLDED(dir))
> +		d_add(dentry, inode);
> +	else
> +		d_instantiate(dentry, inode);
>  	dget(dentry);
>  	return 0;
>  
> @@ -4050,6 +4078,8 @@ enum shmem_param {
>  	Opt_usrquota_inode_hardlimit,
>  	Opt_grpquota_block_hardlimit,
>  	Opt_grpquota_inode_hardlimit,
> +	Opt_casefold,
> +	Opt_strict_encoding,
>  };
>  
>  static const struct constant_table shmem_param_enums_huge[] = {
> @@ -4081,9 +4111,47 @@ const struct fs_parameter_spec shmem_fs_parameters[] = {
>  	fsparam_string("grpquota_block_hardlimit", Opt_grpquota_block_hardlimit),
>  	fsparam_string("grpquota_inode_hardlimit", Opt_grpquota_inode_hardlimit),
>  #endif
> +	fsparam_string("casefold",	Opt_casefold),
> +	fsparam_flag  ("strict_encoding", Opt_strict_encoding),
>  	{}
>  };
>  
> +#if IS_ENABLED(CONFIG_UNICODE)
> +static int shmem_parse_opt_casefold(struct fs_context *fc, struct fs_parameter *param)
> +{
> +	struct shmem_options *ctx = fc->fs_private;
> +	unsigned int maj = 0, min = 0, rev = 0, version_number;
> +	char version[10];
> +	int ret;
> +	struct unicode_map *encoding;
> +
> +	if (strncmp(param->string, "utf8-", 5))
> +		return invalfc(fc, "Only utf8 encondings are supported");
> +	ret = strscpy(version, param->string + 5, sizeof(version));

the extra buffer and the copy seem unnecessary.  It won't live past this
function anyway. Can you just pass the offseted param->string to
utf8_parse_version?

> +	if (ret < 0)
> +		return invalfc(fc, "Invalid enconding argument: %s",
> +			       param->string);

enconding=>encoding

> +
> +	ret = utf8_parse_version(version, &maj, &min, &rev);
> +	if (ret)
> +		return invalfc(fc, "Invalid utf8 version: %s", version);
> +	version_number = UNICODE_AGE(maj, min, rev);
> +	encoding = utf8_load(version_number);

utf8_load(UNICODE_AGE(maj, min, rev));

and drop version_number.

> +	if (IS_ERR(encoding))
> +		return invalfc(fc, "Invalid utf8 version: %s", version);
> +	pr_info("tmpfs: Using encoding provided by mount options: %s\n",
> +		param->string);
> +	ctx->encoding = encoding;
> +
> +	return 0;
> +}
> +#else
> +static int shmem_parse_opt_casefold(struct fs_context *fc, struct fs_parameter *param)
> +{
> +	return invalfc(fc, "tmpfs: No kernel support for casefold filesystems\n");
> +}
> +#endif
> +
>  static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
>  {
>  	struct shmem_options *ctx = fc->fs_private;
> @@ -4242,6 +4310,11 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
>  				       "Group quota inode hardlimit too large.");
>  		ctx->qlimits.grpquota_ihardlimit = size;
>  		break;
> +	case Opt_casefold:
> +		return shmem_parse_opt_casefold(fc, param);
> +	case Opt_strict_encoding:
> +		ctx->strict_encoding = true;
> +		break;
>  	}
>  	return 0;
>  
> @@ -4471,6 +4544,11 @@ static void shmem_put_super(struct super_block *sb)
>  {
>  	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
>  
> +#if IS_ENABLED(CONFIG_UNICODE)
> +	if (sb->s_encoding)
> +		utf8_unload(sb->s_encoding);
> +#endif
> +
>  #ifdef CONFIG_TMPFS_QUOTA
>  	shmem_disable_quotas(sb);
>  #endif
> @@ -4515,6 +4593,16 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
>  	}
>  	sb->s_export_op = &shmem_export_ops;
>  	sb->s_flags |= SB_NOSEC | SB_I_VERSION;
> +
> +#if IS_ENABLED(CONFIG_UNICODE)
> +	if (ctx->encoding) {
> +		sb->s_encoding = ctx->encoding;
> +		generic_set_sb_d_ops(sb);
> +		if (ctx->strict_encoding)
> +			sb->s_encoding_flags = SB_ENC_STRICT_MODE_FL;
> +	}
> +#endif
> +
>  #else
>  	sb->s_flags |= SB_NOUSER;
>  #endif
> @@ -4704,11 +4792,28 @@ static const struct inode_operations shmem_inode_operations = {
>  #endif
>  };
>  
> +static struct dentry *shmem_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
> +{
> +	if (dentry->d_name.len > NAME_MAX)
> +		return ERR_PTR(-ENAMETOOLONG);
> +
> +	/*
> +	 * For now, VFS can't deal with case-insensitive negative dentries, so
> +	 * we prevent them from being created
> +	 */
> +	if (IS_CASEFOLDED(dir))
> +		return NULL;
> +
> +	d_add(dentry, NULL);
> +
> +	return NULL;
> +}
> +
>  static const struct inode_operations shmem_dir_inode_operations = {
>  #ifdef CONFIG_TMPFS
>  	.getattr	= shmem_getattr,
>  	.create		= shmem_create,
> -	.lookup		= simple_lookup,
> +	.lookup		= shmem_lookup,

simple_lookup sets the dentry operations to enable a custom d_delete,
but this disables that. Without it, negative dentries will linger after
the filesystem is gone.

We want to preserve the current behavior both for normal and casefolding
directories.  You need a new flavor of generic_ci_dentry_ops with that
hook for casefolding shmem, as well as ensure &simple_dentry_operations
is still set for every dentry in non-casefolding volumes.

>  	.link		= shmem_link,
>  	.unlink		= shmem_unlink,
>  	.symlink	= shmem_symlink,
> @@ -4791,6 +4896,8 @@ int shmem_init_fs_context(struct fs_context *fc)
>  	ctx->uid = current_fsuid();
>  	ctx->gid = current_fsgid();
>  
> +	ctx->encoding = NULL;
> +
>  	fc->fs_private = ctx;
>  	fc->ops = &shmem_fs_context_ops;
>  	return 0;

-- 
Gabriel Krisman Bertazi

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
  2024-09-02 22:55 ` [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs André Almeida
  2024-09-03  9:04   ` kernel test robot
  2024-09-03  9:04   ` kernel test robot
@ 2024-09-03 16:15   ` Gabriel Krisman Bertazi
  2024-09-04 22:28     ` André Almeida
  2 siblings, 1 reply; 22+ messages in thread
From: Gabriel Krisman Bertazi @ 2024-09-03 16:15 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig

André Almeida <andrealmeid@igalia.com> writes:

> Enable setting flag FS_CASEFOLD_FL for tmpfs directories, when tmpfs is
> mounted with casefold support. A special check is need for this flag,
> since it can't be set for non-empty directories.
>
> Signed-off-by: André Almeida <andrealmeid@igalia.com>
> ---
>  include/linux/shmem_fs.h |  6 +++---
>  mm/shmem.c               | 40 +++++++++++++++++++++++++++++++++-------
>  2 files changed, 36 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
> index 1d06b1e5408a..8367ca2b99d9 100644
> --- a/include/linux/shmem_fs.h
> +++ b/include/linux/shmem_fs.h
> @@ -42,10 +42,10 @@ struct shmem_inode_info {
>  	struct inode		vfs_inode;
>  };
>  
> -#define SHMEM_FL_USER_VISIBLE		FS_FL_USER_VISIBLE
> +#define SHMEM_FL_USER_VISIBLE		(FS_FL_USER_VISIBLE | FS_CASEFOLD_FL)
>  #define SHMEM_FL_USER_MODIFIABLE \
> -	(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL)
> -#define SHMEM_FL_INHERITED		(FS_NODUMP_FL | FS_NOATIME_FL)
> +	(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL | FS_CASEFOLD_FL)
> +#define SHMEM_FL_INHERITED		(FS_NODUMP_FL | FS_NOATIME_FL | FS_CASEFOLD_FL)
>  
>  struct shmem_quota_limits {
>  	qsize_t usrquota_bhardlimit; /* Default user quota block hard limit */
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 0f918010bc54..9a0fc7636629 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -2617,9 +2617,26 @@ static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
>   * chattr's fsflags are unrelated to extended attributes,
>   * but tmpfs has chosen to enable them under the same config option.
>   */
> -static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
> +static int shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
>  {
> -	unsigned int i_flags = 0;
> +	unsigned int i_flags = 0, old = inode->i_flags;
> +	struct super_block *sb = inode->i_sb;
> +
> +	if (fsflags & FS_CASEFOLD_FL) {
> +		if (!sb->s_encoding)
> +			return -EOPNOTSUPP;
> +
> +		if (!S_ISDIR(inode->i_mode))
> +			return -ENOTDIR;
> +
> +		if (dentry && !simple_empty(dentry))
> +			return -ENOTEMPTY;
> +
> +		i_flags |= S_CASEFOLD;
> +	} else if (old & S_CASEFOLD) {
> +		if (dentry && !simple_empty(dentry))
> +			return -ENOTEMPTY;

We don't want to fail if a directory already has the S_CASEFOLD
flag and we are not flipping it in the current operation.  Something like:

if ((fsflags ^ old) & S_CASEFOLD) {
	if (!sb->s_encoding)
		return -EOPNOTSUPP;

	if (!S_ISDIR(inode->i_mode))
		return -ENOTDIR;

	if (dentry && !simple_empty(dentry))
		return -ENOTEMPTY;
        i_flags |= fsflags & S_CASEFOLD;
}

>
>  	if (fsflags & FS_NOATIME_FL)
>  		i_flags |= S_NOATIME;
> @@ -2630,10 +2647,12 @@ static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
>  	/*
>  	 * But FS_NODUMP_FL does not require any action in i_flags.
>  	 */
> -	inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE);
> +	inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE | S_CASEFOLD);
> +
> +	return 0;
>  }
>  #else
> -static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
> +static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags, struct dentry *dentry)
>  {
>  }
>  #define shmem_initxattrs NULL
> @@ -2680,7 +2699,7 @@ static struct inode *__shmem_get_inode(struct mnt_idmap *idmap,
>  	info->fsflags = (dir == NULL) ? 0 :
>  		SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
>  	if (info->fsflags)
> -		shmem_set_inode_flags(inode, info->fsflags);
> +		shmem_set_inode_flags(inode, info->fsflags, NULL);
>  	INIT_LIST_HEAD(&info->shrinklist);
>  	INIT_LIST_HEAD(&info->swaplist);
>  	simple_xattrs_init(&info->xattrs);
> @@ -3790,16 +3809,23 @@ static int shmem_fileattr_set(struct mnt_idmap *idmap,
>  {
>  	struct inode *inode = d_inode(dentry);
>  	struct shmem_inode_info *info = SHMEM_I(inode);
> +	int ret, flags;
>  
>  	if (fileattr_has_fsx(fa))
>  		return -EOPNOTSUPP;
>  	if (fa->flags & ~SHMEM_FL_USER_MODIFIABLE)
>  		return -EOPNOTSUPP;
>  
> -	info->fsflags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
> +	flags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
>  		(fa->flags & SHMEM_FL_USER_MODIFIABLE);
>  
> -	shmem_set_inode_flags(inode, info->fsflags);
> +	ret = shmem_set_inode_flags(inode, flags, dentry);
> +
> +	if (ret)
> +		return ret;
> +
> +	info->fsflags = flags;
> +
>  	inode_set_ctime_current(inode);
>  	inode_inc_iversion(inode);
>  	return 0;

-- 
Gabriel Krisman Bertazi

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 8/8] docs: tmpfs: Add casefold options
  2024-09-02 22:55 ` [PATCH v2 8/8] docs: tmpfs: Add casefold options André Almeida
@ 2024-09-03 16:38   ` Gabriel Krisman Bertazi
  0 siblings, 0 replies; 22+ messages in thread
From: Gabriel Krisman Bertazi @ 2024-09-03 16:38 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig

André Almeida <andrealmeid@igalia.com> writes:

> Document mounting options for casefold support in tmpfs.
>
> Signed-off-by: André Almeida <andrealmeid@igalia.com>
> ---
>  Documentation/filesystems/tmpfs.rst | 37 +++++++++++++++++++++++++++++
>  1 file changed, 37 insertions(+)
>
> diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst
> index 56a26c843dbe..ce24fb16979a 100644
> --- a/Documentation/filesystems/tmpfs.rst
> +++ b/Documentation/filesystems/tmpfs.rst
> @@ -241,6 +241,41 @@ So 'mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs'
>  will give you tmpfs instance on /mytmpfs which can allocate 10GB
>  RAM/SWAP in 10240 inodes and it is only accessible by root.
>  
> +tmpfs has the following mounting options for case-insesitive lookups support:

insensitive

> +
> +================= ==============================================================
> +casefold          Enable casefold support at this mount point using the given
> +                  argument as the encoding standard. Currently only utf8
> +                  encodings are supported.
> +strict_encoding   Enable strict encoding at this mount point (disabled by
> +                  default). This means that invalid sequences will be rejected

Invalid sequences is not clear. Perhaps:

In this mode, the filesystem refuses to create file and directory with
names containing invalid UTF-8 characters.


> +                  by the file system.
> +================= ==============================================================
> +
> +Note that this option doesn't enable casefold by default; one needs to set
> +casefold flag per directory, setting the +F attribute in an empty directory. New
> +directories within a casefolded one will inherit the flag.
> +
> +Example::
> +
> +    $ mount -t tmpfs -o casefold=utf8-12.1.0,cf_strict fs_name /mytmpfs

cf_strict should be strict_encoding.

I keep wondering if we should accept 'casefold' without any argument to
just mean the latest encoding version available.  Sure, that is a
problem for filesystems that can be moved between systems, but for tmpfs
that is not a problem.  It is cumbersome to specify the version and most
will just want the latest.

> +    $ cd /mytmpfs # case-sensitive by default
> +    $ touch a; touch A
> +    $ ls
> +    A  a
> +    $ mkdir B
> +    $ cd b
> +    cd: The directory 'b' does not exist
> +    $ mkdir casefold_dir
> +    $ chattr +F casefold_dir/ # marking it as case-insensitive
> +    $ cd
> +    $ touch dir/a; touch dir/A
> +    $ ls dir
> +    a
> +    $ mkdir B
> +    $ cd b
> +    $ pwd
> +    /home/user/mytmpfs/casefold_dir/B

I don't think we need this example,  since it is just generic
how case-insensitiveness work.

>  
>  :Author:
>     Christoph Rohland <cr@sap.com>, 1.12.01
> @@ -250,3 +285,5 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
>     KOSAKI Motohiro, 16 Mar 2010
>  :Updated:
>     Chris Down, 13 July 2020
> +:Updated:
> +   André Almeida, 23 Aug 2024

-- 
Gabriel Krisman Bertazi

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 1/8] unicode: Fix utf8_load() error path
  2024-09-02 22:55 ` [PATCH v2 1/8] unicode: Fix utf8_load() error path André Almeida
  2024-09-03 11:40   ` Theodore Ts'o
@ 2024-09-03 16:48   ` Gabriel Krisman Bertazi
  1 sibling, 0 replies; 22+ messages in thread
From: Gabriel Krisman Bertazi @ 2024-09-03 16:48 UTC (permalink / raw)
  To: André Almeida
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig

André Almeida <andrealmeid@igalia.com> writes:

> utf8_load() requests the symbol "utf8_data_table" and then checks if the
> requested UTF-8 version is supported. If it's unsupported, it tries to
> put the data table using symbol_put(). If an unsupported version is
> requested, symbol_put() fails like this:
>
>  kernel BUG at kernel/module/main.c:786!
>  RIP: 0010:__symbol_put+0x93/0xb0
>  Call Trace:
>   <TASK>
>   ? __die_body.cold+0x19/0x27
>   ? die+0x2e/0x50
>   ? do_trap+0xca/0x110
>   ? do_error_trap+0x65/0x80
>   ? __symbol_put+0x93/0xb0
>   ? exc_invalid_op+0x51/0x70
>   ? __symbol_put+0x93/0xb0
>   ? asm_exc_invalid_op+0x1a/0x20
>   ? __pfx_cmp_name+0x10/0x10
>   ? __symbol_put+0x93/0xb0
>   ? __symbol_put+0x62/0xb0
>   utf8_load+0xf8/0x150
>
> That happens because symbol_put() expects the unique string that
> identify the symbol, instead of a pointer to the loaded symbol. Fix that
> by using such string.
>

Thanks!

I picked only this one via the for-next branch of the unicode tree.  No need to resubmit
this one with the rest of the series.

-- 
Gabriel Krisman Bertazi

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs
  2024-09-03 16:15   ` Gabriel Krisman Bertazi
@ 2024-09-04 22:28     ` André Almeida
  0 siblings, 0 replies; 22+ messages in thread
From: André Almeida @ 2024-09-04 22:28 UTC (permalink / raw)
  To: Gabriel Krisman Bertazi
  Cc: Hugh Dickins, Andrew Morton, Alexander Viro, Christian Brauner,
	Jan Kara, krisman, linux-mm, linux-kernel, linux-fsdevel,
	kernel-dev, Daniel Rosenberg, smcv, Christoph Hellwig

Hi Krisman,

Thanks for the feedback!

Em 03/09/2024 13:15, Gabriel Krisman Bertazi escreveu:
> André Almeida <andrealmeid@igalia.com> writes:
> 
>> Enable setting flag FS_CASEFOLD_FL for tmpfs directories, when tmpfs is
>> mounted with casefold support. A special check is need for this flag,
>> since it can't be set for non-empty directories.
>>
>> Signed-off-by: André Almeida <andrealmeid@igalia.com>

[...]

>> +
>> +	if (fsflags & FS_CASEFOLD_FL) {
>> +		if (!sb->s_encoding)
>> +			return -EOPNOTSUPP;
>> +
>> +		if (!S_ISDIR(inode->i_mode))
>> +			return -ENOTDIR;
>> +
>> +		if (dentry && !simple_empty(dentry))
>> +			return -ENOTEMPTY;
>> +
>> +		i_flags |= S_CASEFOLD;
>> +	} else if (old & S_CASEFOLD) {
>> +		if (dentry && !simple_empty(dentry))
>> +			return -ENOTEMPTY;
> 
> We don't want to fail if a directory already has the S_CASEFOLD
> flag and we are not flipping it in the current operation.  Something like:
> 
> if ((fsflags ^ old) & S_CASEFOLD) {
> 	if (!sb->s_encoding)
> 		return -EOPNOTSUPP;
> 
> 	if (!S_ISDIR(inode->i_mode))
> 		return -ENOTDIR;
> 
> 	if (dentry && !simple_empty(dentry))
> 		return -ENOTEMPTY;
>          i_flags |= fsflags & S_CASEFOLD;
> }
> 

You are right, it's broken and failing for directories with S_CASEFOLD. 
Here's a small test showing that we can't add the +d attribute to a 
non-empty CI folder (+d doesn't require the directory to be empty):

folder ) mkdir A
folder ) mkdir A/B
folder ) chattr +d A/B
folder ) chattr +d A
chattr: Directory not empty while setting flags on A

However, FS_CASEFOLD_FL != S_CASEFOLD and the set of values for 
inode->i_flags (var old) and fsflags aren't the same, so your proposed 
snippet didn't work. I see that ext4 has a very similar code as your 
proposal, but I think they do something different with the flag values.

I rewrote my code separating the three possible paths and it worked:

/* inheritance from parent dir/keeping the same flags path */
if ((fsflags & FS_CASEFOLD_FL) && (old & S_CASEFOLD))
	i_flags |= S_CASEFOLD;

/* removing flag path */
if (!(fsflags & FS_CASEFOLD_FL) && (old & S_CASEFOLD))
	if (dentry && !simple_empty(dentry))
		return -ENOTEMPTY;

/* adding flag path */
if ((fsflags & FS_CASEFOLD_FL) && !(old & S_CASEFOLD)) {
	if (!sb->s_encoding)
		return -EOPNOTSUPP;

	if (!S_ISDIR(inode->i_mode))
		return -ENOTDIR;

	if (dentry && !simple_empty(dentry))
		return -ENOTEMPTY;

	i_flags |= S_CASEFOLD;
}

In that way, the `chattr +d` call doesn't fall into the simple_empty() 
check. I simplified the code like this for the v3:

if (fsflags & FS_CASEFOLD_FL) {
	if (!(old & S_CASEFOLD)) {
		if (!sb->s_encoding)
			return -EOPNOTSUPP;

		if (!S_ISDIR(inode->i_mode))
			return -ENOTDIR;

		if (dentry && !simple_empty(dentry))
			return -ENOTEMPTY;
	}

	i_flags |= S_CASEFOLD;
} else if (old & S_CASEFOLD) {
	if (dentry && !simple_empty(dentry))
		return -ENOTEMPTY;
}

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2024-09-04 22:28 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-02 22:55 [PATCH v2 0/8] tmpfs: Add case-insesitive support for tmpfs André Almeida
2024-09-02 22:55 ` [PATCH v2 1/8] unicode: Fix utf8_load() error path André Almeida
2024-09-03 11:40   ` Theodore Ts'o
2024-09-03 16:48   ` Gabriel Krisman Bertazi
2024-09-02 22:55 ` [PATCH v2 2/8] unicode: Create utf8_check_strict_name André Almeida
2024-09-03  9:04   ` kernel test robot
2024-09-03 11:36   ` Theodore Ts'o
2024-09-03 15:34   ` Gabriel Krisman Bertazi
2024-09-02 22:55 ` [PATCH v2 3/8] ext4: Use utf8_check_strict_name helper André Almeida
2024-09-03 11:37   ` Theodore Ts'o
2024-09-02 22:55 ` [PATCH v2 4/8] unicode: Recreate utf8_parse_version() André Almeida
2024-09-03 11:41   ` Theodore Ts'o
2024-09-02 22:55 ` [PATCH v2 5/8] tmpfs: Add casefold lookup support André Almeida
2024-09-03 16:08   ` Gabriel Krisman Bertazi
2024-09-02 22:55 ` [PATCH v2 6/8] tmpfs: Add flag FS_CASEFOLD_FL support for tmpfs dirs André Almeida
2024-09-03  9:04   ` kernel test robot
2024-09-03  9:04   ` kernel test robot
2024-09-03 16:15   ` Gabriel Krisman Bertazi
2024-09-04 22:28     ` André Almeida
2024-09-02 22:55 ` [PATCH v2 7/8] tmpfs: Expose filesystem features via sysfs André Almeida
2024-09-02 22:55 ` [PATCH v2 8/8] docs: tmpfs: Add casefold options André Almeida
2024-09-03 16:38   ` Gabriel Krisman Bertazi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).