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@xxxxxxx> --- 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(); -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html