[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240823173332.281211-4-andrealmeid@igalia.com>
Date: Fri, 23 Aug 2024 14:33:30 -0300
From: André Almeida <andrealmeid@...lia.com>
To: Hugh Dickins <hughd@...gle.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Alexander Viro <viro@...iv.linux.org.uk>,
Christian Brauner <brauner@...nel.org>,
Jan Kara <jack@...e.cz>
Cc: linux-mm@...ck.org,
linux-kernel@...r.kernel.org,
linux-fsdevel@...r.kernel.org,
kernel-dev@...lia.com,
krisman@...nel.org,
Daniel Rosenberg <drosen@...gle.com>,
smcv@...labora.com,
André Almeida <andrealmeid@...lia.com>
Subject: [PATCH 3/5] tmpfs: Create casefold 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@...lia.com>
---
mm/shmem.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/mm/shmem.c b/mm/shmem.c
index 67b6ab580ca2..5c77b4e73204 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -4102,6 +4102,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[] = {
@@ -4133,9 +4135,67 @@ 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 utf8_parse_version(const char *version, unsigned int *maj,
+ unsigned int *min, unsigned int *rev)
+{
+ substring_t args[3];
+ char version_string[12];
+ static const struct match_token token[] = {
+ {1, "%d.%d.%d"},
+ {0, NULL}
+ };
+
+ strscpy(version_string, version, sizeof(version_string));
+
+ if (match_token(version_string, 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;
+}
+
+static int shmem_parse_opt_casefold(struct fs_context *fc, struct fs_parameter *param)
+{
+ struct shmem_options *ctx = fc->fs_private;
+ unsigned int maj, min, rev, 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);
+
+ utf8_parse_version(version, &maj, &min, &rev);
+ 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;
@@ -4294,6 +4354,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;
--
2.46.0
Powered by blists - more mailing lists