lkml.org 
[lkml]   [2015]   [May]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 71/79] namei: make should_follow_link() store the link in nd->link
Date
From: Al Viro <viro@zeniv.linux.org.uk>

... if it decides to follow, that is.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/namei.c | 63 +++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 34 insertions(+), 29 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 5eb8b0c..026d7df 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1558,15 +1558,31 @@ static void terminate_walk(struct nameidata *nd)
put_link(nd);
}

+static int pick_link(struct nameidata *nd, struct path *link)
+{
+ if (nd->flags & LOOKUP_RCU) {
+ if (unlikely(nd->path.mnt != link->mnt ||
+ unlazy_walk(nd, link->dentry))) {
+ return -ECHILD;
+ }
+ }
+ nd->link = *link;
+ return 1;
+}
+
/*
* Do we need to follow links? We _really_ want to be able
* to do this check without having to look at inode->i_op,
* so we keep a cache of "no, this doesn't need follow_link"
* for the common case.
*/
-static inline int should_follow_link(struct dentry *dentry, int follow)
+static inline int should_follow_link(struct nameidata *nd, struct path *link, int follow)
{
- return unlikely(d_is_symlink(dentry)) ? follow : 0;
+ if (likely(!d_is_symlink(link->dentry)))
+ return 0;
+ if (!follow)
+ return 0;
+ return pick_link(nd, link);
}

enum {WALK_GET = 1, WALK_PUT = 2};
@@ -1604,17 +1620,9 @@ static int walk_component(struct nameidata *nd, int flags)

if (flags & WALK_PUT)
put_link(nd);
- if (should_follow_link(path.dentry, flags & WALK_GET)) {
- if (nd->flags & LOOKUP_RCU) {
- if (unlikely(nd->path.mnt != path.mnt ||
- unlazy_walk(nd, path.dentry))) {
- return -ECHILD;
- }
- }
- BUG_ON(inode != path.dentry->d_inode);
- nd->link = path;
- return 1;
- }
+ err = should_follow_link(nd, &path, flags & WALK_GET);
+ if (unlikely(err))
+ return err;
path_to_nameidata(&path, nd);
nd->inode = inode;
return 0;
@@ -2367,9 +2375,11 @@ done:
put_link(nd);
path->dentry = dentry;
path->mnt = nd->path.mnt;
- if (should_follow_link(dentry, nd->flags & LOOKUP_FOLLOW)) {
- nd->link = *path;
- return 1;
+ error = should_follow_link(nd, path, nd->flags & LOOKUP_FOLLOW);
+ if (unlikely(error)) {
+ if (error < 0)
+ goto out;
+ return error;
}
mntget(path->mnt);
follow_mount(path);
@@ -3089,19 +3099,14 @@ finish_lookup:
goto out;
}

- if (should_follow_link(path.dentry, nd->flags & LOOKUP_FOLLOW)) {
- if (nd->flags & LOOKUP_RCU) {
- if (unlikely(nd->path.mnt != path.mnt ||
- unlazy_walk(nd, path.dentry))) {
- error = -ECHILD;
- goto out;
- }
- }
- BUG_ON(inode != path.dentry->d_inode);
- if (nd->depth)
- put_link(nd);
- nd->link = path;
- return 1;
+ if (nd->depth)
+ put_link(nd);
+
+ error = should_follow_link(nd, &path, nd->flags & LOOKUP_FOLLOW);
+ if (unlikely(error)) {
+ if (error < 0)
+ goto out;
+ return error;
}

if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
--
2.1.4


\
 
 \ /
  Last update: 2015-05-05 07:41    [W:0.514 / U:82.516 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site