mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 16:24:13 +08:00
[XFS] stop using uio in the readlink code
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>
This commit is contained in:
parent
051e7cd44a
commit
804c83c376
@ -349,19 +349,44 @@ xfs_open_by_handle(
|
|||||||
return new_fd;
|
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
|
STATIC int
|
||||||
xfs_readlink_by_handle(
|
xfs_readlink_by_handle(
|
||||||
xfs_mount_t *mp,
|
xfs_mount_t *mp,
|
||||||
void __user *arg,
|
void __user *arg,
|
||||||
struct inode *parinode)
|
struct inode *parinode)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
struct iovec aiov;
|
|
||||||
struct uio auio;
|
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
xfs_fsop_handlereq_t hreq;
|
xfs_fsop_handlereq_t hreq;
|
||||||
bhv_vnode_t *vp;
|
bhv_vnode_t *vp;
|
||||||
__u32 olen;
|
__u32 olen;
|
||||||
|
void *link;
|
||||||
|
int error;
|
||||||
|
|
||||||
if (!capable(CAP_SYS_ADMIN))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
return -XFS_ERROR(EPERM);
|
return -XFS_ERROR(EPERM);
|
||||||
@ -374,29 +399,31 @@ xfs_readlink_by_handle(
|
|||||||
|
|
||||||
/* Restrict this handle operation to symlinks only. */
|
/* Restrict this handle operation to symlinks only. */
|
||||||
if (!S_ISLNK(inode->i_mode)) {
|
if (!S_ISLNK(inode->i_mode)) {
|
||||||
VN_RELE(vp);
|
error = -XFS_ERROR(EINVAL);
|
||||||
return -XFS_ERROR(EINVAL);
|
goto out_iput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
|
if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
|
||||||
VN_RELE(vp);
|
error = -XFS_ERROR(EFAULT);
|
||||||
return -XFS_ERROR(EFAULT);
|
goto out_iput;
|
||||||
}
|
}
|
||||||
aiov.iov_len = olen;
|
|
||||||
aiov.iov_base = hreq.ohandle;
|
|
||||||
|
|
||||||
auio.uio_iov = (struct kvec *)&aiov;
|
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
|
||||||
auio.uio_iovcnt = 1;
|
if (!link)
|
||||||
auio.uio_offset = 0;
|
goto out_iput;
|
||||||
auio.uio_segflg = UIO_USERSPACE;
|
|
||||||
auio.uio_resid = olen;
|
|
||||||
|
|
||||||
error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
|
error = -bhv_vop_readlink(vp, link);
|
||||||
VN_RELE(vp);
|
|
||||||
if (error)
|
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
|
STATIC int
|
||||||
|
@ -542,50 +542,26 @@ xfs_vn_follow_link(
|
|||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
struct nameidata *nd)
|
struct nameidata *nd)
|
||||||
{
|
{
|
||||||
bhv_vnode_t *vp;
|
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
|
||||||
uio_t *uio;
|
|
||||||
iovec_t iov;
|
|
||||||
int error;
|
|
||||||
char *link;
|
char *link;
|
||||||
|
int error = -ENOMEM;
|
||||||
ASSERT(dentry);
|
|
||||||
ASSERT(nd);
|
|
||||||
|
|
||||||
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
|
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
|
||||||
if (!link) {
|
if (!link)
|
||||||
nd_set_link(nd, ERR_PTR(-ENOMEM));
|
goto out_err;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
|
error = -bhv_vop_readlink(vp, link);
|
||||||
if (!uio) {
|
if (unlikely(error))
|
||||||
kfree(link);
|
goto out_kfree;
|
||||||
nd_set_link(nd, ERR_PTR(-ENOMEM));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
vp = vn_from_inode(dentry->d_inode);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
nd_set_link(nd, link);
|
nd_set_link(nd, link);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
out_kfree:
|
||||||
|
kfree(link);
|
||||||
|
out_err:
|
||||||
|
nd_set_link(nd, ERR_PTR(error));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#ifndef __XFS_VNODE_H__
|
#ifndef __XFS_VNODE_H__
|
||||||
#define __XFS_VNODE_H__
|
#define __XFS_VNODE_H__
|
||||||
|
|
||||||
struct uio;
|
|
||||||
struct file;
|
struct file;
|
||||||
struct bhv_vfs;
|
struct bhv_vfs;
|
||||||
struct bhv_vattr;
|
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);
|
xfs_off_t *offset, filldir_t filldir);
|
||||||
typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
|
typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
|
||||||
char *, bhv_vnode_t **, struct cred *);
|
char *, bhv_vnode_t **, struct cred *);
|
||||||
typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
|
typedef int (*vop_readlink_t)(bhv_desc_t *, char *);
|
||||||
struct cred *);
|
|
||||||
typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
|
typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
|
||||||
xfs_off_t, xfs_off_t);
|
xfs_off_t, xfs_off_t);
|
||||||
typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *);
|
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)
|
VOP(vop_readdir, vp)(VNHEAD(vp),dirent,bufsize,offset,filldir)
|
||||||
#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
|
#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
|
||||||
VOP(vop_symlink, dvp)(VNHEAD(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) \
|
#define bhv_vop_readlink(vp,link) \
|
||||||
VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr)
|
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_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_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr)
|
||||||
#define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp))
|
#define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp))
|
||||||
|
@ -951,6 +951,53 @@ xfs_access(
|
|||||||
*/
|
*/
|
||||||
#define SYMLINK_MAPS 2
|
#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
|
* xfs_readlink
|
||||||
*
|
*
|
||||||
@ -958,29 +1005,14 @@ xfs_access(
|
|||||||
STATIC int
|
STATIC int
|
||||||
xfs_readlink(
|
xfs_readlink(
|
||||||
bhv_desc_t *bdp,
|
bhv_desc_t *bdp,
|
||||||
uio_t *uiop,
|
char *link)
|
||||||
int ioflags,
|
|
||||||
cred_t *credp)
|
|
||||||
{
|
{
|
||||||
xfs_inode_t *ip;
|
xfs_inode_t *ip = XFS_BHVTOI(bdp);
|
||||||
int count;
|
xfs_mount_t *mp = ip->i_mount;
|
||||||
xfs_off_t offset;
|
|
||||||
int pathlen;
|
int pathlen;
|
||||||
bhv_vnode_t *vp;
|
|
||||||
int error = 0;
|
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(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
|
||||||
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
|
|
||||||
|
|
||||||
ip = XFS_BHVTOI(bdp);
|
|
||||||
mp = ip->i_mount;
|
|
||||||
|
|
||||||
if (XFS_FORCED_SHUTDOWN(mp))
|
if (XFS_FORCED_SHUTDOWN(mp))
|
||||||
return XFS_ERROR(EIO);
|
return XFS_ERROR(EIO);
|
||||||
@ -988,68 +1020,24 @@ xfs_readlink(
|
|||||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||||
|
|
||||||
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
|
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
|
||||||
|
ASSERT(ip->i_d.di_size <= MAXPATHLEN);
|
||||||
|
|
||||||
offset = uiop->uio_offset;
|
pathlen = ip->i_d.di_size;
|
||||||
count = uiop->uio_resid;
|
if (!pathlen)
|
||||||
|
goto out;
|
||||||
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;
|
|
||||||
|
|
||||||
if (ip->i_df.if_flags & XFS_IFINLINE) {
|
if (ip->i_df.if_flags & XFS_IFINLINE) {
|
||||||
error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
|
memcpy(link, ip->i_df.if_u1.if_data, pathlen);
|
||||||
}
|
link[pathlen] = '\0';
|
||||||
else {
|
} else {
|
||||||
/*
|
error = xfs_readlink_bmap(ip, link);
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_return:
|
out:
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xfs_fsync
|
* xfs_fsync
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user