aboutsummaryrefslogtreecommitdiffstats
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(
951 */ 951 */
952#define SYMLINK_MAPS 2 952#define SYMLINK_MAPS 2
953 953
954STATIC int
955xfs_readlink_bmap(
956 xfs_inode_t *ip,
957 char *link)
958{
959 xfs_mount_t *mp = ip->i_mount;
960 int pathlen = ip->i_d.di_size;
961 int nmaps = SYMLINK_MAPS;
962 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
963 xfs_daddr_t d;
964 int byte_cnt;
965 int n;
966 xfs_buf_t *bp;
967 int error = 0;
968
969 error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0,
970 mval, &nmaps, NULL, NULL);
971 if (error)
972 goto out;
973
974 for (n = 0; n < nmaps; n++) {
975 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
976 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
977
978 bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0);
979 error = XFS_BUF_GETERROR(bp);
980 if (error) {
981 xfs_ioerror_alert("xfs_readlink",
982 ip->i_mount, bp, XFS_BUF_ADDR(bp));
983 xfs_buf_relse(bp);
984 goto out;
985 }
986 if (pathlen < byte_cnt)
987 byte_cnt = pathlen;
988 pathlen -= byte_cnt;
989
990 memcpy(link, XFS_BUF_PTR(bp), byte_cnt);
991 xfs_buf_relse(bp);
992 }
993
994 link[ip->i_d.di_size] = '\0';
995 error = 0;
996
997 out:
998 return error;
999}
1000
954/* 1001/*
955 * xfs_readlink 1002 * xfs_readlink
956 * 1003 *
@@ -958,29 +1005,14 @@ xfs_access(
958STATIC int 1005STATIC int
959xfs_readlink( 1006xfs_readlink(
960 bhv_desc_t *bdp, 1007 bhv_desc_t *bdp,
961 uio_t *uiop, 1008 char *link)
962 int ioflags,
963 cred_t *credp)
964{ 1009{
965 xfs_inode_t *ip; 1010 xfs_inode_t *ip = XFS_BHVTOI(bdp);
966 int count; 1011 xfs_mount_t *mp = ip->i_mount;
967 xfs_off_t offset;
968 int pathlen; 1012 int pathlen;
969 bhv_vnode_t *vp;
970 int error = 0; 1013 int error = 0;
971 xfs_mount_t *mp;
972 int nmaps;
973 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
974 xfs_daddr_t d;
975 int byte_cnt;
976 int n;
977 xfs_buf_t *bp;
978 1014
979 vp = BHV_TO_VNODE(bdp); 1015 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
980 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
981
982 ip = XFS_BHVTOI(bdp);
983 mp = ip->i_mount;
984 1016
985 if (XFS_FORCED_SHUTDOWN(mp)) 1017 if (XFS_FORCED_SHUTDOWN(mp))
986 return XFS_ERROR(EIO); 1018 return XFS_ERROR(EIO);
@@ -988,68 +1020,24 @@ xfs_readlink(
988 xfs_ilock(ip, XFS_ILOCK_SHARED); 1020 xfs_ilock(ip, XFS_ILOCK_SHARED);
989 1021
990 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK); 1022 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
1023 ASSERT(ip->i_d.di_size <= MAXPATHLEN);
991 1024
992 offset = uiop->uio_offset; 1025 pathlen = ip->i_d.di_size;
993 count = uiop->uio_resid; 1026 if (!pathlen)
994 1027 goto out;
995 if (offset < 0) {
996 error = XFS_ERROR(EINVAL);
997 goto error_return;
998 }
999 if (count <= 0) {
1000 error = 0;
1001 goto error_return;
1002 }
1003
1004 /*
1005 * See if the symlink is stored inline.
1006 */
1007 pathlen = (int)ip->i_d.di_size;
1008 1028
1009 if (ip->i_df.if_flags & XFS_IFINLINE) { 1029 if (ip->i_df.if_flags & XFS_IFINLINE) {
1010 error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); 1030 memcpy(link, ip->i_df.if_u1.if_data, pathlen);
1011 } 1031 link[pathlen] = '\0';
1012 else { 1032 } else {
1013 /* 1033 error = xfs_readlink_bmap(ip, link);
1014 * Symlink not inline. Call bmap to get it in.
1015 */
1016 nmaps = SYMLINK_MAPS;
1017
1018 error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen),
1019 0, NULL, 0, mval, &nmaps, NULL, NULL);
1020
1021 if (error) {
1022 goto error_return;
1023 }
1024
1025 for (n = 0; n < nmaps; n++) {
1026 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
1027 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
1028 bp = xfs_buf_read(mp->m_ddev_targp, d,
1029 BTOBB(byte_cnt), 0);
1030 error = XFS_BUF_GETERROR(bp);
1031 if (error) {
1032 xfs_ioerror_alert("xfs_readlink",
1033 ip->i_mount, bp, XFS_BUF_ADDR(bp));
1034 xfs_buf_relse(bp);
1035 goto error_return;
1036 }
1037 if (pathlen < byte_cnt)
1038 byte_cnt = pathlen;
1039 pathlen -= byte_cnt;
1040
1041 error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
1042 xfs_buf_relse (bp);
1043 }
1044
1045 } 1034 }
1046 1035
1047error_return: 1036 out:
1048 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1037 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1049 return error; 1038 return error;
1050} 1039}
1051 1040
1052
1053/* 1041/*
1054 * xfs_fsync 1042 * xfs_fsync
1055 * 1043 *