All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.de>
To: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 3/9] VFS/namei: new flag to support RCU symlinks: LOOKUP_LINK_RCU.
Date: Thu, 05 Mar 2015 16:21:21 +1100	[thread overview]
Message-ID: <20150305052121.23906.84068.stgit@notabene.brown> (raw)
In-Reply-To: <20150305051530.23906.65097.stgit@notabene.brown>

When we support ->follow_link in RCU-walk we will not want to
take a reference to the 'struct path *link' passed to follow_link,
and correspondingly will not want to drop that reference.

As link_path_walk will complete_walk() in the case of an error,
and as complete_walk() will clear LOOKUP_RCU, we cannot test
LOOKUP_RCU to determine if the path should be 'put'.

So introduce a new flag: LOOKUP_LINK_RCU.  This is set on
entry to follow_link() if appropriate and put_link() will
only call path_put() if it is clear.

Also, unlazy_walk() will fail if LOOKUP_LINK_RCU is set.
This is because there is no way for unlazy_walk to get references
on all the "struct path *link"s that are protected by that flag.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 fs/namei.c            |   18 +++++++++++++-----
 include/linux/namei.h |    1 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 515adc4594be..a4879bb3b4ee 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -533,6 +533,9 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
 	struct dentry *parent = nd->path.dentry;
 
 	BUG_ON(!(nd->flags & LOOKUP_RCU));
+	if (nd->flags & LOOKUP_LINK_RCU)
+		/* Cannot unlazy in the middle of following a symlink */
+		return -ECHILD;
 
 	/*
 	 * After legitimizing the bastards, terminate_walk()
@@ -743,7 +746,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
 	struct inode *inode = link->dentry->d_inode;
 	if (inode->i_op->put_link)
 		inode->i_op->put_link(link->dentry, nd, cookie);
-	path_put(link);
+	if (!(nd->flags & LOOKUP_LINK_RCU))
+		path_put(link);
 }
 
 int sysctl_protected_symlinks __read_mostly = 0;
@@ -869,9 +873,10 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
 	int error;
 	char *s;
 
-	BUG_ON(nd->flags & LOOKUP_RCU);
-
-	if (link->mnt == nd->path.mnt)
+	nd->flags &= ~LOOKUP_LINK_RCU;
+	if (nd->flags & LOOKUP_RCU)
+		nd->flags |= LOOKUP_LINK_RCU;
+	else if (link->mnt == nd->path.mnt)
 		mntget(link->mnt);
 
 	error = -ELOOP;
@@ -921,7 +926,8 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
 out_put_nd_path:
 	*p = NULL;
 	terminate_walk(nd);
-	path_put(link);
+	if (!(nd->flags & LOOKUP_LINK_RCU))
+		path_put(link);
 	return error;
 }
 
@@ -1644,6 +1650,8 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
 
 	current->link_count--;
 	nd->depth--;
+	if (!nd->depth)
+		nd->flags &= ~LOOKUP_LINK_RCU;
 	return res;
 }
 
diff --git a/include/linux/namei.h b/include/linux/namei.h
index c8990779f0c3..34bc87845b0e 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -32,6 +32,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_PARENT		0x0010
 #define LOOKUP_REVAL		0x0020
 #define LOOKUP_RCU		0x0040
+#define LOOKUP_LINK_RCU		0x0080
 
 /*
  * Intent data

  reply	other threads:[~2015-03-05  5:21 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-05  5:21 [PATCH 0/9] Support follow_link in RCU-walk NeilBrown
2015-03-05  5:21 ` NeilBrown [this message]
2015-03-05  5:21 ` [PATCH 8/9] XFS: allow follow_link to often succeed " NeilBrown
2015-03-05  5:21 ` [PATCH 7/9] VFS/namei: handle LOOKUP_RCU in page_follow_link_light NeilBrown
2015-03-05  5:21 ` [PATCH 4/9] VFS/namei: abort RCU-walk on symlink if atime needs updating NeilBrown
2015-03-05  5:21 ` [PATCH 6/9] VFS/namei: enable RCU-walk when following symlinks NeilBrown
2015-03-05  5:21 ` [PATCH 1/9] FS: make all ->follow_link handlers aware for LOOKUP_RCU NeilBrown
2015-03-05  5:21 ` [PATCH 9/9] NFS: support LOOKUP_RCU in nfs_follow_link NeilBrown
2015-03-05  5:21 ` [PATCH 2/9] VFS/namei: use terminate_walk when symlink lookup fails NeilBrown
2015-03-05  5:21 ` [PATCH 5/9] VFS/namei: enhance follow_link to support RCU-walk NeilBrown
2015-03-05  6:05 ` [PATCH 0/9] Support follow_link in RCU-walk Al Viro
2015-03-05 13:52   ` John Stoffel
2015-03-05 16:00     ` Al Viro
2015-03-05 17:17       ` John Stoffel
2015-03-05 21:08   ` NeilBrown
2015-03-09  2:21   ` NeilBrown

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=20150305052121.23906.84068.stgit@notabene.brown \
    --to=neilb@suse.de \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.