summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 12a4159de72a..b87465d67c60 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4682,10 +4682,19 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
{
struct inode *inode = d_inode(dentry);
- if (!inode->i_op->readlink)
- return -EINVAL;
+ 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 inode->i_op->readlink(dentry, buffer, buflen);
+ return generic_readlink(dentry, buffer, buflen);
}
EXPORT_SYMBOL(vfs_readlink);