diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 132 |
1 files changed, 60 insertions, 72 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 36318c66a7bf..bde4a1ad90f2 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 | ||
954 | STATIC int | ||
955 | xfs_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( | |||
958 | STATIC int | 1005 | STATIC int |
959 | xfs_readlink( | 1006 | xfs_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 | ||
1047 | error_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 | * |