From patchwork Tue Mar 23 19:59:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andr=C3=A9_Almeida?= X-Patchwork-Id: 12159183 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7DC4C433DB for ; Tue, 23 Mar 2021 20:01:06 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 71ADE619C1 for ; Tue, 23 Mar 2021 20:01:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 71ADE619C1 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 049C58D0018; Tue, 23 Mar 2021 16:01:06 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id F3C718D0017; Tue, 23 Mar 2021 16:01:05 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DDC928D0018; Tue, 23 Mar 2021 16:01:05 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id BF2418D0017 for ; Tue, 23 Mar 2021 16:01:05 -0400 (EDT) Received: from smtpin07.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 83064A2B9 for ; Tue, 23 Mar 2021 20:01:05 +0000 (UTC) X-FDA: 77952207690.07.6CBBC8C Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by imf23.hostedemail.com (Postfix) with ESMTP id 4EA8FA0000FC for ; Tue, 23 Mar 2021 20:00:04 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: tonyk) with ESMTPSA id 084781F44DB0 From: =?utf-8?q?Andr=C3=A9_Almeida?= To: Hugh Dickins , Andrew Morton , Alexander Viro Cc: krisman@collabora.com, smcv@collabora.com, kernel@collabora.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Daniel Rosenberg , =?utf-8?q?Andr=C3=A9_Almeida?= Subject: [RFC PATCH 1/4] Revert "libfs: unexport generic_ci_d_compare() and generic_ci_d_hash()" Date: Tue, 23 Mar 2021 16:59:38 -0300 Message-Id: <20210323195941.69720-2-andrealmeid@collabora.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210323195941.69720-1-andrealmeid@collabora.com> References: <20210323195941.69720-1-andrealmeid@collabora.com> MIME-Version: 1.0 X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 4EA8FA0000FC X-Stat-Signature: 4qyibegob4db15j9sc1i9y7hysua3x3c Received-SPF: none (collabora.com>: No applicable sender policy available) receiver=imf23; identity=mailfrom; envelope-from=""; helo=bhuna.collabora.co.uk; client-ip=46.235.227.227 X-HE-DKIM-Result: none/none X-HE-Tag: 1616529604-397983 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: This reverts commit 794c43f716845e2d48ce195ed5c4179a4e05ce5f. For implementing casefolding support at tmpfs, it needs to set dentry operations at superblock level, given that tmpfs has no support for fscrypt and we don't need to set operations on a per-dentry basis. Revert this commit so we can access those exported function from tmpfs code. Signed-off-by: André Almeida --- fs/libfs.c | 8 +++++--- include/linux/fs.h | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index e2de5401abca..d1d06494463a 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1387,8 +1387,8 @@ static bool needs_casefold(const struct inode *dir) * * Return: 0 if names match, 1 if mismatch, or -ERRNO */ -static int generic_ci_d_compare(const struct dentry *dentry, unsigned int len, - const char *str, const struct qstr *name) +int generic_ci_d_compare(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) { const struct dentry *parent = READ_ONCE(dentry->d_parent); const struct inode *dir = READ_ONCE(parent->d_inode); @@ -1425,6 +1425,7 @@ static int generic_ci_d_compare(const struct dentry *dentry, unsigned int len, return 1; return !!memcmp(str, name->name, len); } +EXPORT_SYMBOL(generic_ci_d_compare); /** * generic_ci_d_hash - generic d_hash implementation for casefolding filesystems @@ -1433,7 +1434,7 @@ static int generic_ci_d_compare(const struct dentry *dentry, unsigned int len, * * Return: 0 if hash was successful or unchanged, and -EINVAL on error */ -static int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str) +int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str) { const struct inode *dir = READ_ONCE(dentry->d_inode); struct super_block *sb = dentry->d_sb; @@ -1448,6 +1449,7 @@ static int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str) return -EINVAL; return 0; } +EXPORT_SYMBOL(generic_ci_d_hash); static const struct dentry_operations generic_ci_dentry_ops = { .d_hash = generic_ci_d_hash, diff --git a/include/linux/fs.h b/include/linux/fs.h index ec8f3ddf4a6a..29a0c6371f7d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3313,6 +3313,11 @@ extern int generic_file_fsync(struct file *, loff_t, loff_t, int); extern int generic_check_addressable(unsigned, u64); +#ifdef CONFIG_UNICODE +extern int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str); +extern int generic_ci_d_compare(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name); +#endif extern void generic_set_encrypted_ci_d_ops(struct dentry *dentry); #ifdef CONFIG_MIGRATION From patchwork Tue Mar 23 19:59:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andr=C3=A9_Almeida?= X-Patchwork-Id: 12159177 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 48E70C433C1 for ; Tue, 23 Mar 2021 20:00:10 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id DF54A619C1 for ; Tue, 23 Mar 2021 20:00:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DF54A619C1 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 702156B012E; Tue, 23 Mar 2021 16:00:09 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 68AB06B0131; Tue, 23 Mar 2021 16:00:09 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 505016B0133; Tue, 23 Mar 2021 16:00:09 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0027.hostedemail.com [216.40.44.27]) by kanga.kvack.org (Postfix) with ESMTP id 2CE406B012E for ; Tue, 23 Mar 2021 16:00:09 -0400 (EDT) Received: from smtpin01.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id CB82C173084E for ; Tue, 23 Mar 2021 20:00:08 +0000 (UTC) X-FDA: 77952205296.01.2EC14F8 Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by imf22.hostedemail.com (Postfix) with ESMTP id 3EBF5C001C52 for ; Tue, 23 Mar 2021 20:00:07 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: tonyk) with ESMTPSA id 6A9991F44DB3 From: =?utf-8?q?Andr=C3=A9_Almeida?= To: Hugh Dickins , Andrew Morton , Alexander Viro Cc: krisman@collabora.com, smcv@collabora.com, kernel@collabora.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Daniel Rosenberg , =?utf-8?q?Andr=C3=A9_Almeida?= Subject: [RFC PATCH 2/4] mm: shmem: Support case-insensitive file name lookups Date: Tue, 23 Mar 2021 16:59:39 -0300 Message-Id: <20210323195941.69720-3-andrealmeid@collabora.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210323195941.69720-1-andrealmeid@collabora.com> References: <20210323195941.69720-1-andrealmeid@collabora.com> MIME-Version: 1.0 X-Rspamd-Server: rspam03 X-Rspamd-Queue-Id: 3EBF5C001C52 X-Stat-Signature: h55x6mh49t6fj6ucjjs9mznzf9ydsscr Received-SPF: none (collabora.com>: No applicable sender policy available) receiver=imf22; identity=mailfrom; envelope-from=""; helo=bhuna.collabora.co.uk; client-ip=46.235.227.227 X-HE-DKIM-Result: none/none X-HE-Tag: 1616529607-39268 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: This patch implements the support for case-insensitive file name lookups in tmpfs, based on the encoding passed in the mount options. A filesystem that has the casefold feature set is able to configure directories with the +F (TMPFS_CASEFOLD_FL) attribute, enabling lookups to succeed in that directory in a case-insensitive fashion, i.e: match a directory entry even if the name used by userspace is not a byte per byte match with the disk name, but is an equivalent case-insensitive version of the Unicode string. This operation is called a case-insensitive file name lookup. The feature is configured as an inode attribute applied to directories and inherited by its children. This attribute can only be enabled on empty directories for filesystems that support the encoding feature, thus preventing collision of file names that only differ by case. * dcache handling: For a +F directory, tmpfs only stores the first equivalent name dentry used in the dcache. This is done to prevent unintentional duplication of dentries in the dcache, while also allowing the VFS code to quickly find the right entry in the cache despite which equivalent string was used in a previous lookup, without having to resort to ->lookup(). d_hash() of casefolded directories is implemented as the hash of the casefolded string, such that we always have a well-known bucket for all the equivalencies of the same string. d_compare() uses the utf8_strncasecmp() infrastructure, which handles the comparison of equivalent, same case, names as well. For now, negative lookups are not inserted in the dcache, since they would need to be invalidated anyway, because we can't trust missing file dentries. This is bad for performance but requires some leveraging of the VFS layer to fix. We can live without that for now, and so does everyone else. The lookup() path at tmpfs creates negatives dentries, that are later instantiated if the file is created. In that way, all files in tmpfs have a dentry given that the filesystem exists exclusively in memory. As explained above, we don't have negative dentries for casefold files, so dentries are created at lookup() iff files aren't casefolded. Else, the dentry is created just before being instantiated at create path. At the remove path, dentries are invalidated for casefolded files. * Dealing with invalid sequences: By default, when an invalid UTF-8 sequence is identified, tmpfs will treat it as an opaque byte sequence, ignoring the encoding and reverting to the old behavior for that unique file. This means that case-insensitive file name lookup will not work only for that file. An optional flag (cf_strict) can be set in the mount arguments telling the filesystem code and userspace tools to enforce the encoding. When that optional flag is set, any attempt to create a file name using an invalid UTF-8 sequence will fail and return an error to userspace. Signed-off-by: André Almeida --- include/linux/shmem_fs.h | 1 + mm/shmem.c | 91 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index d82b6f396588..29ee64352807 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -43,6 +43,7 @@ struct shmem_sb_info { spinlock_t shrinklist_lock; /* Protects shrinklist */ struct list_head shrinklist; /* List of shinkable inodes */ unsigned long shrinklist_len; /* Length of shrinklist */ + bool casefold; /* If this mount point supports casefolding */ }; static inline struct shmem_inode_info *SHMEM_I(struct inode *inode) diff --git a/mm/shmem.c b/mm/shmem.c index b2db4ed0fbc7..20df81763995 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -38,6 +38,7 @@ #include #include #include +#include #include /* for arch/microblaze update_mmu_cache() */ @@ -117,6 +118,8 @@ struct shmem_options { bool full_inums; int huge; int seen; + struct unicode_map *encoding; + bool cf_strict; #define SHMEM_SEEN_BLOCKS 1 #define SHMEM_SEEN_INODES 2 #define SHMEM_SEEN_HUGE 4 @@ -161,6 +164,13 @@ static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb) return sb->s_fs_info; } +#ifdef CONFIG_UNICODE +static const struct dentry_operations casefold_dentry_ops = { + .d_hash = generic_ci_d_hash, + .d_compare = generic_ci_d_compare, +}; +#endif + /* * shmem_file_setup pre-accounts the whole fixed size of a VM object, * for shared memory and for shared anonymous (/dev/zero) mappings @@ -2859,8 +2869,18 @@ shmem_mknod(struct user_namespace *mnt_userns, struct inode *dir, struct inode *inode; int error = -ENOSPC; +#ifdef CONFIG_UNICODE + struct super_block *sb = dir->i_sb; + + if (sb_has_strict_encoding(sb) && IS_CASEFOLDED(dir) && + sb->s_encoding && utf8_validate(sb->s_encoding, &dentry->d_name)) + return -EINVAL; +#endif + inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); if (inode) { + inode->i_flags |= dir->i_flags; + error = simple_acl_create(dir, inode); if (error) goto out_iput; @@ -2870,6 +2890,9 @@ shmem_mknod(struct user_namespace *mnt_userns, struct inode *dir, if (error && error != -EOPNOTSUPP) goto out_iput; + if (IS_CASEFOLDED(dir)) + d_add(dentry, NULL); + error = 0; dir->i_size += BOGO_DIRENT_SIZE; dir->i_ctime = dir->i_mtime = current_time(dir); @@ -2925,6 +2948,19 @@ static int shmem_create(struct user_namespace *mnt_userns, struct inode *dir, return shmem_mknod(&init_user_ns, dir, dentry, mode | S_IFREG, 0); } +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); + + if (IS_CASEFOLDED(dir)) + return NULL; + + d_add(dentry, NULL); + + return NULL; +} + /* * Link a file.. */ @@ -2946,6 +2982,9 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr goto out; } + if (IS_CASEFOLDED(dir)) + d_add(dentry, NULL); + dir->i_size += BOGO_DIRENT_SIZE; inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode); inc_nlink(inode); @@ -2967,6 +3006,10 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry) inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode); drop_nlink(inode); dput(dentry); /* Undo the count from "create" - this does all the work */ + + if (IS_CASEFOLDED(dir)) + d_invalidate(dentry); + return 0; } @@ -3128,6 +3171,8 @@ static int shmem_symlink(struct user_namespace *mnt_userns, struct inode *dir, } dir->i_size += BOGO_DIRENT_SIZE; dir->i_ctime = dir->i_mtime = current_time(dir); + if (IS_CASEFOLDED(dir)) + d_add(dentry, NULL); d_instantiate(dentry, inode); dget(dentry); return 0; @@ -3364,6 +3409,8 @@ enum shmem_param { Opt_uid, Opt_inode32, Opt_inode64, + Opt_casefold, + Opt_cf_strict, }; static const struct constant_table shmem_param_enums_huge[] = { @@ -3385,6 +3432,8 @@ const struct fs_parameter_spec shmem_fs_parameters[] = { fsparam_u32 ("uid", Opt_uid), fsparam_flag ("inode32", Opt_inode32), fsparam_flag ("inode64", Opt_inode64), + fsparam_string("casefold", Opt_casefold), + fsparam_flag ("cf_strict", Opt_cf_strict), {} }; @@ -3392,9 +3441,11 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) { struct shmem_options *ctx = fc->fs_private; struct fs_parse_result result; + struct unicode_map *encoding; unsigned long long size; + char version[10]; char *rest; - int opt; + int opt, ret; opt = fs_parse(fc, shmem_fs_parameters, param, &result); if (opt < 0) @@ -3468,6 +3519,23 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) ctx->full_inums = true; ctx->seen |= SHMEM_SEEN_INUMS; break; + case Opt_casefold: + 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); + + encoding = utf8_load(version); + if (IS_ERR(encoding)) + return invalfc(fc, "Invalid utf8 version: %s", version); + pr_info("tmpfs: Using encoding defined by mount options: %s\n", + param->string); + ctx->encoding = encoding; + break; + case Opt_cf_strict: + ctx->cf_strict = true; + break; } return 0; @@ -3646,6 +3714,11 @@ static void shmem_put_super(struct super_block *sb) { struct shmem_sb_info *sbinfo = SHMEM_SB(sb); +#ifdef CONFIG_UNICODE + if (sbinfo->casefold) + utf8_unload(sb->s_encoding); +#endif + free_percpu(sbinfo->ino_batch); percpu_counter_destroy(&sbinfo->used_blocks); mpol_put(sbinfo->mpol); @@ -3686,6 +3759,18 @@ 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; + +#ifdef CONFIG_UNICODE + if (ctx->encoding) { + sb->s_d_op = &casefold_dentry_ops; + sb->s_encoding = ctx->encoding; + if (ctx->cf_strict) + sb->s_encoding_flags = SB_ENC_STRICT_MODE_FL; + sbinfo->casefold = true; + } else if (ctx->cf_strict) { + pr_warn("tmpfs: casefold strict mode enabled without encoding, ignoring\n"); + } +#endif /* CONFIG_UNICODE */ #else sb->s_flags |= SB_NOUSER; #endif @@ -3846,7 +3931,7 @@ static const struct inode_operations shmem_inode_operations = { static const struct inode_operations shmem_dir_inode_operations = { #ifdef CONFIG_TMPFS .create = shmem_create, - .lookup = simple_lookup, + .lookup = shmem_lookup, .link = shmem_link, .unlink = shmem_unlink, .symlink = shmem_symlink, @@ -3912,6 +3997,8 @@ int shmem_init_fs_context(struct fs_context *fc) ctx->mode = 0777 | S_ISVTX; ctx->uid = current_fsuid(); ctx->gid = current_fsgid(); + ctx->encoding = NULL; + ctx->cf_strict = false; fc->fs_private = ctx; fc->ops = &shmem_fs_context_ops; From patchwork Tue Mar 23 19:59:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andr=C3=A9_Almeida?= X-Patchwork-Id: 12159179 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 33A32C433DB for ; Tue, 23 Mar 2021 20:00:13 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id D703F619C8 for ; Tue, 23 Mar 2021 20:00:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D703F619C8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 750006B0133; Tue, 23 Mar 2021 16:00:12 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 6FF936B0147; Tue, 23 Mar 2021 16:00:12 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5A0306B0149; Tue, 23 Mar 2021 16:00:12 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0158.hostedemail.com [216.40.44.158]) by kanga.kvack.org (Postfix) with ESMTP id 384E76B0133 for ; Tue, 23 Mar 2021 16:00:12 -0400 (EDT) Received: from smtpin34.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay04.hostedemail.com (Postfix) with ESMTP id 04E611DF9 for ; Tue, 23 Mar 2021 20:00:12 +0000 (UTC) X-FDA: 77952205464.34.F3245BC Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by imf13.hostedemail.com (Postfix) with ESMTP id 34827E0011C0 for ; Tue, 23 Mar 2021 20:00:11 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: tonyk) with ESMTPSA id C6F111F44DBA From: =?utf-8?q?Andr=C3=A9_Almeida?= To: Hugh Dickins , Andrew Morton , Alexander Viro Cc: krisman@collabora.com, smcv@collabora.com, kernel@collabora.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Daniel Rosenberg , =?utf-8?q?Andr=C3=A9_Almeida?= Subject: [RFC PATCH 3/4] mm: shmem: Add IOCTL support for tmpfs Date: Tue, 23 Mar 2021 16:59:40 -0300 Message-Id: <20210323195941.69720-4-andrealmeid@collabora.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210323195941.69720-1-andrealmeid@collabora.com> References: <20210323195941.69720-1-andrealmeid@collabora.com> MIME-Version: 1.0 X-Stat-Signature: co7wj18frasmgmcxaujt551og5xp9d3d X-Rspamd-Server: rspam02 X-Rspamd-Queue-Id: 34827E0011C0 Received-SPF: none (collabora.com>: No applicable sender policy available) receiver=imf13; identity=mailfrom; envelope-from=""; helo=bhuna.collabora.co.uk; client-ip=46.235.227.227 X-HE-DKIM-Result: none/none X-HE-Tag: 1616529611-246924 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Implement IOCTL operations for files to set/get file flags. Implement the only supported flag by now, that is S_CASEFOLD. Signed-off-by: André Almeida --- include/linux/shmem_fs.h | 4 ++ mm/shmem.c | 84 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 29ee64352807..2c89c5a66508 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -140,4 +140,8 @@ extern int shmem_mfill_zeropage_pte(struct mm_struct *dst_mm, dst_addr) ({ BUG(); 0; }) #endif +#define TMPFS_CASEFOLD_FL 0x40000000 /* Casefolded file */ +#define TMPFS_USER_FLS TMPFS_CASEFOLD_FL /* Userspace supported flags */ +#define TMPFS_FLS S_CASEFOLD /* Kernel supported flags */ + #endif diff --git a/mm/shmem.c b/mm/shmem.c index 20df81763995..2f2c996d215b 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -258,6 +258,7 @@ static inline void shmem_inode_unacct_blocks(struct inode *inode, long pages) static const struct super_operations shmem_ops; const struct address_space_operations shmem_aops; static const struct file_operations shmem_file_operations; +static const struct file_operations shmem_dir_operations; static const struct inode_operations shmem_inode_operations; static const struct inode_operations shmem_dir_inode_operations; static const struct inode_operations shmem_special_inode_operations; @@ -2347,7 +2348,7 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode /* Some things misbehave if size == 0 on a directory */ inode->i_size = 2 * BOGO_DIRENT_SIZE; inode->i_op = &shmem_dir_inode_operations; - inode->i_fop = &simple_dir_operations; + inode->i_fop = &shmem_dir_operations; break; case S_IFLNK: /* @@ -2838,6 +2839,76 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, return error; } +static long shmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret; + u32 fsflags = 0, old, new = 0; + struct inode *inode = file_inode(file); + struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + + switch (cmd) { + case FS_IOC_GETFLAGS: + if ((inode->i_flags & S_CASEFOLD) && S_ISDIR(inode->i_mode)) + fsflags |= TMPFS_CASEFOLD_FL; + + if (put_user(fsflags, (int __user *)arg)) + return -EFAULT; + + return 0; + + case FS_IOC_SETFLAGS: + if (get_user(fsflags, (int __user *)arg)) + return -EFAULT; + + old = inode->i_flags; + + if (fsflags & ~TMPFS_USER_FLS) + return -EINVAL; + + if (fsflags & TMPFS_CASEFOLD_FL) { + if (!sbinfo->casefold) { + pr_err("tmpfs: casefold disabled at this mount point\n"); + return -EOPNOTSUPP; + } + + if (!S_ISDIR(inode->i_mode)) + return -ENOTDIR; + + if (!simple_empty(file_dentry(file))) + return -ENOTEMPTY; + + new |= S_CASEFOLD; + } else if (old & S_CASEFOLD) { + if (!simple_empty(file_dentry(file))) + return -ENOTEMPTY; + } + + ret = mnt_want_write_file(file); + if (ret) + return ret; + + inode_lock(inode); + + ret = vfs_ioc_setflags_prepare(inode, old, new); + if (ret) { + inode_unlock(inode); + mnt_drop_write_file(file); + return ret; + } + + inode_set_flags(inode, new, TMPFS_FLS); + + inode_unlock(inode); + mnt_drop_write_file(file); + return 0; + + default: + return -ENOTTY; + } + + return 0; +} + static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) { struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb); @@ -3916,6 +3987,7 @@ static const struct file_operations shmem_file_operations = { .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, .fallocate = shmem_fallocate, + .unlocked_ioctl = shmem_ioctl, #endif }; @@ -3928,6 +4000,16 @@ static const struct inode_operations shmem_inode_operations = { #endif }; +static const struct file_operations shmem_dir_operations = { + .open = dcache_dir_open, + .release = dcache_dir_close, + .llseek = dcache_dir_lseek, + .read = generic_read_dir, + .iterate_shared = dcache_readdir, + .fsync = noop_fsync, + .unlocked_ioctl = shmem_ioctl, +}; + static const struct inode_operations shmem_dir_inode_operations = { #ifdef CONFIG_TMPFS .create = shmem_create, From patchwork Tue Mar 23 19:59:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andr=C3=A9_Almeida?= X-Patchwork-Id: 12159181 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9080EC433DB for ; Tue, 23 Mar 2021 20:00:16 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 3953461990 for ; Tue, 23 Mar 2021 20:00:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3953461990 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id CF4CF6B0149; Tue, 23 Mar 2021 16:00:15 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id CA5E26B014A; Tue, 23 Mar 2021 16:00:15 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B45516B0160; Tue, 23 Mar 2021 16:00:15 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0179.hostedemail.com [216.40.44.179]) by kanga.kvack.org (Postfix) with ESMTP id 94B5A6B0149 for ; Tue, 23 Mar 2021 16:00:15 -0400 (EDT) Received: from smtpin27.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 57FBC180F68A3 for ; Tue, 23 Mar 2021 20:00:15 +0000 (UTC) X-FDA: 77952205590.27.37BB8FE Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by imf05.hostedemail.com (Postfix) with ESMTP id 6E847E00023A for ; Tue, 23 Mar 2021 20:00:14 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: tonyk) with ESMTPSA id 145E31F44E0F From: =?utf-8?q?Andr=C3=A9_Almeida?= To: Hugh Dickins , Andrew Morton , Alexander Viro Cc: krisman@collabora.com, smcv@collabora.com, kernel@collabora.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Daniel Rosenberg , =?utf-8?q?Andr=C3=A9_Almeida?= Subject: [RFC PATCH 4/4] docs: tmpfs: Add casefold options Date: Tue, 23 Mar 2021 16:59:41 -0300 Message-Id: <20210323195941.69720-5-andrealmeid@collabora.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210323195941.69720-1-andrealmeid@collabora.com> References: <20210323195941.69720-1-andrealmeid@collabora.com> MIME-Version: 1.0 X-Stat-Signature: wu3zt8djysuw3ruqintsuw655fuhjsdb X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: 6E847E00023A Received-SPF: none (collabora.com>: No applicable sender policy available) receiver=imf05; identity=mailfrom; envelope-from=""; helo=bhuna.collabora.co.uk; client-ip=46.235.227.227 X-HE-DKIM-Result: none/none X-HE-Tag: 1616529614-772767 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Document mounting options to enable casefold support in tmpfs. Signed-off-by: André Almeida --- Documentation/filesystems/tmpfs.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst index 0408c245785e..84c87c309bd7 100644 --- a/Documentation/filesystems/tmpfs.rst +++ b/Documentation/filesystems/tmpfs.rst @@ -170,6 +170,32 @@ 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 enconding. Currently only utf8 encondings are supported. +cf_strict Enable strict casefolding at this mouting point (disabled by + default). This means that invalid strings should be reject 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 tmpfs /mytmpfs + $ cd /mytmpfs + $ touch a; touch A + $ ls + A a + $ mkdir dir + $ chattr +F dir + $ touch dir/a; touch dir/A + $ ls dir + a :Author: Christoph Rohland , 1.12.01