summaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c132
1 files changed, 60 insertions, 72 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 36318c66a7b..bde4a1ad90f 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -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
*