]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge uncontroversial parts of branch 'readlink' of git://git.kernel.org/pub/scm...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 18 Dec 2016 03:16:12 +0000 (19:16 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 18 Dec 2016 03:16:12 +0000 (19:16 -0800)
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

46 files changed:
Documentation/filesystems/porting
Documentation/filesystems/vfs.txt
drivers/staging/lustre/lustre/llite/symlink.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/affs/symlink.c
fs/autofs4/symlink.c
fs/bad_inode.c
fs/btrfs/inode.c
fs/ceph/inode.c
fs/cifs/cifsfs.c
fs/coda/cnode.c
fs/configfs/symlink.c
fs/ecryptfs/inode.c
fs/ext2/symlink.c
fs/ext4/symlink.c
fs/f2fs/namei.c
fs/fuse/dir.c
fs/gfs2/inode.c
fs/hostfs/hostfs_kern.c
fs/jffs2/symlink.c
fs/jfs/symlink.c
fs/kernfs/symlink.c
fs/libfs.c
fs/minix/inode.c
fs/namei.c
fs/ncpfs/inode.c
fs/nfs/symlink.c
fs/nfsd/nfs4xdr.c
fs/nfsd/vfs.c
fs/nilfs2/namei.c
fs/ocfs2/symlink.c
fs/orangefs/symlink.c
fs/overlayfs/inode.c
fs/proc/inode.c
fs/proc/self.c
fs/proc/thread_self.c
fs/reiserfs/namei.c
fs/squashfs/symlink.c
fs/stat.c
fs/sysv/inode.c
fs/ubifs/file.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iops.c
include/linux/fs.h
mm/shmem.c

index bdd025ceb763b112a01ff18dc6d04d866e7240e7..95280079c0b3af0c217270e6838b723eb818cbcd 100644 (file)
@@ -596,3 +596,7 @@ in your dentry operations instead.
 [mandatory]
        ->rename() has an added flags argument.  Any flags not handled by the
         filesystem should result in EINVAL being returned.
+--
+[recommended]
+       ->readlink is optional for symlinks.  Don't set, unless filesystem needs
+       to fake something for readlink(2).
index 3893f4d44cd46e0c7b9579fad48638a0fe359960..b968084eeac14bbc4f8f51dbf7fc3484f61da496 100644 (file)
@@ -451,9 +451,6 @@ otherwise noted.
        exist; this is checked by the VFS.  Unlike plain rename,
        source and target may be of different type.
 
-  readlink: called by the readlink(2) system call. Only required if
-       you want to support reading symbolic links
-
   get_link: called by the VFS to follow a symbolic link to the
        inode it points to.  Only required if you want to support
        symbolic links.  This method returns the symlink body
@@ -468,6 +465,12 @@ otherwise noted.
        argument.  If request can't be handled without leaving RCU mode,
        have it return ERR_PTR(-ECHILD).
 
+  readlink: this is now just an override for use by readlink(2) for the
+       cases when ->get_link uses nd_jump_link() or object is not in
+       fact a symlink.  Normally filesystems should only implement
+       ->get_link for symlinks and readlink(2) will automatically use
+       that.
+
   permission: called by the VFS to check for access rights on a POSIX-like
        filesystem.
 
index 82c7c48aa619c7090127025664f58eaed769cc5a..cd77b55d3895462e144071651f91ddce2185ef8e 100644 (file)
@@ -149,7 +149,6 @@ static const char *ll_get_link(struct dentry *dentry,
 }
 
 const struct inode_operations ll_fast_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .setattr        = ll_setattr,
        .get_link       = ll_get_link,
        .getattr        = ll_getattr,
index 30ca770c5e0b854d51abeb5193882a12503c8f8d..f4f4450119e42f74c1bc3269cc07ee798f9bc49b 100644 (file)
@@ -1464,7 +1464,6 @@ static const struct inode_operations v9fs_file_inode_operations = {
 };
 
 static const struct inode_operations v9fs_symlink_inode_operations = {
-       .readlink = generic_readlink,
        .get_link = v9fs_vfs_get_link,
        .getattr = v9fs_vfs_getattr,
        .setattr = v9fs_vfs_setattr,
index afaa4b6de8018f37f6bbc2c8595c0af01d14fdef..5999bd050678cd333ffa0f7e6e88f6a575e5a885 100644 (file)
@@ -979,7 +979,6 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {
 };
 
 const struct inode_operations v9fs_symlink_inode_operations_dotl = {
-       .readlink = generic_readlink,
        .get_link = v9fs_vfs_get_link_dotl,
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
index 69b03dbb792f7a080abc70f5d45ff4bf50d458b9..ae622cdce142264af53127a8d94730c64a0d74d2 100644 (file)
@@ -70,7 +70,6 @@ const struct address_space_operations affs_symlink_aops = {
 };
 
 const struct inode_operations affs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = affs_notify_change,
 };
index 99aab00dc21763505adbe5a1d8d992a83e131aaf..ab0b4285a202c77ded6ab0c36d75621db281d1bc 100644 (file)
@@ -25,6 +25,5 @@ static const char *autofs4_get_link(struct dentry *dentry,
 }
 
 const struct inode_operations autofs4_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = autofs4_get_link
 };
index 8712062275b83fb7f2995106c80b5e7e39292c21..5f685c8192981864c3e273acce95dacc40494367 100644 (file)
@@ -106,6 +106,50 @@ static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
        return -EIO;
 }
 
+static const char *bad_inode_get_link(struct dentry *dentry,
+                                     struct inode *inode,
+                                     struct delayed_call *done)
+{
+       return ERR_PTR(-EIO);
+}
+
+static struct posix_acl *bad_inode_get_acl(struct inode *inode, int type)
+{
+       return ERR_PTR(-EIO);
+}
+
+static int bad_inode_fiemap(struct inode *inode,
+                           struct fiemap_extent_info *fieinfo, u64 start,
+                           u64 len)
+{
+       return -EIO;
+}
+
+static int bad_inode_update_time(struct inode *inode, struct timespec *time,
+                                int flags)
+{
+       return -EIO;
+}
+
+static int bad_inode_atomic_open(struct inode *inode, struct dentry *dentry,
+                                struct file *file, unsigned int open_flag,
+                                umode_t create_mode, int *opened)
+{
+       return -EIO;
+}
+
+static int bad_inode_tmpfile(struct inode *inode, struct dentry *dentry,
+                            umode_t mode)
+{
+       return -EIO;
+}
+
+static int bad_inode_set_acl(struct inode *inode, struct posix_acl *acl,
+                            int type)
+{
+       return -EIO;
+}
+
 static const struct inode_operations bad_inode_ops =
 {
        .create         = bad_inode_create,
@@ -118,14 +162,17 @@ static const struct inode_operations bad_inode_ops =
        .mknod          = bad_inode_mknod,
        .rename         = bad_inode_rename2,
        .readlink       = bad_inode_readlink,
-       /* follow_link must be no-op, otherwise unmounting this inode
-          won't work */
-       /* put_link returns void */
-       /* truncate returns void */
        .permission     = bad_inode_permission,
        .getattr        = bad_inode_getattr,
        .setattr        = bad_inode_setattr,
        .listxattr      = bad_inode_listxattr,
+       .get_link       = bad_inode_get_link,
+       .get_acl        = bad_inode_get_acl,
+       .fiemap         = bad_inode_fiemap,
+       .update_time    = bad_inode_update_time,
+       .atomic_open    = bad_inode_atomic_open,
+       .tmpfile        = bad_inode_tmpfile,
+       .set_acl        = bad_inode_set_acl,
 };
 
 
index c3b6ffa8e39d272981c0f3fe8134e97a93f0b360..f2b281ad7af6b9db26b48c6d4f072a850c19d58a 100644 (file)
@@ -10653,7 +10653,6 @@ static const struct inode_operations btrfs_special_inode_operations = {
        .update_time    = btrfs_update_time,
 };
 static const struct inode_operations btrfs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
index 284f0d807151e4d28655e0087fa727164b701e64..398e5328b30952410cc503e7e4d20918d3bdc671 100644 (file)
@@ -1869,7 +1869,6 @@ retry:
  * symlinks
  */
 static const struct inode_operations ceph_symlink_iops = {
-       .readlink = generic_readlink,
        .get_link = simple_get_link,
        .setattr = ceph_setattr,
        .getattr = ceph_getattr,
index 15261ba464c5023f82014751fee8efaf09abec5f..e6efb9a8859892df6ded9d58334815439828d2ec 100644 (file)
@@ -914,7 +914,6 @@ const struct inode_operations cifs_file_inode_ops = {
 };
 
 const struct inode_operations cifs_symlink_inode_ops = {
-       .readlink = generic_readlink,
        .get_link = cifs_get_link,
        .permission = cifs_permission,
        .listxattr = cifs_listxattr,
index 1bfb7ba4e85e3ecc05000a3543a01917a7ed40a4..f13e09057c6b8297ce8f8572e880b953c4e4e864 100644 (file)
@@ -17,7 +17,6 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
 }
 
 static const struct inode_operations coda_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = coda_setattr,
 };
index db6d692896088ebc9745d9c05c85309280885b38..a6ab012a2c6acf9815bb8d4d1e29fb4568084b08 100644 (file)
@@ -305,7 +305,6 @@ static const char *configfs_get_link(struct dentry *dentry,
 
 const struct inode_operations configfs_symlink_inode_operations = {
        .get_link = configfs_get_link,
-       .readlink = generic_readlink,
        .setattr = configfs_setattr,
 };
 
index cf390dceddd29a27708f92f41c727c1c3c99c812..e7413f82d27bf392be10998aa9c8b2ef598a354e 100644 (file)
@@ -631,28 +631,23 @@ out_lock:
 
 static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz)
 {
+       DEFINE_DELAYED_CALL(done);
        struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       char *lower_buf;
+       const char *link;
        char *buf;
-       mm_segment_t old_fs;
        int rc;
 
-       lower_buf = kmalloc(PATH_MAX, GFP_KERNEL);
-       if (!lower_buf)
-               return ERR_PTR(-ENOMEM);
-       old_fs = get_fs();
-       set_fs(get_ds());
-       rc = d_inode(lower_dentry)->i_op->readlink(lower_dentry,
-                                                  (char __user *)lower_buf,
-                                                  PATH_MAX);
-       set_fs(old_fs);
-       if (rc < 0)
-               goto out;
+       link = vfs_get_link(lower_dentry, &done);
+       if (IS_ERR(link))
+               return ERR_CAST(link);
+
        rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb,
-                                                 lower_buf, rc);
-out:
-       kfree(lower_buf);
-       return rc ? ERR_PTR(rc) : buf;
+                                                 link, strlen(link));
+       do_delayed_call(&done);
+       if (rc)
+               return ERR_PTR(rc);
+
+       return buf;
 }
 
 static const char *ecryptfs_get_link(struct dentry *dentry,
@@ -1089,7 +1084,6 @@ out:
 }
 
 const struct inode_operations ecryptfs_symlink_iops = {
-       .readlink = generic_readlink,
        .get_link = ecryptfs_get_link,
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
index 8437b191bf5de334a5c8908832c0dec0ac1f0fc7..eeffb0138a1744a32466308ed8f39c9151d0bd33 100644 (file)
@@ -21,7 +21,6 @@
 #include "xattr.h"
 
 const struct inode_operations ext2_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = ext2_setattr,
 #ifdef CONFIG_EXT2_FS_XATTR
@@ -30,7 +29,6 @@ const struct inode_operations ext2_symlink_inode_operations = {
 };
  
 const struct inode_operations ext2_fast_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = simple_get_link,
        .setattr        = ext2_setattr,
 #ifdef CONFIG_EXT2_FS_XATTR
index 557b3b0d668c3f12d458a194d819ecb1da407645..73b184d161fc98dc6c870758243b1a03932cb85f 100644 (file)
@@ -83,21 +83,18 @@ errout:
 }
 
 const struct inode_operations ext4_encrypted_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = ext4_encrypted_get_link,
        .setattr        = ext4_setattr,
        .listxattr      = ext4_listxattr,
 };
 
 const struct inode_operations ext4_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = ext4_setattr,
        .listxattr      = ext4_listxattr,
 };
 
 const struct inode_operations ext4_fast_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = simple_get_link,
        .setattr        = ext4_setattr,
        .listxattr      = ext4_listxattr,
index db33b5631dc81d16a88efd4a4f4de3f809be65b9..56c19b0610a899a6351f72a16e26b788f956e3d5 100644 (file)
@@ -1075,7 +1075,6 @@ errout:
 }
 
 const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = f2fs_encrypted_get_link,
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
@@ -1105,7 +1104,6 @@ const struct inode_operations f2fs_dir_inode_operations = {
 };
 
 const struct inode_operations f2fs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = f2fs_get_link,
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
index 096f79997f75adf9603c4c6367635588535a8ae3..1f7c732f32b07f1bab9e4961f16cb52ee9f09f70 100644 (file)
@@ -1831,7 +1831,6 @@ static const struct inode_operations fuse_common_inode_operations = {
 static const struct inode_operations fuse_symlink_inode_operations = {
        .setattr        = fuse_setattr,
        .get_link       = fuse_get_link,
-       .readlink       = generic_readlink,
        .getattr        = fuse_getattr,
        .listxattr      = fuse_listxattr,
 };
index fe3f84995c486f139651518e3dd58cc6c447d899..6cd9f84967b8a8b89a446c4a6232c65627233be2 100644 (file)
@@ -2067,7 +2067,6 @@ const struct inode_operations gfs2_dir_iops = {
 };
 
 const struct inode_operations gfs2_symlink_iops = {
-       .readlink = generic_readlink,
        .get_link = gfs2_get_link,
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
index 23e15ea53e4582fa43cd703ae715de95313c4a25..e61261a7417e57cc49a784c5a54b8a15f92bd352 100644 (file)
@@ -920,7 +920,6 @@ static const char *hostfs_get_link(struct dentry *dentry,
 }
 
 static const struct inode_operations hostfs_link_iops = {
-       .readlink       = generic_readlink,
        .get_link       = hostfs_get_link,
 };
 
index 8f3f0855fcd230a28563105108c5e0e19cf55b72..d2fa138a868ce2550724e8565881660be4b392e0 100644 (file)
@@ -13,7 +13,6 @@
 
 const struct inode_operations jffs2_symlink_inode_operations =
 {
-       .readlink =     generic_readlink,
        .get_link =     simple_get_link,
        .setattr =      jffs2_setattr,
        .listxattr =    jffs2_listxattr,
index c82404fee6cd3b391de27297996d5bd6246f9960..38320607993e2f5c093b26dcfeb372022aa90dff 100644 (file)
 #include "jfs_xattr.h"
 
 const struct inode_operations jfs_fast_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = simple_get_link,
        .setattr        = jfs_setattr,
        .listxattr      = jfs_listxattr,
 };
 
 const struct inode_operations jfs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = jfs_setattr,
        .listxattr      = jfs_listxattr,
index 9b43ca02b7ab2b28c5a17ea36856b3fa4237a55a..1684af4a8b9b4eaf752dfffc063b3a2cc622d472 100644 (file)
@@ -135,7 +135,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
 
 const struct inode_operations kernfs_symlink_iops = {
        .listxattr      = kernfs_iop_listxattr,
-       .readlink       = generic_readlink,
        .get_link       = kernfs_iop_get_link,
        .setattr        = kernfs_iop_setattr,
        .getattr        = kernfs_iop_getattr,
index 76048705d9220d3234f36ad151dd93d81ef839f6..6637aa60c1dac94cea638cc58b1b700bbb25b9c9 100644 (file)
@@ -1131,7 +1131,6 @@ EXPORT_SYMBOL(simple_get_link);
 
 const struct inode_operations simple_symlink_inode_operations = {
        .get_link = simple_get_link,
-       .readlink = generic_readlink
 };
 EXPORT_SYMBOL(simple_symlink_inode_operations);
 
index f975d667c53900c08526e4774b8f74a96e822dbb..e7d9bf86d97595d1d1fe29bcca7ae5bdeefa0b6a 100644 (file)
@@ -434,7 +434,6 @@ static const struct address_space_operations minix_aops = {
 };
 
 static const struct inode_operations minix_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .getattr        = minix_getattr,
 };
index 1c372debcbbe62c57d922448b86ee967e18d6584..d9fc7617b9e48a9225f5a97a752ed3bd5db7b869 100644 (file)
@@ -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);
index f6cf4c7e92b1b8c3cf7e7846aa4c968a24829b03..ba611bf1aff3bcfb3837257a86610431bf425d26 100644 (file)
@@ -243,7 +243,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 static const struct inode_operations ncp_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = ncp_notify_change,
 };
index 4fe3eead3868ebe418432b4593c10464188fb4ed..5a1d0ded897989c0243df2c07cd9108a38bbc594 100644 (file)
@@ -77,7 +77,6 @@ static const char *nfs_get_link(struct dentry *dentry,
  * symlinks can't do much...
  */
 const struct inode_operations nfs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = nfs_get_link,
        .getattr        = nfs_getattr,
        .setattr        = nfs_setattr,
index 79edde4577b29457767a3cb85c1714350184513d..7ecf16be4a444ec250678e89ad210c7f19cbbc18 100644 (file)
@@ -3605,10 +3605,10 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
        if (!p)
                return nfserr_resource;
        /*
-        * XXX: By default, the ->readlink() VFS op will truncate symlinks
-        * if they would overflow the buffer.  Is this kosher in NFSv4?  If
-        * not, one easy fix is: if ->readlink() precisely fills the buffer,
-        * assume that truncation occurred, and return NFS4ERR_RESOURCE.
+        * XXX: By default, vfs_readlink() will truncate symlinks if they
+        * would overflow the buffer.  Is this kosher in NFSv4?  If not, one
+        * easy fix is: if vfs_readlink() precisely fills the buffer, assume
+        * that truncation occurred, and return NFS4ERR_RESOURCE.
         */
        nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp,
                                                (char *)p, &maxcount);
index 357e844aee8440c7969dee0359cee8ff71fc223c..7a21abe7caf7623e8354dc56a1057d9469e22d39 100644 (file)
@@ -1450,7 +1450,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
 __be32
 nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
 {
-       struct inode    *inode;
        mm_segment_t    oldfs;
        __be32          err;
        int             host_err;
@@ -1462,10 +1461,9 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
 
        path.mnt = fhp->fh_export->ex_path.mnt;
        path.dentry = fhp->fh_dentry;
-       inode = d_inode(path.dentry);
 
        err = nfserr_inval;
-       if (!inode->i_op->readlink)
+       if (!d_is_symlink(path.dentry))
                goto out;
 
        touch_atime(&path);
@@ -1474,7 +1472,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
         */
 
        oldfs = get_fs(); set_fs(KERNEL_DS);
-       host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp);
+       host_err = vfs_readlink(path.dentry, (char __user *)buf, *lenp);
        set_fs(oldfs);
 
        if (host_err < 0)
index 2b71c60fe982a1bafdca0848193acc33287b56c5..515d13c196daf81f69dc0b5501b4b9780c8d2743 100644 (file)
@@ -568,7 +568,6 @@ const struct inode_operations nilfs_special_inode_operations = {
 };
 
 const struct inode_operations nilfs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .permission     = nilfs_permission,
 };
index 6ad8eecefe21ff26fa43ca92fbe16ee02b90c323..94cfacc9bad70ce0745c14d982a840453aaf6e44 100644 (file)
@@ -87,7 +87,6 @@ const struct address_space_operations ocfs2_fast_symlink_aops = {
 };
 
 const struct inode_operations ocfs2_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .getattr        = ocfs2_getattr,
        .setattr        = ocfs2_setattr,
index 10b0b06e075ef0295a39f9833360a936a3a221bf..02b1bbdbcc42feef7e88af3b6cf5bdb4ff2dba66 100644 (file)
@@ -9,7 +9,6 @@
 #include "orangefs-bufmap.h"
 
 const struct inode_operations orangefs_symlink_inode_operations = {
-       .readlink = generic_readlink,
        .get_link = simple_get_link,
        .setattr = orangefs_setattr,
        .getattr = orangefs_getattr,
index 1ab8b0dbc23788f10c61e0e734e10f42cd717545..08643ac44a0278ed04be96d6df267e3b13821692 100644 (file)
@@ -296,7 +296,6 @@ static const struct inode_operations ovl_file_inode_operations = {
 static const struct inode_operations ovl_symlink_inode_operations = {
        .setattr        = ovl_setattr,
        .get_link       = ovl_get_link,
-       .readlink       = generic_readlink,
        .getattr        = ovl_getattr,
        .listxattr      = ovl_listxattr,
        .update_time    = ovl_update_time,
index 783bc19644d18d2b5b64de10f10169a6e957cc28..873300164dc6b1413da81a6e4d6d56d2a4e2843d 100644 (file)
@@ -425,7 +425,6 @@ static const char *proc_get_link(struct dentry *dentry,
 }
 
 const struct inode_operations proc_link_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = proc_get_link,
 };
 
index 40245954c4501e838b15a00b68b7105ab9ab759a..39857f6db5cfd85c5ae4dff31b85f2739d783648 100644 (file)
@@ -6,18 +6,6 @@
 /*
  * /proc/self:
  */
-static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
-                             int buflen)
-{
-       struct pid_namespace *ns = dentry->d_sb->s_fs_info;
-       pid_t tgid = task_tgid_nr_ns(current, ns);
-       char tmp[PROC_NUMBUF];
-       if (!tgid)
-               return -ENOENT;
-       sprintf(tmp, "%d", tgid);
-       return readlink_copy(buffer, buflen, tmp);
-}
-
 static const char *proc_self_get_link(struct dentry *dentry,
                                      struct inode *inode,
                                      struct delayed_call *done)
@@ -38,7 +26,6 @@ static const char *proc_self_get_link(struct dentry *dentry,
 }
 
 static const struct inode_operations proc_self_inode_operations = {
-       .readlink       = proc_self_readlink,
        .get_link       = proc_self_get_link,
 };
 
index 595b90a9766c98c93014418486397f0e508873f1..20614b62a9b793cd357b76f1eba97ab9218f89e7 100644 (file)
@@ -6,19 +6,6 @@
 /*
  * /proc/thread_self:
  */
-static int proc_thread_self_readlink(struct dentry *dentry, char __user *buffer,
-                             int buflen)
-{
-       struct pid_namespace *ns = dentry->d_sb->s_fs_info;
-       pid_t tgid = task_tgid_nr_ns(current, ns);
-       pid_t pid = task_pid_nr_ns(current, ns);
-       char tmp[PROC_NUMBUF + 6 + PROC_NUMBUF];
-       if (!pid)
-               return -ENOENT;
-       sprintf(tmp, "%d/task/%d", tgid, pid);
-       return readlink_copy(buffer, buflen, tmp);
-}
-
 static const char *proc_thread_self_get_link(struct dentry *dentry,
                                             struct inode *inode,
                                             struct delayed_call *done)
@@ -40,7 +27,6 @@ static const char *proc_thread_self_get_link(struct dentry *dentry,
 }
 
 static const struct inode_operations proc_thread_self_inode_operations = {
-       .readlink       = proc_thread_self_readlink,
        .get_link       = proc_thread_self_get_link,
 };
 
index e6a2b406af367071920a332bf6dc62a5d72e8fcf..bd39a998843da62db4b634800813c3de29d969c7 100644 (file)
@@ -1665,7 +1665,6 @@ const struct inode_operations reiserfs_dir_inode_operations = {
  * stuff added
  */
 const struct inode_operations reiserfs_symlink_inode_operations = {
-       .readlink = generic_readlink,
        .get_link       = page_get_link,
        .setattr = reiserfs_setattr,
        .listxattr = reiserfs_listxattr,
index 79b9c31a0c8ffdd223b83f9c243918e64ef3ed59..befeba0fa70af27b9b239c38d6e9592604cad071 100644 (file)
@@ -118,7 +118,6 @@ const struct address_space_operations squashfs_symlink_aops = {
 };
 
 const struct inode_operations squashfs_symlink_inode_ops = {
-       .readlink = generic_readlink,
        .get_link = page_get_link,
        .listxattr = squashfs_listxattr
 };
index bc045c7994e1bf6fe98af3a475afaeb4ecd8f16a..0b210c3ead5c3d60b9fe9035a56d3c79519da563 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -329,12 +329,14 @@ retry:
                struct inode *inode = d_backing_inode(path.dentry);
 
                error = empty ? -ENOENT : -EINVAL;
-               if (inode->i_op->readlink) {
+               /*
+                * AFS mountpoints allow readlink(2) but are not symlinks
+                */
+               if (d_is_symlink(path.dentry) || inode->i_op->readlink) {
                        error = security_inode_readlink(path.dentry);
                        if (!error) {
                                touch_atime(&path);
-                               error = inode->i_op->readlink(path.dentry,
-                                                             buf, bufsiz);
+                               error = vfs_readlink(path.dentry, buf, bufsiz);
                        }
                }
                path_put(&path);
index d62c423a5a2d8723807d2bb5f65b227042dcf724..858fb72f9e0fa76a7b2214bb518537733bc1dea4 100644 (file)
@@ -145,7 +145,6 @@ static inline void write3byte(struct sysv_sb_info *sbi,
 }
 
 static const struct inode_operations sysv_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .getattr        = sysv_getattr,
 };
index aa0625f4f6427677f38f8c5d6e177f58572ad05d..b0d783774c963c97f32df7649feeb8fb7e4e3e4f 100644 (file)
@@ -1733,7 +1733,6 @@ const struct inode_operations ubifs_file_inode_operations = {
 };
 
 const struct inode_operations ubifs_symlink_inode_operations = {
-       .readlink    = generic_readlink,
        .get_link    = ubifs_get_link,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
index fc563b82aea65a666aecd67f349046c06d68147b..c67cfb451fd3a74dad2d365e372b4e5fa296eecd 100644 (file)
@@ -287,7 +287,7 @@ xfs_readlink_by_handle(
                return PTR_ERR(dentry);
 
        /* Restrict this handle operation to symlinks only. */
-       if (!d_inode(dentry)->i_op->readlink) {
+       if (!d_is_symlink(dentry)) {
                error = -EINVAL;
                goto out_dput;
        }
@@ -297,7 +297,7 @@ xfs_readlink_by_handle(
                goto out_dput;
        }
 
-       error = d_inode(dentry)->i_op->readlink(dentry, hreq->ohandle, olen);
+       error = vfs_readlink(dentry, hreq->ohandle, olen);
 
  out_dput:
        dput(dentry);
index b930be0b1596592de8fc71aecbb25c033c513f17..308bebb6dfd266f85ae225ef0c235128bb7b36ba 100644 (file)
@@ -1120,7 +1120,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
 };
 
 static const struct inode_operations xfs_symlink_inode_operations = {
-       .readlink               = generic_readlink,
        .get_link               = xfs_vn_get_link,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
@@ -1129,7 +1128,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
 };
 
 static const struct inode_operations xfs_inline_symlink_inode_operations = {
-       .readlink               = generic_readlink,
        .get_link               = xfs_vn_get_link_inline,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
index 358789650607b398e3e03078c171dc84a4dfd460..e6e4146bf9ae5ee9def7da466f369127895713df 100644 (file)
@@ -543,6 +543,7 @@ is_uncached_acl(struct posix_acl *acl)
 #define IOP_LOOKUP     0x0002
 #define IOP_NOFOLLOW   0x0004
 #define IOP_XATTR      0x0008
+#define IOP_DEFAULT_READLINK   0x0010
 
 /*
  * Keep mostly read-only and often accessed (especially for
@@ -2867,7 +2868,6 @@ extern int __page_symlink(struct inode *inode, const char *symname, int len,
 extern int page_symlink(struct inode *inode, const char *symname, int len);
 extern const struct inode_operations page_symlink_inode_operations;
 extern void kfree_link(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);
 extern int vfs_getattr(struct path *, struct kstat *);
@@ -2888,6 +2888,7 @@ extern int vfs_lstat(const char __user *, struct kstat *);
 extern int vfs_fstat(unsigned int, struct kstat *);
 extern int vfs_fstatat(int , const char __user *, struct kstat *, int);
 extern const char *vfs_get_link(struct dentry *, struct delayed_call *);
+extern int vfs_readlink(struct dentry *, char __user *, int);
 
 extern int __generic_block_fiemap(struct inode *inode,
                                  struct fiemap_extent_info *fieinfo,
index 54287d443806243fba2efa67e6b5ec71f3a4f56d..b1b20dc63265029e0f5e77221d8a2d851032992f 100644 (file)
@@ -3212,7 +3212,6 @@ static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
 #endif /* CONFIG_TMPFS_XATTR */
 
 static const struct inode_operations shmem_short_symlink_operations = {
-       .readlink       = generic_readlink,
        .get_link       = simple_get_link,
 #ifdef CONFIG_TMPFS_XATTR
        .listxattr      = shmem_listxattr,
@@ -3220,7 +3219,6 @@ static const struct inode_operations shmem_short_symlink_operations = {
 };
 
 static const struct inode_operations shmem_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = shmem_get_link,
 #ifdef CONFIG_TMPFS_XATTR
        .listxattr      = shmem_listxattr,