* Copies a byte range from invp to outvp. Calls VOP_COPY_FILE_RANGE() * or vn_generic_copy_file_range() after rangelocking the byte ranges, * to do the actual copy. * vn_generic_copy_file_range() is factored out, so it can be called * from a VOP_COPY_FILE_RANGE() call as well, but handles vnodes from * different file systems. */
| 2808 | * different file systems. |
| 2809 | */ |
| 2810 | int |
| 2811 | vn_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp, |
| 2812 | off_t *outoffp, size_t *lenp, unsigned int flags, struct ucred *incred, |
| 2813 | struct ucred *outcred, struct thread *fsize_td) |
| 2814 | { |
| 2815 | int error; |
| 2816 | size_t len; |
| 2817 | uint64_t uval; |
| 2818 | |
| 2819 | len = *lenp; |
| 2820 | *lenp = 0; /* For error returns. */ |
| 2821 | error = 0; |
| 2822 | |
| 2823 | /* Do some sanity checks on the arguments. */ |
| 2824 | if (invp->v_type == VDIR || outvp->v_type == VDIR) |
| 2825 | error = EISDIR; |
| 2826 | else if (*inoffp < 0 || *outoffp < 0 || |
| 2827 | invp->v_type != VREG || outvp->v_type != VREG) |
| 2828 | error = EINVAL; |
| 2829 | if (error != 0) |
| 2830 | goto out; |
| 2831 | |
| 2832 | /* Ensure offset + len does not wrap around. */ |
| 2833 | uval = *inoffp; |
| 2834 | uval += len; |
| 2835 | if (uval > INT64_MAX) |
| 2836 | len = INT64_MAX - *inoffp; |
| 2837 | uval = *outoffp; |
| 2838 | uval += len; |
| 2839 | if (uval > INT64_MAX) |
| 2840 | len = INT64_MAX - *outoffp; |
| 2841 | if (len == 0) |
| 2842 | goto out; |
| 2843 | |
| 2844 | /* |
| 2845 | * If the two vnode are for the same file system, call |
| 2846 | * VOP_COPY_FILE_RANGE(), otherwise call vn_generic_copy_file_range() |
| 2847 | * which can handle copies across multiple file systems. |
| 2848 | */ |
| 2849 | *lenp = len; |
| 2850 | if (invp->v_mount == outvp->v_mount) |
| 2851 | error = VOP_COPY_FILE_RANGE(invp, inoffp, outvp, outoffp, |
| 2852 | lenp, flags, incred, outcred, fsize_td); |
| 2853 | else |
| 2854 | error = vn_generic_copy_file_range(invp, inoffp, outvp, |
| 2855 | outoffp, lenp, flags, incred, outcred, fsize_td); |
| 2856 | out: |
| 2857 | return (error); |
| 2858 | } |
| 2859 | |
| 2860 | /* |
| 2861 | * Test len bytes of data starting at dat for all bytes == 0. |
no test coverage detected