diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 63 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 50 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 132 |
4 files changed, 121 insertions, 132 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 5917808abbd6..47cfde6cfae2 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -349,19 +349,44 @@ xfs_open_by_handle( | |||
349 | return new_fd; | 349 | return new_fd; |
350 | } | 350 | } |
351 | 351 | ||
352 | /* | ||
353 | * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's | ||
354 | * unused first argument. | ||
355 | */ | ||
356 | STATIC int | ||
357 | do_readlink( | ||
358 | char __user *buffer, | ||
359 | int buflen, | ||
360 | const char *link) | ||
361 | { | ||
362 | int len; | ||
363 | |||
364 | len = PTR_ERR(link); | ||
365 | if (IS_ERR(link)) | ||
366 | goto out; | ||
367 | |||
368 | len = strlen(link); | ||
369 | if (len > (unsigned) buflen) | ||
370 | len = buflen; | ||
371 | if (copy_to_user(buffer, link, len)) | ||
372 | len = -EFAULT; | ||
373 | out: | ||
374 | return len; | ||
375 | } | ||
376 | |||
377 | |||
352 | STATIC int | 378 | STATIC int |
353 | xfs_readlink_by_handle( | 379 | xfs_readlink_by_handle( |
354 | xfs_mount_t *mp, | 380 | xfs_mount_t *mp, |
355 | void __user *arg, | 381 | void __user *arg, |
356 | struct inode *parinode) | 382 | struct inode *parinode) |
357 | { | 383 | { |
358 | int error; | ||
359 | struct iovec aiov; | ||
360 | struct uio auio; | ||
361 | struct inode *inode; | 384 | struct inode *inode; |
362 | xfs_fsop_handlereq_t hreq; | 385 | xfs_fsop_handlereq_t hreq; |
363 | bhv_vnode_t *vp; | 386 | bhv_vnode_t *vp; |
364 | __u32 olen; | 387 | __u32 olen; |
388 | void *link; | ||
389 | int error; | ||
365 | 390 | ||
366 | if (!capable(CAP_SYS_ADMIN)) | 391 | if (!capable(CAP_SYS_ADMIN)) |
367 | return -XFS_ERROR(EPERM); | 392 | return -XFS_ERROR(EPERM); |
@@ -374,29 +399,31 @@ xfs_readlink_by_handle( | |||
374 | 399 | ||
375 | /* Restrict this handle operation to symlinks only. */ | 400 | /* Restrict this handle operation to symlinks only. */ |
376 | if (!S_ISLNK(inode->i_mode)) { | 401 | if (!S_ISLNK(inode->i_mode)) { |
377 | VN_RELE(vp); | 402 | error = -XFS_ERROR(EINVAL); |
378 | return -XFS_ERROR(EINVAL); | 403 | goto out_iput; |
379 | } | 404 | } |
380 | 405 | ||
381 | if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { | 406 | if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { |
382 | VN_RELE(vp); | 407 | error = -XFS_ERROR(EFAULT); |
383 | return -XFS_ERROR(EFAULT); | 408 | goto out_iput; |
384 | } | 409 | } |
385 | aiov.iov_len = olen; | ||
386 | aiov.iov_base = hreq.ohandle; | ||
387 | 410 | ||
388 | auio.uio_iov = (struct kvec *)&aiov; | 411 | link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); |
389 | auio.uio_iovcnt = 1; | 412 | if (!link) |
390 | auio.uio_offset = 0; | 413 | goto out_iput; |
391 | auio.uio_segflg = UIO_USERSPACE; | ||
392 | auio.uio_resid = olen; | ||
393 | 414 | ||
394 | error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL); | 415 | error = -bhv_vop_readlink(vp, link); |
395 | VN_RELE(vp); | ||
396 | if (error) | 416 | if (error) |
397 | return -error; | 417 | goto out_kfree; |
418 | error = do_readlink(hreq.ohandle, olen, link); | ||
419 | if (error) | ||
420 | goto out_kfree; | ||
398 | 421 | ||
399 | return (olen - auio.uio_resid); | 422 | out_kfree: |
423 | kfree(link); | ||
424 | out_iput: | ||
425 | iput(inode); | ||
426 | return error; | ||
400 | } | 427 | } |
401 | 428 | ||
402 | STATIC int | 429 | STATIC int |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 0b5fa124bef2..ef941f99b2bc 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -542,50 +542,26 @@ xfs_vn_follow_link( | |||
542 | struct dentry *dentry, | 542 | struct dentry *dentry, |
543 | struct nameidata *nd) | 543 | struct nameidata *nd) |
544 | { | 544 | { |
545 | bhv_vnode_t *vp; | 545 | bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); |
546 | uio_t *uio; | ||
547 | iovec_t iov; | ||
548 | int error; | ||
549 | char *link; | 546 | char *link; |
550 | 547 | int error = -ENOMEM; | |
551 | ASSERT(dentry); | ||
552 | ASSERT(nd); | ||
553 | 548 | ||
554 | link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); | 549 | link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); |
555 | if (!link) { | 550 | if (!link) |
556 | nd_set_link(nd, ERR_PTR(-ENOMEM)); | 551 | goto out_err; |
557 | return NULL; | ||
558 | } | ||
559 | |||
560 | uio = kmalloc(sizeof(uio_t), GFP_KERNEL); | ||
561 | if (!uio) { | ||
562 | kfree(link); | ||
563 | nd_set_link(nd, ERR_PTR(-ENOMEM)); | ||
564 | return NULL; | ||
565 | } | ||
566 | |||
567 | vp = vn_from_inode(dentry->d_inode); | ||
568 | 552 | ||
569 | iov.iov_base = link; | 553 | error = -bhv_vop_readlink(vp, link); |
570 | iov.iov_len = MAXPATHLEN; | 554 | if (unlikely(error)) |
571 | 555 | goto out_kfree; | |
572 | uio->uio_iov = &iov; | ||
573 | uio->uio_offset = 0; | ||
574 | uio->uio_segflg = UIO_SYSSPACE; | ||
575 | uio->uio_resid = MAXPATHLEN; | ||
576 | uio->uio_iovcnt = 1; | ||
577 | |||
578 | error = bhv_vop_readlink(vp, uio, 0, NULL); | ||
579 | if (unlikely(error)) { | ||
580 | kfree(link); | ||
581 | link = ERR_PTR(-error); | ||
582 | } else { | ||
583 | link[MAXPATHLEN - uio->uio_resid] = '\0'; | ||
584 | } | ||
585 | kfree(uio); | ||
586 | 556 | ||
587 | nd_set_link(nd, link); | 557 | nd_set_link(nd, link); |
588 | return NULL; | 558 | return NULL; |
559 | |||
560 | out_kfree: | ||
561 | kfree(link); | ||
562 | out_err: | ||
563 | nd_set_link(nd, ERR_PTR(error)); | ||
564 | return NULL; | ||
589 | } | 565 | } |
590 | 566 | ||
591 | STATIC void | 567 | STATIC void |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 146c84ba6941..bddbdb904234 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -18,7 +18,6 @@ | |||
18 | #ifndef __XFS_VNODE_H__ | 18 | #ifndef __XFS_VNODE_H__ |
19 | #define __XFS_VNODE_H__ | 19 | #define __XFS_VNODE_H__ |
20 | 20 | ||
21 | struct uio; | ||
22 | struct file; | 21 | struct file; |
23 | struct bhv_vfs; | 22 | struct bhv_vfs; |
24 | struct bhv_vattr; | 23 | struct bhv_vattr; |
@@ -165,8 +164,7 @@ typedef int (*vop_readdir_t)(bhv_desc_t *, void *dirent, size_t bufsize, | |||
165 | xfs_off_t *offset, filldir_t filldir); | 164 | xfs_off_t *offset, filldir_t filldir); |
166 | typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*, | 165 | typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*, |
167 | char *, bhv_vnode_t **, struct cred *); | 166 | char *, bhv_vnode_t **, struct cred *); |
168 | typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, | 167 | typedef int (*vop_readlink_t)(bhv_desc_t *, char *); |
169 | struct cred *); | ||
170 | typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, | 168 | typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, |
171 | xfs_off_t, xfs_off_t); | 169 | xfs_off_t, xfs_off_t); |
172 | typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); | 170 | typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); |
@@ -271,8 +269,8 @@ typedef struct bhv_vnodeops { | |||
271 | VOP(vop_readdir, vp)(VNHEAD(vp),dirent,bufsize,offset,filldir) | 269 | VOP(vop_readdir, vp)(VNHEAD(vp),dirent,bufsize,offset,filldir) |
272 | #define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \ | 270 | #define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \ |
273 | VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr) | 271 | VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr) |
274 | #define bhv_vop_readlink(vp,uiop,fl,cr) \ | 272 | #define bhv_vop_readlink(vp,link) \ |
275 | VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr) | 273 | VOP(vop_readlink, vp)(VNHEAD(vp), link) |
276 | #define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e) | 274 | #define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e) |
277 | #define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr) | 275 | #define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr) |
278 | #define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp)) | 276 | #define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp)) |
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 | * |