linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
To: viro@ZenIV.linux.org.uk
Cc: linux-fsdevel@vger.kernel.org,
	Gabriel Krisman Bertazi <krisman@collabora.co.uk>
Subject: [PATCH NOMERGE 02/13] vfs: Propagate LOOKUP_CASEFOLD after doing parent lookups
Date: Tue, 22 May 2018 17:38:07 -0300	[thread overview]
Message-ID: <20180522203818.14666-3-krisman@collabora.co.uk> (raw)
In-Reply-To: <20180522203818.14666-1-krisman@collabora.co.uk>

filename_parentat() is executed in order to quickly access a child
dentry for creation, unlinking or rename, outside the path_walk path.
Although, if the parent was accessed via a CI mount, we need to make
sure the child will also be searched in a CI manner, so the nameidata
flag from the first search needs to be propageted to the following child
__lookup_hash call.

Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
---
 fs/namei.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 54 insertions(+), 7 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index ddd5c9e9ab3c..135a9a4e676b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2369,7 +2369,7 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
 
 static struct filename *filename_parentat(int dfd, struct filename *name,
 				unsigned int flags, struct path *parent,
-				struct qstr *last, int *type)
+				struct qstr *last, int *type, bool *foldtree)
 {
 	int retval;
 	struct nameidata nd;
@@ -2385,6 +2385,7 @@ static struct filename *filename_parentat(int dfd, struct filename *name,
 	if (likely(!retval)) {
 		*last = nd.last;
 		*type = nd.last_type;
+		*foldtree = !!(nd.flags & LOOKUP_CASEFOLD);
 		audit_inode(name, parent->dentry, LOOKUP_PARENT);
 	} else {
 		putname(name);
@@ -2401,9 +2402,14 @@ struct dentry *kern_path_locked(const char *name, struct path *path)
 	struct dentry *d;
 	struct qstr last;
 	int type;
+	bool foldtree = false;
 
 	filename = filename_parentat(AT_FDCWD, getname_kernel(name), 0, path,
-				    &last, &type);
+				     &last, &type, &foldtree);
+
+	/* kernel path don't care about foldtree.  Root cannot be folded. */
+	WARN_ON(foldtree);
+
 	if (IS_ERR(filename))
 		return ERR_CAST(filename);
 	if (unlikely(type != LAST_NORM)) {
@@ -3620,6 +3626,7 @@ static struct dentry *filename_create(int dfd, struct filename *name,
 	int err2;
 	int error;
 	bool is_dir = (lookup_flags & LOOKUP_DIRECTORY);
+	bool foldtree = false;
 
 	/*
 	 * Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any
@@ -3627,7 +3634,8 @@ static struct dentry *filename_create(int dfd, struct filename *name,
 	 */
 	lookup_flags &= LOOKUP_REVAL;
 
-	name = filename_parentat(dfd, name, lookup_flags, path, &last, &type);
+	name = filename_parentat(dfd, name, lookup_flags, path, &last,
+				 &type, &foldtree);
 	if (IS_ERR(name))
 		return ERR_CAST(name);
 
@@ -3644,6 +3652,16 @@ static struct dentry *filename_create(int dfd, struct filename *name,
 	 * Do the final lookup.
 	 */
 	lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL;
+
+	/* If parent is a casefold mountpoint, search for an existing
+	 * dentry with LOOKUP_CASEFOLD.
+	 * LOOKUP_CASEFOLD needs to be explicitly cleared in case it is
+	 * doing retry. */
+	if (foldtree)
+		lookup_flags |= LOOKUP_CASEFOLD;
+	else
+		lookup_flags &= ~LOOKUP_CASEFOLD;
+
 	inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
 	dentry = __lookup_hash(&last, path->dentry, lookup_flags);
 	if (IS_ERR(dentry))
@@ -3904,9 +3922,10 @@ static long do_rmdir(int dfd, const char __user *pathname)
 	struct qstr last;
 	int type;
 	unsigned int lookup_flags = 0;
+	bool foldtree;
 retry:
 	name = filename_parentat(dfd, getname(pathname), lookup_flags,
-				&path, &last, &type);
+				 &path, &last, &type, &foldtree);
 	if (IS_ERR(name))
 		return PTR_ERR(name);
 
@@ -3926,6 +3945,13 @@ static long do_rmdir(int dfd, const char __user *pathname)
 	if (error)
 		goto exit1;
 
+	/* LOOKUP_CASEFOLD needs to be explicitly cleared in case it is
+	 * doing retry. */
+	if (foldtree)
+		lookup_flags |= LOOKUP_CASEFOLD;
+	else
+		lookup_flags &= ~LOOKUP_CASEFOLD;
+
 	inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
 	dentry = __lookup_hash(&last, path.dentry, lookup_flags);
 	error = PTR_ERR(dentry);
@@ -4033,8 +4059,10 @@ long do_unlinkat(int dfd, struct filename *name)
 	struct inode *inode = NULL;
 	struct inode *delegated_inode = NULL;
 	unsigned int lookup_flags = 0;
+	bool foldtree = false;
 retry:
-	name = filename_parentat(dfd, name, lookup_flags, &path, &last, &type);
+	name = filename_parentat(dfd, name, lookup_flags, &path, &last, &type,
+				 &foldtree);
 	if (IS_ERR(name))
 		return PTR_ERR(name);
 
@@ -4045,6 +4073,13 @@ long do_unlinkat(int dfd, struct filename *name)
 	error = mnt_want_write(path.mnt);
 	if (error)
 		goto exit1;
+
+	/* LOOKUP_CASEFOLD needs to be explicitly cleared in case it is
+	 * doing retry. */
+	if (foldtree)
+		lookup_flags |= LOOKUP_CASEFOLD;
+	else
+		lookup_flags &= ~LOOKUP_CASEFOLD;
 retry_deleg:
 	inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
 	dentry = __lookup_hash(&last, path.dentry, lookup_flags);
@@ -4514,6 +4549,7 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
 	struct filename *to;
 	unsigned int lookup_flags = 0, target_flags = LOOKUP_RENAME_TARGET;
 	bool should_retry = false;
+	bool foldtree = false;
 	int error;
 
 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
@@ -4531,14 +4567,14 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
 
 retry:
 	from = filename_parentat(olddfd, getname(oldname), lookup_flags,
-				&old_path, &old_last, &old_type);
+				 &old_path, &old_last, &old_type, &foldtree);
 	if (IS_ERR(from)) {
 		error = PTR_ERR(from);
 		goto exit;
 	}
 
 	to = filename_parentat(newdfd, getname(newname), lookup_flags,
-				&new_path, &new_last, &new_type);
+			       &new_path, &new_last, &new_type, &foldtree);
 	if (IS_ERR(to)) {
 		error = PTR_ERR(to);
 		goto exit1;
@@ -4561,6 +4597,17 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
 	if (error)
 		goto exit2;
 
+	/* Since rename(2) doesn't work across mountpoints, we are sure
+	 * that foldtree for TO and FROM are the same.
+	 *
+	 * LOOKUP_CASEFOLD needs to be explicitly cleared in case it is
+	 * doing retry. */
+	if (foldtree)
+		lookup_flags |= LOOKUP_CASEFOLD;
+	else
+		lookup_flags &= ~LOOKUP_CASEFOLD;
+
+
 retry_deleg:
 	trap = lock_rename(new_path.dentry, old_path.dentry);
 
-- 
2.17.0

  parent reply	other threads:[~2018-05-22 20:37 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-22 20:38 [PATCH NOMERGE 00/13] Case insensitiveness as a mountpoint Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 01/13] vfs: Add support for mounting with MS_CASEFOLD Gabriel Krisman Bertazi
2018-05-22 20:38 ` Gabriel Krisman Bertazi [this message]
2018-05-22 20:38 ` [PATCH NOMERGE 03/13] vfs: Add support for positive dentries CI lookups in the dentry cache Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 04/13] vfs: Allow bind,remount with MS_CASEFOLD Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 05/13] vfs: Handle case-exact lookup in d_add_ci Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 06/13] vfs: Add Support for hard negative dentries in the dcache Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 07/13] vfs: Handle MNT_CASEFOLD in /proc/mounts Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 08/13] fscrypt: Introduce charset-based matching functions Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 09/13] ext4: Include encoding information on the superblock Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 10/13] ext4: Plumb LOOK_CASEFOLD up to ext4 comparison functions Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 11/13] ext4: Support charset name matching Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 12/13] ext4: Implement ext4 dcache hooks for custom charsets Gabriel Krisman Bertazi
2018-05-22 20:38 ` [PATCH NOMERGE 13/13] ext4: Notify VFS of support for casefolded mountpoints Gabriel Krisman Bertazi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180522203818.14666-3-krisman@collabora.co.uk \
    --to=krisman@collabora.co.uk \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).