65 #include <inet/ip.h>
66 #include <inet/ip6.h>
67 #include <inet/tcp.h>
68
69 extern int sosendfile64(file_t *, file_t *, const struct ksendfilevec64 *,
70 ssize32_t *);
71 extern int nl7c_sendfilev(struct sonode *, u_offset_t *, struct sendfilevec *,
72 int, ssize_t *);
73 extern int snf_segmap(file_t *, vnode_t *, u_offset_t, u_offset_t, ssize_t *,
74 boolean_t);
75 extern sotpi_info_t *sotpi_sototpi(struct sonode *);
76
77 #define SEND_MAX_CHUNK 16
78
79 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
80 /*
81 * 64 bit offsets for 32 bit applications only running either on
82 * 64 bit kernel or 32 bit kernel. For 32 bit apps, we can't transfer
83 * more than 2GB of data.
84 */
85 int
86 sendvec_chunk64(file_t *fp, u_offset_t *fileoff, struct ksendfilevec64 *sfv,
87 int copy_cnt, ssize32_t *count)
88 {
89 struct vnode *vp;
90 ushort_t fflag;
91 int ioflag;
92 size32_t cnt;
93 ssize32_t sfv_len;
94 ssize32_t tmpcount;
95 u_offset_t sfv_off;
96 struct uio auio;
97 struct iovec aiov;
98 int i, error;
99
100 fflag = fp->f_flag;
101 vp = fp->f_vnode;
102 for (i = 0; i < copy_cnt; i++) {
103
104 if (ISSIG(curthread, JUSTLOOKING))
105 return (EINTR);
326 if (vp->v_type == VREG)
327 *fileoff += cnt;
328 *count += cnt;
329 if (error != 0) {
330 kmem_free(ptr, size);
331 VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE,
332 NULL);
333 releasef(sfv->sfv_fd);
334 return (error);
335 }
336 }
337 VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
338 releasef(sfv->sfv_fd);
339 kmem_free(ptr, size);
340 }
341 sfv++;
342 }
343 return (0);
344 }
345
346 ssize32_t
347 sendvec64(file_t *fp, const struct ksendfilevec64 *vec, int sfvcnt,
348 size32_t *xferred, int fildes)
349 {
350 u_offset_t fileoff;
351 int copy_cnt;
352 const struct ksendfilevec64 *copy_vec;
353 struct ksendfilevec64 sfv[SEND_MAX_CHUNK];
354 struct vnode *vp;
355 int error;
356 ssize32_t count = 0;
357
358 vp = fp->f_vnode;
359 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
360
361 copy_vec = vec;
362 fileoff = fp->f_offset;
363
364 do {
365 copy_cnt = MIN(sfvcnt, SEND_MAX_CHUNK);
366 if (copyin(copy_vec, sfv, copy_cnt *
373 if (error != 0)
374 break;
375
376 copy_vec += copy_cnt;
377 sfvcnt -= copy_cnt;
378 } while (sfvcnt > 0);
379
380 if (vp->v_type == VREG)
381 fp->f_offset += count;
382
383 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
384 if (copyout(&count, xferred, sizeof (count)))
385 error = EFAULT;
386 releasef(fildes);
387 if (error != 0)
388 return (set_errno(error));
389 return (count);
390 }
391 #endif
392
393 int
394 sendvec_small_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
395 int copy_cnt, ssize_t total_size, int maxblk, ssize_t *count)
396 {
397 struct vnode *vp;
398 struct uio auio;
399 struct iovec aiov;
400 ushort_t fflag;
401 int ioflag;
402 int i, error;
403 size_t cnt;
404 ssize_t sfv_len;
405 u_offset_t sfv_off;
406 #ifdef _SYSCALL32_IMPL
407 model_t model = get_udatamodel();
408 u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
409 MAXOFF32_T : MAXOFFSET_T;
410 #else
411 const u_offset_t maxoff = MAXOFF32_T;
412 #endif
413 mblk_t *dmp = NULL;
663 VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
664 releasef(sfv->sfv_fd);
665 }
666 sfv++;
667 }
668
669 ASSERT(total_size == 0);
670 error = socket_sendmblk(VTOSO(vp), &msg, fflag, CRED(), &head);
671 if (error != 0) {
672 if (head != NULL)
673 freemsg(head);
674 return (error);
675 }
676 ttolwp(curthread)->lwp_ru.ioch += (ulong_t)size;
677 *count += size;
678
679 return (0);
680 }
681
682
683 int
684 sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
685 int copy_cnt, ssize_t *count)
686 {
687 struct vnode *vp;
688 struct uio auio;
689 struct iovec aiov;
690 ushort_t fflag;
691 int ioflag;
692 int i, error;
693 size_t cnt;
694 ssize_t sfv_len;
695 u_offset_t sfv_off;
696 #ifdef _SYSCALL32_IMPL
697 model_t model = get_udatamodel();
698 u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
699 MAXOFF32_T : MAXOFFSET_T;
700 #else
701 const u_offset_t maxoff = MAXOFF32_T;
702 #endif
703 mblk_t *dmp = NULL;
1143 if ((fp = getf(fildes)) == NULL)
1144 return (set_errno(EBADF));
1145
1146 if (((fp->f_flag) & FWRITE) == 0) {
1147 error = EBADF;
1148 goto err;
1149 }
1150
1151 fileoff = fp->f_offset;
1152 vp = fp->f_vnode;
1153
1154 switch (vp->v_type) {
1155 case VSOCK:
1156 so = VTOSO(vp);
1157 is_sock = B_TRUE;
1158 if (SOCK_IS_NONSTR(so)) {
1159 maxblk = so->so_proto_props.sopp_maxblk;
1160 } else {
1161 maxblk = (int)vp->v_stream->sd_maxblk;
1162 }
1163 break;
1164 case VREG:
1165 break;
1166 default:
1167 error = EINVAL;
1168 goto err;
1169 }
1170
1171 switch (opcode) {
1172 case SENDFILEV :
1173 break;
1174 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
1175 case SENDFILEV64 :
1176 return (sendvec64(fp, (struct ksendfilevec64 *)vec, sfvcnt,
1177 (size32_t *)xferred, fildes));
1178 #endif
1179 default :
1180 error = ENOSYS;
1181 break;
1182 }
|
65 #include <inet/ip.h>
66 #include <inet/ip6.h>
67 #include <inet/tcp.h>
68
69 extern int sosendfile64(file_t *, file_t *, const struct ksendfilevec64 *,
70 ssize32_t *);
71 extern int nl7c_sendfilev(struct sonode *, u_offset_t *, struct sendfilevec *,
72 int, ssize_t *);
73 extern int snf_segmap(file_t *, vnode_t *, u_offset_t, u_offset_t, ssize_t *,
74 boolean_t);
75 extern sotpi_info_t *sotpi_sototpi(struct sonode *);
76
77 #define SEND_MAX_CHUNK 16
78
79 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
80 /*
81 * 64 bit offsets for 32 bit applications only running either on
82 * 64 bit kernel or 32 bit kernel. For 32 bit apps, we can't transfer
83 * more than 2GB of data.
84 */
85 static int
86 sendvec_chunk64(file_t *fp, u_offset_t *fileoff, struct ksendfilevec64 *sfv,
87 int copy_cnt, ssize32_t *count)
88 {
89 struct vnode *vp;
90 ushort_t fflag;
91 int ioflag;
92 size32_t cnt;
93 ssize32_t sfv_len;
94 ssize32_t tmpcount;
95 u_offset_t sfv_off;
96 struct uio auio;
97 struct iovec aiov;
98 int i, error;
99
100 fflag = fp->f_flag;
101 vp = fp->f_vnode;
102 for (i = 0; i < copy_cnt; i++) {
103
104 if (ISSIG(curthread, JUSTLOOKING))
105 return (EINTR);
326 if (vp->v_type == VREG)
327 *fileoff += cnt;
328 *count += cnt;
329 if (error != 0) {
330 kmem_free(ptr, size);
331 VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE,
332 NULL);
333 releasef(sfv->sfv_fd);
334 return (error);
335 }
336 }
337 VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
338 releasef(sfv->sfv_fd);
339 kmem_free(ptr, size);
340 }
341 sfv++;
342 }
343 return (0);
344 }
345
346 static ssize32_t
347 sendvec64(file_t *fp, const struct ksendfilevec64 *vec, int sfvcnt,
348 size32_t *xferred, int fildes)
349 {
350 u_offset_t fileoff;
351 int copy_cnt;
352 const struct ksendfilevec64 *copy_vec;
353 struct ksendfilevec64 sfv[SEND_MAX_CHUNK];
354 struct vnode *vp;
355 int error;
356 ssize32_t count = 0;
357
358 vp = fp->f_vnode;
359 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
360
361 copy_vec = vec;
362 fileoff = fp->f_offset;
363
364 do {
365 copy_cnt = MIN(sfvcnt, SEND_MAX_CHUNK);
366 if (copyin(copy_vec, sfv, copy_cnt *
373 if (error != 0)
374 break;
375
376 copy_vec += copy_cnt;
377 sfvcnt -= copy_cnt;
378 } while (sfvcnt > 0);
379
380 if (vp->v_type == VREG)
381 fp->f_offset += count;
382
383 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
384 if (copyout(&count, xferred, sizeof (count)))
385 error = EFAULT;
386 releasef(fildes);
387 if (error != 0)
388 return (set_errno(error));
389 return (count);
390 }
391 #endif
392
393 static int
394 sendvec_small_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
395 int copy_cnt, ssize_t total_size, int maxblk, ssize_t *count)
396 {
397 struct vnode *vp;
398 struct uio auio;
399 struct iovec aiov;
400 ushort_t fflag;
401 int ioflag;
402 int i, error;
403 size_t cnt;
404 ssize_t sfv_len;
405 u_offset_t sfv_off;
406 #ifdef _SYSCALL32_IMPL
407 model_t model = get_udatamodel();
408 u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
409 MAXOFF32_T : MAXOFFSET_T;
410 #else
411 const u_offset_t maxoff = MAXOFF32_T;
412 #endif
413 mblk_t *dmp = NULL;
663 VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
664 releasef(sfv->sfv_fd);
665 }
666 sfv++;
667 }
668
669 ASSERT(total_size == 0);
670 error = socket_sendmblk(VTOSO(vp), &msg, fflag, CRED(), &head);
671 if (error != 0) {
672 if (head != NULL)
673 freemsg(head);
674 return (error);
675 }
676 ttolwp(curthread)->lwp_ru.ioch += (ulong_t)size;
677 *count += size;
678
679 return (0);
680 }
681
682
683 static int
684 sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
685 int copy_cnt, ssize_t *count)
686 {
687 struct vnode *vp;
688 struct uio auio;
689 struct iovec aiov;
690 ushort_t fflag;
691 int ioflag;
692 int i, error;
693 size_t cnt;
694 ssize_t sfv_len;
695 u_offset_t sfv_off;
696 #ifdef _SYSCALL32_IMPL
697 model_t model = get_udatamodel();
698 u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
699 MAXOFF32_T : MAXOFFSET_T;
700 #else
701 const u_offset_t maxoff = MAXOFF32_T;
702 #endif
703 mblk_t *dmp = NULL;
1143 if ((fp = getf(fildes)) == NULL)
1144 return (set_errno(EBADF));
1145
1146 if (((fp->f_flag) & FWRITE) == 0) {
1147 error = EBADF;
1148 goto err;
1149 }
1150
1151 fileoff = fp->f_offset;
1152 vp = fp->f_vnode;
1153
1154 switch (vp->v_type) {
1155 case VSOCK:
1156 so = VTOSO(vp);
1157 is_sock = B_TRUE;
1158 if (SOCK_IS_NONSTR(so)) {
1159 maxblk = so->so_proto_props.sopp_maxblk;
1160 } else {
1161 maxblk = (int)vp->v_stream->sd_maxblk;
1162 }
1163
1164 /*
1165 * We need to make sure that the socket that we're sending on
1166 * supports sendfile behavior. sockfs doesn't know that the APIs
1167 * we want to use are coming from sendfile, so we can't rely on
1168 * it to check for us.
1169 */
1170 if ((so->so_mode & SM_SENDFILESUPP) == 0) {
1171 error = EOPNOTSUPP;
1172 goto err;
1173 }
1174 break;
1175 case VREG:
1176 break;
1177 default:
1178 error = EINVAL;
1179 goto err;
1180 }
1181
1182 switch (opcode) {
1183 case SENDFILEV :
1184 break;
1185 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
1186 case SENDFILEV64 :
1187 return (sendvec64(fp, (struct ksendfilevec64 *)vec, sfvcnt,
1188 (size32_t *)xferred, fildes));
1189 #endif
1190 default :
1191 error = ENOSYS;
1192 break;
1193 }
|