From: NeilBrown <neilb@suse.de>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 03/13] VFS: remove nameidata args from ->follow_link and ->put_link
Date: Mon, 16 Mar 2015 15:43:19 +1100 [thread overview]
Message-ID: <20150316044319.23648.2840.stgit@notabene.brown> (raw)
In-Reply-To: <20150316043602.23648.52734.stgit@notabene.brown>
Now that current->nameidata is available, nd_set_link() and
nd_get_link() can use that directly, so 'nd' doesn't need to
be passed through ->follow_link and ->put_link.
->follow_link gains a 'flags' argument instead which will
be useful for adding RCU-walk support.
For now, any filesystem which cannot trivially handle RCU-walk
support simply returns -ECHILD if LOOKUP_RCU is set in 'flags'.
security_inode_follow_link() all gets 'flags' in place of 'nd',
as does the inode_follow_link() security_op.
As a result of this change, 'nameidata' is almost entirely
local to namei.c. It is only exposed externally as an opaque struct
pointed to by current->nameidata.
Note: Documentation/filesystemd/automount-support.txt mentions
nameidata in ways that have been wrong for a while and are still
wrong.
Signed-off-by: NeilBrown <neilb@suse.de>
---
Documentation/filesystems/Locking | 4 +--
Documentation/filesystems/automount-support.txt | 3 ++
Documentation/filesystems/porting | 5 +++
Documentation/filesystems/vfs.txt | 4 +--
drivers/staging/lustre/lustre/llite/symlink.c | 8 +++--
fs/9p/v9fs.h | 3 +-
fs/9p/vfs_inode.c | 13 ++++----
fs/9p/vfs_inode_dotl.c | 8 +++--
fs/autofs4/symlink.c | 4 +--
fs/befs/linuxvfs.c | 14 ++++-----
fs/ceph/inode.c | 4 +--
fs/cifs/cifsfs.h | 2 +
fs/cifs/link.c | 6 ++--
fs/configfs/symlink.c | 11 +++----
fs/debugfs/file.c | 4 +--
fs/ecryptfs/inode.c | 8 ++---
fs/exofs/symlink.c | 4 +--
fs/ext2/symlink.c | 4 +--
fs/ext3/symlink.c | 4 +--
fs/ext4/symlink.c | 4 +--
fs/freevxfs/vxfs_immed.c | 8 +++--
fs/fuse/dir.c | 10 +++---
fs/gfs2/inode.c | 10 +++---
fs/hostfs/hostfs_kern.c | 10 +++---
fs/hppfs/hppfs.c | 9 +++---
fs/jffs2/symlink.c | 6 ++--
fs/jfs/symlink.c | 4 +--
fs/kernfs/symlink.c | 11 +++----
fs/libfs.c | 5 +--
fs/namei.c | 36 +++++++++++++----------
fs/nfs/symlink.c | 8 +++--
fs/ntfs/namei.c | 1 -
fs/overlayfs/inode.c | 12 ++++----
fs/proc/base.c | 6 ++--
fs/proc/inode.c | 6 ++--
fs/proc/namespaces.c | 6 ++--
fs/proc/self.c | 6 ++--
fs/proc/thread_self.c | 6 ++--
fs/sysv/symlink.c | 4 +--
fs/ubifs/file.c | 4 +--
fs/ufs/symlink.c | 4 +--
fs/xfs/xfs_iops.c | 8 +++--
include/linux/fs.h | 12 +++-----
include/linux/namei.h | 7 ++--
include/linux/sched.h | 1 +
include/linux/security.h | 9 +++---
mm/shmem.c | 14 ++++-----
security/capability.c | 2 +
security/security.c | 4 +--
security/selinux/hooks.c | 2 +
50 files changed, 175 insertions(+), 173 deletions(-)
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index f91926f2f482..8a772d4bb51f 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -50,8 +50,8 @@ prototypes:
int (*rename2) (struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int);
int (*readlink) (struct dentry *, char __user *,int);
- void * (*follow_link) (struct dentry *, struct nameidata *);
- void (*put_link) (struct dentry *, struct nameidata *, void *);
+ void * (*follow_link) (struct dentry *, int flags);
+ void (*put_link) (struct dentry *, void *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, unsigned int);
int (*get_acl)(struct inode *, int);
diff --git a/Documentation/filesystems/automount-support.txt b/Documentation/filesystems/automount-support.txt
index 7cac200e2a85..b68370fcc8f8 100644
--- a/Documentation/filesystems/automount-support.txt
+++ b/Documentation/filesystems/automount-support.txt
@@ -8,6 +8,9 @@ requested. The latter can also be requested by userspace.
IN-KERNEL AUTOMOUNTING
======================
+THE FOLLOWING IS WRONG AND NEED TO BE UPDATED
+
+
A filesystem can now mount another filesystem on one of its directories by the
following procedure:
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index fa2db081505e..d6d228d54993 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -471,3 +471,8 @@ in your dentry operations instead.
[mandatory]
f_dentry is gone; use f_path.dentry, or, better yet, see if you can avoid
it entirely.
+--
+[mandatory]
+ ->follow_link and ->put_link no longer receive 'struct nameidata *'.
+ ->follow_link receives flags which may contains LOOKUP_RCU.
+ When that is set code must not block, but can return -ECHILD.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 966b22829f3b..a813af5ee097 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -350,8 +350,8 @@ struct inode_operations {
int (*rename2) (struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int);
int (*readlink) (struct dentry *, char __user *,int);
- void * (*follow_link) (struct dentry *, struct nameidata *);
- void (*put_link) (struct dentry *, struct nameidata *, void *);
+ void * (*follow_link) (struct dentry *, int flags);
+ void (*put_link) (struct dentry *, void *);
int (*permission) (struct inode *, int);
int (*get_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c
index e8a8d25fcabf..e1f4ef3356ae 100644
--- a/drivers/staging/lustre/lustre/llite/symlink.c
+++ b/drivers/staging/lustre/lustre/llite/symlink.c
@@ -118,14 +118,14 @@ failed:
return rc;
}
-static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ll_follow_link(struct dentry *dentry, int flags)
{
struct inode *inode = dentry->d_inode;
struct ptlrpc_request *request = NULL;
int rc;
char *symname = NULL;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
CDEBUG(D_VFSTRACE, "VFS Op\n");
@@ -139,14 +139,14 @@ static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
symname = ERR_PTR(rc);
}
- nd_set_link(nd, symname);
+ nd_set_link(symname);
/* symname may contain a pointer to the request message buffer,
* we delay request releasing until ll_put_link then.
*/
return request;
}
-static void ll_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+static void ll_put_link(struct dentry *dentry, void *cookie)
{
ptlrpc_req_finished(cookie);
}
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 099c7712631c..b50310bf5bac 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -150,8 +150,7 @@ extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
-extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
- void *p);
+extern void v9fs_vfs_put_link(struct dentry *dentry, void *p);
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
struct p9_fid *fid,
struct super_block *sb, int new);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 8aff5d684154..f3bc0640dd4c 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1274,16 +1274,16 @@ done:
/**
* v9fs_vfs_follow_link - follow a symlink path
* @dentry: dentry for symlink
- * @nd: nameidata
+ * @flags: lookup flags
*
*/
-static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *v9fs_vfs_follow_link(struct dentry *dentry, int flags)
{
int len = 0;
char *link;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
link = __getname();
@@ -1300,7 +1300,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
} else
link[min(len, PATH_MAX-1)] = 0;
}
- nd_set_link(nd, link);
+ nd_set_link(link);
return NULL;
}
@@ -1308,15 +1308,14 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
/**
* v9fs_vfs_put_link - release a symlink path
* @dentry: dentry for symlink
- * @nd: nameidata
* @p: unused
*
*/
void
-v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+v9fs_vfs_put_link(struct dentry *dentry, void *p)
{
- char *s = nd_get_link(nd);
+ char *s = nd_get_link();
p9_debug(P9_DEBUG_VFS, " %pd %s\n",
dentry, IS_ERR(s) ? "<error>" : s);
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 51776a3cc842..5862720911aa 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -905,19 +905,19 @@ error:
/**
* v9fs_vfs_follow_link_dotl - follow a symlink path
* @dentry: dentry for symlink
- * @nd: nameidata
+ * @flags: lookup flags
*
*/
static void *
-v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
+v9fs_vfs_follow_link_dotl(struct dentry *dentry, int flags)
{
int retval;
struct p9_fid *fid;
char *link;
char *target;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
link = __getname();
p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
@@ -941,7 +941,7 @@ v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
__putname(link);
link = ERR_PTR(retval);
ndset:
- nd_set_link(nd, link);
+ nd_set_link(link);
return NULL;
}
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c
index 1e8ea192be2b..311f176708ae 100644
--- a/fs/autofs4/symlink.c
+++ b/fs/autofs4/symlink.c
@@ -12,13 +12,13 @@
#include "autofs_i.h"
-static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *autofs4_follow_link(struct dentry *dentry, int flags)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
if (ino && !autofs4_oz_mode(sbi))
ino->last_used = jiffies;
- nd_set_link(nd, dentry->d_inode->i_private);
+ nd_set_link(dentry->d_inode->i_private);
return NULL;
}
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index bbe8f90924b2..b129966e7277 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -42,8 +42,8 @@ static struct inode *befs_iget(struct super_block *, unsigned long);
static struct inode *befs_alloc_inode(struct super_block *sb);
static void befs_destroy_inode(struct inode *inode);
static void befs_destroy_inodecache(void);
-static void *befs_follow_link(struct dentry *, struct nameidata *);
-static void *befs_fast_follow_link(struct dentry *, struct nameidata *);
+static void *befs_follow_link(struct dentry *, int);
+static void *befs_fast_follow_link(struct dentry *, int);
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
char **out, int *out_len);
static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
@@ -469,7 +469,7 @@ befs_destroy_inodecache(void)
* flag is set.
*/
static void *
-befs_follow_link(struct dentry *dentry, struct nameidata *nd)
+befs_follow_link(struct dentry *dentry, int flags)
{
struct super_block *sb = dentry->d_sb;
befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
@@ -477,7 +477,7 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
befs_off_t len = data->size;
char *link;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
if (len == 0) {
befs_error(sb, "Long symlink with illegal length");
@@ -496,16 +496,16 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
link[len - 1] = '\0';
}
}
- nd_set_link(nd, link);
+ nd_set_link(link);
return NULL;
}
static void *
-befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
+befs_fast_follow_link(struct dentry *dentry, int flags)
{
befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
- nd_set_link(nd, befs_ino->i_data.symlink);
+ nd_set_link(befs_ino->i_data.symlink);
return NULL;
}
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 119c43c80638..ceaa82d3a157 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1691,10 +1691,10 @@ retry:
/*
* symlinks
*/
-static void *ceph_sym_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ceph_sym_follow_link(struct dentry *dentry, int flags)
{
struct ceph_inode_info *ci = ceph_inode(dentry->d_inode);
- nd_set_link(nd, ci->i_symlink);
+ nd_set_link(ci->i_symlink);
return NULL;
}
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 252f5c15806b..f40f664a8c51 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -120,7 +120,7 @@ extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
#endif
/* Functions related to symlinks */
-extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
+extern void *cifs_follow_link(struct dentry *direntry, int flags);
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 0dbe1a326632..148a9b54669f 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -627,7 +627,7 @@ cifs_hl_exit:
}
void *
-cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
+cifs_follow_link(struct dentry *direntry, int flags)
{
struct inode *inode = direntry->d_inode;
int rc = -ENOMEM;
@@ -639,7 +639,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
xid = get_xid();
@@ -681,7 +681,7 @@ out:
free_xid(xid);
if (tlink)
cifs_put_tlink(tlink);
- nd_set_link(nd, target_path);
+ nd_set_link(target_path);
return NULL;
}
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index 1397342aad5b..a83685894e1c 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -279,12 +279,12 @@ static int configfs_getlink(struct dentry *dentry, char * path)
}
-static void *configfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *configfs_follow_link(struct dentry *dentry, int flags)
{
int error = -ENOMEM;
unsigned long page;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
page = get_zeroed_page(GFP_KERNEL);
@@ -292,17 +292,16 @@ static void *configfs_follow_link(struct dentry *dentry, struct nameidata *nd)
if (page) {
error = configfs_getlink(dentry, (char *)page);
if (!error) {
- nd_set_link(nd, (char *)page);
+ nd_set_link((char *)page);
return (void *)page;
}
}
- nd_set_link(nd, ERR_PTR(error));
+ nd_set_link(ERR_PTR(error));
return NULL;
}
-static void configfs_put_link(struct dentry *dentry, struct nameidata *nd,
- void *cookie)
+static void configfs_put_link(struct dentry *dentry, void *cookie)
{
if (cookie) {
unsigned long page = (unsigned long)cookie;
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 517e64938438..3dd676a2a4c0 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -43,9 +43,9 @@ const struct file_operations debugfs_file_operations = {
.llseek = noop_llseek,
};
-static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *debugfs_follow_link(struct dentry *dentry, int flags)
{
- nd_set_link(nd, dentry->d_inode->i_private);
+ nd_set_link(dentry->d_inode->i_private);
return NULL;
}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 49d3dd96344c..47f8d3a3ff48 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -170,7 +170,6 @@ out_unlock:
* @directory_inode: inode of the new file's dentry's parent in ecryptfs
* @ecryptfs_dentry: New file's dentry in ecryptfs
* @mode: The mode of the new file
- * @nd: nameidata of ecryptfs' parent's dentry & vfsmount
*
* Creates the underlying file and the eCryptfs inode which will link to
* it. It will also update the eCryptfs directory inode to mimic the
@@ -384,7 +383,6 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
* ecryptfs_lookup
* @ecryptfs_dir_inode: The eCryptfs directory inode
* @ecryptfs_dentry: The eCryptfs dentry that we are looking up
- * @ecryptfs_nd: nameidata; may be NULL
*
* Find a file on disk. If the file does not exist, then we'll add it to the
* dentry cache and continue on to read it from the disk.
@@ -675,12 +673,12 @@ out:
return rc ? ERR_PTR(rc) : buf;
}
-static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ecryptfs_follow_link(struct dentry *dentry, int flags)
{
size_t len;
char *buf;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
buf = ecryptfs_readlink_lower(dentry, &len);
@@ -690,7 +688,7 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
ecryptfs_dentry_to_lower(dentry)->d_inode);
buf[len] = '\0';
out:
- nd_set_link(nd, buf);
+ nd_set_link(buf);
return NULL;
}
diff --git a/fs/exofs/symlink.c b/fs/exofs/symlink.c
index 832e2624b80b..5565f457358c 100644
--- a/fs/exofs/symlink.c
+++ b/fs/exofs/symlink.c
@@ -35,11 +35,11 @@
#include "exofs.h"
-static void *exofs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *exofs_follow_link(struct dentry *dentry, int flags)
{
struct exofs_i_info *oi = exofs_i(dentry->d_inode);
- nd_set_link(nd, (char *)oi->i_data);
+ nd_set_link((char *)oi->i_data);
return NULL;
}
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 565cf817bbf1..dbad23054842 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -21,10 +21,10 @@
#include "xattr.h"
#include <linux/namei.h>
-static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ext2_follow_link(struct dentry *dentry, int flags)
{
struct ext2_inode_info *ei = EXT2_I(dentry->d_inode);
- nd_set_link(nd, (char *)ei->i_data);
+ nd_set_link((char *)ei->i_data);
return NULL;
}
diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c
index 6b01c3eab1f3..28bee0541bc1 100644
--- a/fs/ext3/symlink.c
+++ b/fs/ext3/symlink.c
@@ -21,10 +21,10 @@
#include "ext3.h"
#include "xattr.h"
-static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void * ext3_follow_link(struct dentry *dentry, int flags)
{
struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
- nd_set_link(nd, (char*)ei->i_data);
+ nd_set_link((char*)ei->i_data);
return NULL;
}
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index ff3711932018..eb987cc01c85 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -23,10 +23,10 @@
#include "ext4.h"
#include "xattr.h"
-static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ext4_follow_link(struct dentry *dentry, int flags)
{
struct ext4_inode_info *ei = EXT4_I(dentry->d_inode);
- nd_set_link(nd, (char *) ei->i_data);
+ nd_set_link((char *) ei->i_data);
return NULL;
}
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index c36aeaf92e41..ea20270f46f8 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -39,7 +39,7 @@
#include "vxfs_inode.h"
-static void * vxfs_immed_follow_link(struct dentry *, struct nameidata *);
+static void * vxfs_immed_follow_link(struct dentry *, int);
static int vxfs_immed_readpage(struct file *, struct page *);
@@ -64,7 +64,7 @@ const struct address_space_operations vxfs_immed_aops = {
/**
* vxfs_immed_follow_link - follow immed symlink
* @dp: dentry for the link
- * @np: pathname lookup data for the current path walk
+ * @flags: lookup flags for the current path walk
*
* Description:
* vxfs_immed_follow_link restarts the pathname lookup with
@@ -74,10 +74,10 @@ const struct address_space_operations vxfs_immed_aops = {
* Zero on success, else a negative error code.
*/
static void *
-vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
+vxfs_immed_follow_link(struct dentry *dp, int flags)
{
struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode);
- nd_set_link(np, vip->vii_immed.vi_immed);
+ nd_set_link(vip->vii_immed.vi_immed);
return NULL;
}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 15d326ec5943..9a4ca5dc62f1 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1400,17 +1400,17 @@ static void free_link(char *link)
free_page((unsigned long) link);
}
-static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *fuse_follow_link(struct dentry *dentry, int flags)
{
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
- nd_set_link(nd, read_link(dentry));
+ nd_set_link(read_link(dentry));
return NULL;
}
-static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
+static void fuse_put_link(struct dentry *dentry, void *c)
{
- free_link(nd_get_link(nd));
+ free_link(nd_get_link());
}
static int fuse_dir_open(struct inode *inode, struct file *file)
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 21086c7870f1..f0691c863956 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1541,14 +1541,14 @@ out:
/**
* gfs2_follow_link - Follow a symbolic link
* @dentry: The dentry of the link
- * @nd: Data that we pass to vfs_follow_link()
+ * @flags: Lookup flags
*
* This can handle symlinks of any size.
*
* Returns: 0 on success or error code
*/
-static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *gfs2_follow_link(struct dentry *dentry, int flags)
{
struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
struct gfs2_holder i_gh;
@@ -1557,13 +1557,13 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
char *buf;
int error;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
error = gfs2_glock_nq(&i_gh);
if (error) {
gfs2_holder_uninit(&i_gh);
- nd_set_link(nd, ERR_PTR(error));
+ nd_set_link(ERR_PTR(error));
return NULL;
}
@@ -1588,7 +1588,7 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
brelse(dibh);
out:
gfs2_glock_dq_uninit(&i_gh);
- nd_set_link(nd, buf);
+ nd_set_link(buf);
return NULL;
}
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 374d04909538..da224778b1be 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -882,11 +882,11 @@ static const struct inode_operations hostfs_dir_iops = {
.setattr = hostfs_setattr,
};
-static void *hostfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *hostfs_follow_link(struct dentry *dentry, int flags)
{
char *link;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
link = __getname();
@@ -907,13 +907,13 @@ static void *hostfs_follow_link(struct dentry *dentry, struct nameidata *nd)
link = ERR_PTR(-ENOMEM);
}
- nd_set_link(nd, link);
+ nd_set_link(link);
return NULL;
}
-static void hostfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+static void hostfs_put_link(struct dentry *dentry, void *cookie)
{
- char *s = nd_get_link(nd);
+ char *s = nd_get_link();
if (!IS_ERR(s))
__putname(s);
}
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 043ac9d77262..37d9a777f8e0 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -642,20 +642,19 @@ static int hppfs_readlink(struct dentry *dentry, char __user *buffer,
buflen);
}
-static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *hppfs_follow_link(struct dentry *dentry, int flags)
{
struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
- return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd);
+ return proc_dentry->d_inode->i_op->follow_link(proc_dentry, flags);
}
-static void hppfs_put_link(struct dentry *dentry, struct nameidata *nd,
- void *cookie)
+static void hppfs_put_link(struct dentry *dentry, void *cookie)
{
struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
if (proc_dentry->d_inode->i_op->put_link)
- proc_dentry->d_inode->i_op->put_link(proc_dentry, nd, cookie);
+ proc_dentry->d_inode->i_op->put_link(proc_dentry, cookie);
}
static const struct inode_operations hppfs_dir_iops = {
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index c7c77b0dfccd..c2bebe5c7c42 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -16,7 +16,7 @@
#include <linux/namei.h>
#include "nodelist.h"
-static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);
+static void *jffs2_follow_link(struct dentry *dentry, int flags);
const struct inode_operations jffs2_symlink_inode_operations =
{
@@ -29,7 +29,7 @@ const struct inode_operations jffs2_symlink_inode_operations =
.removexattr = jffs2_removexattr
};
-static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *jffs2_follow_link(struct dentry *dentry, int flags)
{
struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
char *p = (char *)f->target;
@@ -54,7 +54,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
jffs2_dbg(1, "%s(): target path is '%s'\n",
__func__, (char *)f->target);
- nd_set_link(nd, p);
+ nd_set_link(p);
/*
* We will unlock the f->sem mutex but VFS will use the f->target string. This is safe
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index 205b946d8e0d..1cfae27aa6a8 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -22,10 +22,10 @@
#include "jfs_inode.h"
#include "jfs_xattr.h"
-static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *jfs_follow_link(struct dentry *dentry, int flags)
{
char *s = JFS_IP(dentry->d_inode)->i_inline;
- nd_set_link(nd, s);
+ nd_set_link(s);
return NULL;
}
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index 8e5421f386c0..88694e0df282 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -112,12 +112,12 @@ static int kernfs_getlink(struct dentry *dentry, char *path)
return error;
}
-static void *kernfs_iop_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *kernfs_iop_follow_link(struct dentry *dentry, int flags)
{
int error = -ENOMEM;
unsigned long page;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
page = get_zeroed_page(GFP_KERNEL);
@@ -126,14 +126,13 @@ static void *kernfs_iop_follow_link(struct dentry *dentry, struct nameidata *nd)
if (error < 0)
free_page((unsigned long)page);
}
- nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
+ nd_set_link(error ? ERR_PTR(error) : (char *)page);
return NULL;
}
-static void kernfs_iop_put_link(struct dentry *dentry, struct nameidata *nd,
- void *cookie)
+static void kernfs_iop_put_link(struct dentry *dentry, void *cookie)
{
- char *page = nd_get_link(nd);
+ char *page = nd_get_link();
if (!IS_ERR(page))
free_page((unsigned long)page);
}
diff --git a/fs/libfs.c b/fs/libfs.c
index 0ab65122ee45..f437c8489998 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -1024,10 +1024,9 @@ int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
}
EXPORT_SYMBOL(noop_fsync);
-void kfree_put_link(struct dentry *dentry, struct nameidata *nd,
- void *cookie)
+void kfree_put_link(struct dentry *dentry, void *cookie)
{
- char *s = nd_get_link(nd);
+ char *s = nd_get_link();
if (!IS_ERR(s))
kfree(s);
}
diff --git a/fs/namei.c b/fs/namei.c
index eefa4a00501a..9a5d429f2a8a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -722,8 +722,10 @@ static inline void path_to_nameidata(const struct path *path,
* Helper to directly jump to a known parsed path from ->follow_link,
* caller must have taken a reference to path beforehand.
*/
-void nd_jump_link(struct nameidata *nd, struct path *path)
+void nd_jump_link(struct path *path)
{
+ struct nameidata *nd = current->nameidata;
+
path_put(&nd->path);
nd->path = *path;
@@ -731,14 +733,18 @@ void nd_jump_link(struct nameidata *nd, struct path *path)
nd->flags |= LOOKUP_JUMPED;
}
-void nd_set_link(struct nameidata *nd, char *path)
+void nd_set_link(char *path)
{
+ struct nameidata *nd = current->nameidata;
+
nd->saved_names[nd->depth] = path;
}
EXPORT_SYMBOL(nd_set_link);
-char *nd_get_link(struct nameidata *nd)
+char *nd_get_link(void)
{
+ struct nameidata *nd = current->nameidata;
+
return nd->saved_names[nd->depth];
}
EXPORT_SYMBOL(nd_get_link);
@@ -747,7 +753,7 @@ 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);
+ inode->i_op->put_link(link->dentry, cookie);
path_put(link);
}
@@ -887,20 +893,20 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
current->nameidata->total_link_count++;
touch_atime(link);
- nd_set_link(nd, NULL);
+ nd_set_link(NULL);
- error = security_inode_follow_link(link->dentry, nd);
+ error = security_inode_follow_link(link->dentry, nd->flags);
if (error)
goto out_put_nd_path;
nd->last_type = LAST_BIND;
- *p = dentry->d_inode->i_op->follow_link(dentry, nd);
+ *p = dentry->d_inode->i_op->follow_link(dentry, nd->flags);
error = PTR_ERR(*p);
if (IS_ERR(*p))
goto out_put_nd_path;
error = 0;
- s = nd_get_link(nd);
+ s = nd_get_link();
if (s) {
if (unlikely(IS_ERR(s))) {
path_put(&nd->path);
@@ -4458,13 +4464,13 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
int res;
nd.depth = 0;
- cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
+ cookie = dentry->d_inode->i_op->follow_link(dentry, nd.flags);
if (IS_ERR(cookie))
return PTR_ERR(cookie);
- res = readlink_copy(buffer, buflen, nd_get_link(&nd));
+ res = readlink_copy(buffer, buflen, nd_get_link());
if (dentry->d_inode->i_op->put_link)
- dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
+ dentry->d_inode->i_op->put_link(dentry, cookie);
set_nameidata(saved);
return res;
}
@@ -4497,17 +4503,17 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
}
EXPORT_SYMBOL(page_readlink);
-void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
+void *page_follow_link_light(struct dentry *dentry, int flags)
{
struct page *page = NULL;
- if (nd->flags & LOOKUP_RCU)
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
- nd_set_link(nd, page_getlink(dentry, &page));
+ nd_set_link(page_getlink(dentry, &page));
return page;
}
EXPORT_SYMBOL(page_follow_link_light);
-void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+void page_put_link(struct dentry *dentry, void *cookie)
{
struct page *page = cookie;
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index c9a2d3cc4619..43e43d2c8c5b 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -43,13 +43,13 @@ error:
return -EIO;
}
-static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *nfs_follow_link(struct dentry *dentry, int flags)
{
struct inode *inode = dentry->d_inode;
struct page *page;
void *err;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
if (err)
@@ -60,11 +60,11 @@ static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
err = page;
goto read_failed;
}
- nd_set_link(nd, kmap(page));
+ nd_set_link(kmap(page));
return page;
read_failed:
- nd_set_link(nd, err);
+ nd_set_link(err);
return NULL;
}
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index b3973c2fd190..a6a240ecf878 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -35,7 +35,6 @@
* ntfs_lookup - find the inode represented by a dentry in a directory inode
* @dir_ino: directory inode in which to look for the inode
* @dent: dentry representing the inode to look for
- * @nd: lookup nameidata
*
* In short, ntfs_lookup() looks for the inode represented by the dentry @dent
* in the directory inode @dir_ino and if found attaches the inode to the
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index db370d5d84c4..e8ef9f44af12 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -141,13 +141,13 @@ struct ovl_link_data {
void *cookie;
};
-static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ovl_follow_link(struct dentry *dentry, int flags)
{
void *ret;
struct dentry *realdentry;
struct inode *realinode;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
realdentry = ovl_dentry_real(dentry);
realinode = realdentry->d_inode;
@@ -155,7 +155,7 @@ static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
if (WARN_ON(!realinode->i_op->follow_link))
return ERR_PTR(-EPERM);
- ret = realinode->i_op->follow_link(realdentry, nd);
+ ret = realinode->i_op->follow_link(realdentry, flags);
if (IS_ERR(ret))
return ret;
@@ -164,7 +164,7 @@ static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL);
if (!data) {
- realinode->i_op->put_link(realdentry, nd, ret);
+ realinode->i_op->put_link(realdentry, ret);
return ERR_PTR(-ENOMEM);
}
data->realdentry = realdentry;
@@ -176,7 +176,7 @@ static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
}
}
-static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
+static void ovl_put_link(struct dentry *dentry, void *c)
{
struct inode *realinode;
struct ovl_link_data *data = c;
@@ -185,7 +185,7 @@ static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
return;
realinode = data->realdentry->d_inode;
- realinode->i_op->put_link(data->realdentry, nd, data->cookie);
+ realinode->i_op->put_link(data->realdentry, data->cookie);
kfree(data);
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6f5dbfe68516..7e6f95c0d58d 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1371,13 +1371,13 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
return -ENOENT;
}
-static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_pid_follow_link(struct dentry *dentry, int flags)
{
struct inode *inode = dentry->d_inode;
struct path path;
int error = -EACCES;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
/* Are we allowed to snoop on the tasks file descriptors? */
if (!proc_fd_access_allowed(inode))
@@ -1387,7 +1387,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
if (error)
goto out;
- nd_jump_link(nd, &path);
+ nd_jump_link(&path);
return NULL;
out:
return ERR_PTR(error);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 7697b6621cfd..f9980443427c 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -394,16 +394,16 @@ static const struct file_operations proc_reg_file_ops_no_compat = {
};
#endif
-static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_follow_link(struct dentry *dentry, int flags)
{
struct proc_dir_entry *pde = PDE(dentry->d_inode);
if (unlikely(!use_pde(pde)))
return ERR_PTR(-EINVAL);
- nd_set_link(nd, pde->data);
+ nd_set_link(pde->data);
return pde;
}
-static void proc_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+static void proc_put_link(struct dentry *dentry, void *p)
{
unuse_pde(p);
}
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index c89a51401bb5..46c7ab225e17 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -30,7 +30,7 @@ static const struct proc_ns_operations *ns_entries[] = {
&mntns_operations,
};
-static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_ns_follow_link(struct dentry *dentry, int flags)
{
struct inode *inode = dentry->d_inode;
const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
@@ -38,7 +38,7 @@ static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
struct path ns_path;
void *error = ERR_PTR(-EACCES);
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
task = get_proc_task(inode);
@@ -48,7 +48,7 @@ static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
if (ptrace_may_access(task, PTRACE_MODE_READ)) {
error = ns_get_path(&ns_path, task, ns_ops);
if (!error)
- nd_jump_link(nd, &ns_path);
+ nd_jump_link(&ns_path);
}
put_task_struct(task);
return error;
diff --git a/fs/proc/self.c b/fs/proc/self.c
index c094ea04e1bb..c56e282b84b8 100644
--- a/fs/proc/self.c
+++ b/fs/proc/self.c
@@ -19,13 +19,13 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
return readlink_copy(buffer, buflen, tmp);
}
-static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_self_follow_link(struct dentry *dentry, int flags)
{
struct pid_namespace *ns = dentry->d_sb->s_fs_info;
pid_t tgid;
char *name = ERR_PTR(-ENOENT);
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
tgid = task_tgid_nr_ns(current, ns);
@@ -37,7 +37,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
else
sprintf(name, "%d", tgid);
}
- nd_set_link(nd, name);
+ nd_set_link(name);
return NULL;
}
diff --git a/fs/proc/thread_self.c b/fs/proc/thread_self.c
index 5d3144d51018..78b35e18a042 100644
--- a/fs/proc/thread_self.c
+++ b/fs/proc/thread_self.c
@@ -20,14 +20,14 @@ static int proc_thread_self_readlink(struct dentry *dentry, char __user *buffer,
return readlink_copy(buffer, buflen, tmp);
}
-static void *proc_thread_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_thread_self_follow_link(struct dentry *dentry, int flags)
{
struct pid_namespace *ns = dentry->d_sb->s_fs_info;
pid_t tgid;
pid_t pid;
char *name = ERR_PTR(-ENOENT);
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
tgid = task_tgid_nr_ns(current, ns);
@@ -39,7 +39,7 @@ static void *proc_thread_self_follow_link(struct dentry *dentry, struct nameidat
else
sprintf(name, "%d/task/%d", tgid, pid);
}
- nd_set_link(nd, name);
+ nd_set_link(name);
return NULL;
}
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
index 00d2f8a43e4e..ad285577a928 100644
--- a/fs/sysv/symlink.c
+++ b/fs/sysv/symlink.c
@@ -8,9 +8,9 @@
#include "sysv.h"
#include <linux/namei.h>
-static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *sysv_follow_link(struct dentry *dentry, int flags)
{
- nd_set_link(nd, (char *)SYSV_I(dentry->d_inode)->i_data);
+ nd_set_link((char *)SYSV_I(dentry->d_inode)->i_data);
return NULL;
}
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index e627c0acf626..ccc83837f078 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1300,11 +1300,11 @@ static void ubifs_invalidatepage(struct page *page, unsigned int offset,
ClearPageChecked(page);
}
-static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ubifs_follow_link(struct dentry *dentry, int flags)
{
struct ubifs_inode *ui = ubifs_inode(dentry->d_inode);
- nd_set_link(nd, ui->data);
+ nd_set_link(ui->data);
return NULL;
}
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
index d283628b4778..29622d6beaa4 100644
--- a/fs/ufs/symlink.c
+++ b/fs/ufs/symlink.c
@@ -32,10 +32,10 @@
#include "ufs.h"
-static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *ufs_follow_link(struct dentry *dentry, int flags)
{
struct ufs_inode_info *p = UFS_I(dentry->d_inode);
- nd_set_link(nd, (char*)p->i_u1.i_symlink);
+ nd_set_link((char*)p->i_u1.i_symlink);
return NULL;
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 23cea798b777..8fd416ae935a 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -412,12 +412,12 @@ xfs_vn_rename(
STATIC void *
xfs_vn_follow_link(
struct dentry *dentry,
- struct nameidata *nd)
+ int flags)
{
char *link;
int error = -ENOMEM;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
if (!link)
@@ -427,13 +427,13 @@ xfs_vn_follow_link(
if (unlikely(error))
goto out_kfree;
- nd_set_link(nd, link);
+ nd_set_link(link);
return NULL;
out_kfree:
kfree(link);
out_err:
- nd_set_link(nd, ERR_PTR(error));
+ nd_set_link(ERR_PTR(error));
return NULL;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index eaef987ae3cf..b7d578d552bf 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -38,7 +38,6 @@ struct backing_dev_info;
struct export_operations;
struct hd_geometry;
struct iovec;
-struct nameidata;
struct kiocb;
struct kobject;
struct pipe_inode_info;
@@ -1574,12 +1573,12 @@ struct file_operations {
struct inode_operations {
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
- void * (*follow_link) (struct dentry *, struct nameidata *);
+ void * (*follow_link) (struct dentry *, int);
int (*permission) (struct inode *, int);
struct posix_acl * (*get_acl)(struct inode *, int);
int (*readlink) (struct dentry *, char __user *,int);
- void (*put_link) (struct dentry *, struct nameidata *, void *);
+ void (*put_link) (struct dentry *, void *);
int (*create) (struct inode *,struct dentry *, umode_t, bool);
int (*link) (struct dentry *,struct inode *,struct dentry *);
@@ -2167,7 +2166,6 @@ extern struct filename *getname_flags(const char __user *, int, int *);
extern struct filename *getname(const char __user *);
extern struct filename *getname_kernel(const char *);
extern void putname(struct filename *name);
-extern int nd_is_rcu(struct nameidata *nd);
enum {
FILE_CREATED = 1,
@@ -2650,13 +2648,13 @@ extern const struct file_operations generic_ro_fops;
extern int readlink_copy(char __user *, int, const char *);
extern int page_readlink(struct dentry *, char __user *, int);
-extern void *page_follow_link_light(struct dentry *, struct nameidata *);
-extern void page_put_link(struct dentry *, struct nameidata *, void *);
+extern void *page_follow_link_light(struct dentry *, int);
+extern void page_put_link(struct dentry *, void *);
extern int __page_symlink(struct inode *inode, const char *symname, int len,
int nofs);
extern int page_symlink(struct inode *inode, const char *symname, int len);
extern const struct inode_operations page_symlink_inode_operations;
-extern void kfree_put_link(struct dentry *, struct nameidata *, void *);
+extern void kfree_put_link(struct dentry *, void *);
extern int generic_readlink(struct dentry *, char __user *, int);
extern void generic_fillattr(struct inode *, struct kstat *);
int vfs_getattr_nosec(struct path *path, struct kstat *stat);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index c8990779f0c3..368eb3d721b8 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -7,7 +7,6 @@
#include <linux/path.h>
struct vfsmount;
-struct nameidata;
enum { MAX_NESTED_LINKS = 8 };
@@ -70,9 +69,9 @@ extern int follow_up(struct path *);
extern struct dentry *lock_rename(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);
-extern void nd_jump_link(struct nameidata *nd, struct path *path);
-extern void nd_set_link(struct nameidata *nd, char *path);
-extern char *nd_get_link(struct nameidata *nd);
+extern void nd_jump_link(struct path *path);
+extern void nd_set_link(char *path);
+extern char *nd_get_link(void);
static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
{
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b88b9eea169a..5d85ef2b64c3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1267,6 +1267,7 @@ union rcu_special {
short s;
};
struct rcu_node;
+struct nameidata;
enum perf_event_task_context {
perf_invalid_context = -1,
diff --git a/include/linux/security.h b/include/linux/security.h
index a1b7dbd127ff..587f7b0849b6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -43,7 +43,6 @@ struct file;
struct vfsmount;
struct path;
struct qstr;
-struct nameidata;
struct iattr;
struct fown_struct;
struct file_operations;
@@ -477,7 +476,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @inode_follow_link:
* Check permission to follow a symbolic link when looking up a pathname.
* @dentry contains the dentry structure for the link.
- * @nd contains the nameidata structure for the parent directory.
+ * @flags contains lookup flags
* Return 0 if permission is granted.
* @inode_permission:
* Check permission before accessing an inode. This hook is called by the
@@ -1553,7 +1552,7 @@ struct security_operations {
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
int (*inode_readlink) (struct dentry *dentry);
- int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
+ int (*inode_follow_link) (struct dentry *dentry, int flags);
int (*inode_permission) (struct inode *inode, int mask);
int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
@@ -1840,7 +1839,7 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags);
int security_inode_readlink(struct dentry *dentry);
-int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
+int security_inode_follow_link(struct dentry *dentry, int flags);
int security_inode_permission(struct inode *inode, int mask);
int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
@@ -2243,7 +2242,7 @@ static inline int security_inode_readlink(struct dentry *dentry)
}
static inline int security_inode_follow_link(struct dentry *dentry,
- struct nameidata *nd)
+ int flags)
{
return 0;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index fdf6ba18fce3..8f23e0f5e050 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2474,29 +2474,29 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
return 0;
}
-static void *shmem_follow_short_symlink(struct dentry *dentry, struct nameidata *nd)
+static void *shmem_follow_short_symlink(struct dentry *dentry, int flags)
{
- nd_set_link(nd, SHMEM_I(dentry->d_inode)->symlink);
+ nd_set_link(SHMEM_I(dentry->d_inode)->symlink);
return NULL;
}
-static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *shmem_follow_link(struct dentry *dentry, int flags)
{
struct page *page = NULL;
int error;
- if (nd_is_rcu(nd))
+ if (flags & LOOKUP_RCU)
return ERR_PTR(-ECHILD);
error = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
- nd_set_link(nd, error ? ERR_PTR(error) : kmap(page));
+ nd_set_link(error ? ERR_PTR(error) : kmap(page));
if (page)
unlock_page(page);
return page;
}
-static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+static void shmem_put_link(struct dentry *dentry, void *cookie)
{
- if (!IS_ERR(nd_get_link(nd))) {
+ if (!IS_ERR(nd_get_link())) {
struct page *page = cookie;
kunmap(page);
mark_page_accessed(page);
diff --git a/security/capability.c b/security/capability.c
index 070dd46f62f4..569e4253343c 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -210,7 +210,7 @@ static int cap_inode_readlink(struct dentry *dentry)
}
static int cap_inode_follow_link(struct dentry *dentry,
- struct nameidata *nameidata)
+ int flags)
{
return 0;
}
diff --git a/security/security.c b/security/security.c
index e81d5bbe7363..5798987b2a18 100644
--- a/security/security.c
+++ b/security/security.c
@@ -581,11 +581,11 @@ int security_inode_readlink(struct dentry *dentry)
return security_ops->inode_readlink(dentry);
}
-int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
+int security_inode_follow_link(struct dentry *dentry, int flags)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_follow_link(dentry, nd);
+ return security_ops->inode_follow_link(dentry, flags);
}
int security_inode_permission(struct inode *inode, int mask)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4d1a54190388..e3074e01f058 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2862,7 +2862,7 @@ static int selinux_inode_readlink(struct dentry *dentry)
return dentry_has_perm(cred, dentry, FILE__READ);
}
-static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
+static int selinux_inode_follow_link(struct dentry *dentry, int flags)
{
const struct cred *cred = current_cred();
next prev parent reply other threads:[~2015-03-16 4:43 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-16 4:43 [PATCH 00/13] Support follow_link in RCU-walk. - V2 NeilBrown
2015-03-16 4:43 ` [PATCH 02/13] VFS: make all ->follow_link handlers aware for LOOKUP_RCU NeilBrown
2015-03-16 4:43 ` [PATCH 01/13] VFS: replace {, total_}link_count in task_struct with pointer to nameidata NeilBrown
2015-03-16 19:46 ` Al Viro
2015-03-16 4:43 ` [PATCH 04/13] security/selinux: check for LOOKUP_RCU in _follow_link NeilBrown
2015-03-16 21:00 ` Al Viro
2015-03-20 4:39 ` NeilBrown
2015-03-20 5:12 ` Al Viro
2015-03-16 4:43 ` NeilBrown [this message]
2015-03-16 20:47 ` [PATCH 03/13] VFS: remove nameidata args from ->follow_link and ->put_link Al Viro
2015-03-16 4:43 ` [PATCH 09/13] VFS/namei: enable RCU-walk when following symlinks NeilBrown
2015-03-16 22:44 ` Al Viro
2015-03-16 4:43 ` [PATCH 13/13] NFS: support LOOKUP_RCU in nfs_follow_link NeilBrown
2015-03-16 4:43 ` [PATCH 06/13] VFS/namei: new flag to support RCU symlinks: LOOKUP_LINK_RCU NeilBrown
2015-03-16 22:33 ` Al Viro
2015-03-17 0:59 ` Al Viro
2015-03-16 4:43 ` [PATCH 08/13] VFS/namei: enhance follow_link to support RCU-walk NeilBrown
2015-03-16 4:43 ` [PATCH 12/13] XFS: allow follow_link to often succeed in RCU-walk NeilBrown
2015-03-16 22:37 ` Al Viro
2015-03-16 4:43 ` [PATCH 05/13] VFS/namei: use terminate_walk when symlink lookup fails NeilBrown
2015-03-16 4:43 ` [PATCH 11/13] xfs: use RCU to free 'struct xfs_mount' NeilBrown
2015-03-16 4:43 ` [PATCH 07/13] VFS/namei: abort RCU-walk on symlink if atime needs updating NeilBrown
2015-03-16 4:43 ` [PATCH 10/13] VFS/namei: handle LOOKUP_RCU in page_follow_link_light NeilBrown
2015-03-16 22:50 ` Al Viro
2015-03-19 22:38 ` NeilBrown
2015-03-19 23:46 ` Al Viro
2015-03-16 19:14 ` [PATCH 00/13] Support follow_link in RCU-walk. - V2 Al Viro
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=20150316044319.23648.2840.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.