[XFS] stop using uio in the readlink code
authorChristoph Hellwig <hch@infradead.org>
Tue, 28 Aug 2007 03:59:03 +0000 (13:59 +1000)
committerTim Shimmin <tes@chook.melbourne.sgi.com>
Mon, 15 Oct 2007 06:50:13 +0000 (16:50 +1000)
Simplify the readlink code to get rid of the last user of uio.

SGI-PV: 968563
SGI-Modid: xfs-linux-melb:xfs-kern:29479a

Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/xfs_vnodeops.c

index 5917808abbd6b0f9b1e98f3db6cc1c71c8ed0f67..47cfde6cfae2fc41adc3415143bcd6643a7b23a6 100644 (file)
@@ -349,19 +349,44 @@ xfs_open_by_handle(
        return new_fd;
 }
 
+/*
+ * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's
+ * unused first argument.
+ */
+STATIC int
+do_readlink(
+       char __user             *buffer,
+       int                     buflen,
+       const char              *link)
+{
+        int len;
+
+       len = PTR_ERR(link);
+       if (IS_ERR(link))
+               goto out;
+
+       len = strlen(link);
+       if (len > (unsigned) buflen)
+               len = buflen;
+       if (copy_to_user(buffer, link, len))
+               len = -EFAULT;
+ out:
+       return len;
+}
+
+
 STATIC int
 xfs_readlink_by_handle(
        xfs_mount_t             *mp,
        void                    __user *arg,
        struct inode            *parinode)
 {
-       int                     error;
-       struct iovec            aiov;
-       struct uio              auio;
        struct inode            *inode;
        xfs_fsop_handlereq_t    hreq;
        bhv_vnode_t             *vp;
        __u32                   olen;
+       void                    *link;
+       int                     error;
 
        if (!capable(CAP_SYS_ADMIN))
                return -XFS_ERROR(EPERM);
@@ -374,29 +399,31 @@ xfs_readlink_by_handle(
 
        /* Restrict this handle operation to symlinks only. */
        if (!S_ISLNK(inode->i_mode)) {
-               VN_RELE(vp);
-               return -XFS_ERROR(EINVAL);
+               error = -XFS_ERROR(EINVAL);
+               goto out_iput;
        }
 
        if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
-               VN_RELE(vp);
-               return -XFS_ERROR(EFAULT);
+               error = -XFS_ERROR(EFAULT);
+               goto out_iput;
        }
-       aiov.iov_len    = olen;
-       aiov.iov_base   = hreq.ohandle;
 
-       auio.uio_iov    = (struct kvec *)&aiov;
-       auio.uio_iovcnt = 1;
-       auio.uio_offset = 0;
-       auio.uio_segflg = UIO_USERSPACE;
-       auio.uio_resid  = olen;
+       link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
+       if (!link)
+               goto out_iput;
 
-       error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
-       VN_RELE(vp);
+       error = -bhv_vop_readlink(vp, link);
        if (error)
-               return -error;
+               goto out_kfree;
+       error = do_readlink(hreq.ohandle, olen, link);
+       if (error)
+               goto out_kfree;
 
-       return (olen - auio.uio_resid);
+ out_kfree:
+       kfree(link);
+ out_iput:
+       iput(inode);
+       return error;
 }
 
 STATIC int
index 0b5fa124bef2a8d53b88af18169020df11f0a68c..ef941f99b2bc7ee6cfb639b2c5645d1501e27922 100644 (file)
@@ -542,50 +542,26 @@ xfs_vn_follow_link(
        struct dentry           *dentry,
        struct nameidata        *nd)
 {
-       bhv_vnode_t             *vp;
-       uio_t                   *uio;
-       iovec_t                 iov;
-       int                     error;
+       bhv_vnode_t             *vp = vn_from_inode(dentry->d_inode);
        char                    *link;
-
-       ASSERT(dentry);
-       ASSERT(nd);
+       int                     error = -ENOMEM;
 
        link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
-       if (!link) {
-               nd_set_link(nd, ERR_PTR(-ENOMEM));
-               return NULL;
-       }
-
-       uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
-       if (!uio) {
-               kfree(link);
-               nd_set_link(nd, ERR_PTR(-ENOMEM));
-               return NULL;
-       }
-
-       vp = vn_from_inode(dentry->d_inode);
+       if (!link)
+               goto out_err;
 
-       iov.iov_base = link;
-       iov.iov_len = MAXPATHLEN;
-
-       uio->uio_iov = &iov;
-       uio->uio_offset = 0;
-       uio->uio_segflg = UIO_SYSSPACE;
-       uio->uio_resid = MAXPATHLEN;
-       uio->uio_iovcnt = 1;
-
-       error = bhv_vop_readlink(vp, uio, 0, NULL);
-       if (unlikely(error)) {
-               kfree(link);
-               link = ERR_PTR(-error);
-       } else {
-               link[MAXPATHLEN - uio->uio_resid] = '\0';
-       }
-       kfree(uio);
+       error = -bhv_vop_readlink(vp, link);
+       if (unlikely(error))
+               goto out_kfree;
 
        nd_set_link(nd, link);
        return NULL;
+
+ out_kfree:
+       kfree(link);
+ out_err:
+       nd_set_link(nd, ERR_PTR(error));
+       return NULL;
 }
 
 STATIC void
index 146c84ba6941163fa51cedee5bf7cec53e8be613..bddbdb90423419966c9ef675828a797d3ed40226 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __XFS_VNODE_H__
 #define __XFS_VNODE_H__
 
-struct uio;
 struct file;
 struct bhv_vfs;
 struct bhv_vattr;
@@ -165,8 +164,7 @@ typedef int (*vop_readdir_t)(bhv_desc_t *, void *dirent, size_t bufsize,
                                 xfs_off_t *offset, filldir_t filldir);
 typedef int    (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
                                char *, bhv_vnode_t **, struct cred *);
-typedef int    (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
-                               struct cred *);
+typedef int    (*vop_readlink_t)(bhv_desc_t *, char *);
 typedef int    (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
                                xfs_off_t, xfs_off_t);
 typedef int    (*vop_inactive_t)(bhv_desc_t *, struct cred *);
@@ -271,8 +269,8 @@ typedef struct bhv_vnodeops {
                VOP(vop_readdir, vp)(VNHEAD(vp),dirent,bufsize,offset,filldir)
 #define        bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr)                           \
                VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
-#define        bhv_vop_readlink(vp,uiop,fl,cr)                                 \
-               VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr)
+#define        bhv_vop_readlink(vp,link)                                       \
+               VOP(vop_readlink, vp)(VNHEAD(vp), link)
 #define        bhv_vop_fsync(vp,f,cr,b,e)      VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e)
 #define bhv_vop_inactive(vp,cr)                VOP(vop_inactive, vp)(VNHEAD(vp),cr)
 #define bhv_vop_release(vp)            VOP(vop_release, vp)(VNHEAD(vp))
index 36318c66a7bfa5f5f13ded007b51ed28963e2cad..bde4a1ad90f2fb7bbc333a324f1e87131c4cc3a6 100644 (file)
@@ -951,6 +951,53 @@ xfs_access(
  */
 #define SYMLINK_MAPS 2
 
+STATIC int
+xfs_readlink_bmap(
+       xfs_inode_t     *ip,
+       char            *link)
+{
+       xfs_mount_t     *mp = ip->i_mount;
+       int             pathlen = ip->i_d.di_size;
+       int             nmaps = SYMLINK_MAPS;
+       xfs_bmbt_irec_t mval[SYMLINK_MAPS];
+       xfs_daddr_t     d;
+       int             byte_cnt;
+       int             n;
+       xfs_buf_t       *bp;
+       int             error = 0;
+
+       error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0,
+                       mval, &nmaps, NULL, NULL);
+       if (error)
+               goto out;
+
+       for (n = 0; n < nmaps; n++) {
+               d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
+               byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
+
+               bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0);
+               error = XFS_BUF_GETERROR(bp);
+               if (error) {
+                       xfs_ioerror_alert("xfs_readlink",
+                                 ip->i_mount, bp, XFS_BUF_ADDR(bp));
+                       xfs_buf_relse(bp);
+                       goto out;
+               }
+               if (pathlen < byte_cnt)
+                       byte_cnt = pathlen;
+               pathlen -= byte_cnt;
+
+               memcpy(link, XFS_BUF_PTR(bp), byte_cnt);
+               xfs_buf_relse(bp);
+       }
+
+       link[ip->i_d.di_size] = '\0';
+       error = 0;
+
+ out:
+       return error;
+}
+
 /*
  * xfs_readlink
  *
@@ -958,29 +1005,14 @@ xfs_access(
 STATIC int
 xfs_readlink(
        bhv_desc_t      *bdp,
-       uio_t           *uiop,
-       int             ioflags,
-       cred_t          *credp)
+       char            *link)
 {
-       xfs_inode_t     *ip;
-       int             count;
-       xfs_off_t       offset;
+       xfs_inode_t     *ip = XFS_BHVTOI(bdp);
+       xfs_mount_t     *mp = ip->i_mount;
        int             pathlen;
-       bhv_vnode_t     *vp;
        int             error = 0;
-       xfs_mount_t     *mp;
-       int             nmaps;
-       xfs_bmbt_irec_t mval[SYMLINK_MAPS];
-       xfs_daddr_t     d;
-       int             byte_cnt;
-       int             n;
-       xfs_buf_t       *bp;
 
-       vp = BHV_TO_VNODE(bdp);
-       vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-
-       ip = XFS_BHVTOI(bdp);
-       mp = ip->i_mount;
+       vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
 
        if (XFS_FORCED_SHUTDOWN(mp))
                return XFS_ERROR(EIO);
@@ -988,68 +1020,24 @@ xfs_readlink(
        xfs_ilock(ip, XFS_ILOCK_SHARED);
 
        ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
+       ASSERT(ip->i_d.di_size <= MAXPATHLEN);
 
-       offset = uiop->uio_offset;
-       count = uiop->uio_resid;
-
-       if (offset < 0) {
-               error = XFS_ERROR(EINVAL);
-               goto error_return;
-       }
-       if (count <= 0) {
-               error = 0;
-               goto error_return;
-       }
-
-       /*
-        * See if the symlink is stored inline.
-        */
-       pathlen = (int)ip->i_d.di_size;
+       pathlen = ip->i_d.di_size;
+       if (!pathlen)
+               goto out;
 
        if (ip->i_df.if_flags & XFS_IFINLINE) {
-               error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
-       }
-       else {
-               /*
-                * Symlink not inline.  Call bmap to get it in.
-                */
-               nmaps = SYMLINK_MAPS;
-
-               error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen),
-                                 0, NULL, 0, mval, &nmaps, NULL, NULL);
-
-               if (error) {
-                       goto error_return;
-               }
-
-               for (n = 0; n < nmaps; n++) {
-                       d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
-                       byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
-                       bp = xfs_buf_read(mp->m_ddev_targp, d,
-                                     BTOBB(byte_cnt), 0);
-                       error = XFS_BUF_GETERROR(bp);
-                       if (error) {
-                               xfs_ioerror_alert("xfs_readlink",
-                                         ip->i_mount, bp, XFS_BUF_ADDR(bp));
-                               xfs_buf_relse(bp);
-                               goto error_return;
-                       }
-                       if (pathlen < byte_cnt)
-                               byte_cnt = pathlen;
-                       pathlen -= byte_cnt;
-
-                       error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
-                       xfs_buf_relse (bp);
-               }
-
+               memcpy(link, ip->i_df.if_u1.if_data, pathlen);
+               link[pathlen] = '\0';
+       } else {
+               error = xfs_readlink_bmap(ip, link);
        }
 
-error_return:
+ out:
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
        return error;
 }
 
-
 /*
  * xfs_fsync
  *