diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-17 19:16:12 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-17 19:16:12 -0800 |
commit | 231753ef780012eb6f3922c3dfc0a7186baa33c2 (patch) | |
tree | c580186402ac9c5d7392ba4516dd3c88588807ba /fs/namei.c | |
parent | 0110c350c86d511be2130cb2a30dcbb76c4af750 (diff) | |
parent | d16744ec8ad011793144bb932ce822cc0c1733cb (diff) | |
download | linux-stable-231753ef780012eb6f3922c3dfc0a7186baa33c2.tar.gz linux-stable-231753ef780012eb6f3922c3dfc0a7186baa33c2.tar.bz2 linux-stable-231753ef780012eb6f3922c3dfc0a7186baa33c2.zip |
Merge uncontroversial parts of branch 'readlink' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull partial readlink cleanups from Miklos Szeredi.
This is the uncontroversial part of the readlink cleanup patch-set that
simplifies the default readlink handling.
Miklos and Al are still discussing the rest of the series.
* git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
vfs: make generic_readlink() static
vfs: remove ".readlink = generic_readlink" assignments
vfs: default to generic_readlink()
vfs: replace calling i_op->readlink with vfs_readlink()
proc/self: use generic_readlink
ecryptfs: use vfs_get_link()
bad_inode: add missing i_op initializers
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/fs/namei.c b/fs/namei.c index 1c372debcbbe..d9fc7617b9e4 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4606,7 +4606,8 @@ out: * have ->get_link() not calling nd_jump_link(). Using (or not using) it * for any given inode is up to filesystem. */ -int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) +static int generic_readlink(struct dentry *dentry, char __user *buffer, + int buflen) { DEFINE_DELAYED_CALL(done); struct inode *inode = d_inode(dentry); @@ -4622,7 +4623,36 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) do_delayed_call(&done); return res; } -EXPORT_SYMBOL(generic_readlink); + +/** + * vfs_readlink - copy symlink body into userspace buffer + * @dentry: dentry on which to get symbolic link + * @buffer: user memory pointer + * @buflen: size of buffer + * + * Does not touch atime. That's up to the caller if necessary + * + * Does not call security hook. + */ +int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) +{ + struct inode *inode = d_inode(dentry); + + if (unlikely(!(inode->i_opflags & IOP_DEFAULT_READLINK))) { + if (unlikely(inode->i_op->readlink)) + return inode->i_op->readlink(dentry, buffer, buflen); + + if (!d_is_symlink(dentry)) + return -EINVAL; + + spin_lock(&inode->i_lock); + inode->i_opflags |= IOP_DEFAULT_READLINK; + spin_unlock(&inode->i_lock); + } + + return generic_readlink(dentry, buffer, buflen); +} +EXPORT_SYMBOL(vfs_readlink); /** * vfs_get_link - get symlink body @@ -4739,7 +4769,6 @@ int page_symlink(struct inode *inode, const char *symname, int len) EXPORT_SYMBOL(page_symlink); const struct inode_operations page_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, }; EXPORT_SYMBOL(page_symlink_inode_operations); |