1/* 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 20 unchanged lines hidden (view full) --- 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 34 */ 35 36#include <sys/cdefs.h> |
37__FBSDID("$FreeBSD: head/sys/kern/uipc_socket.c 121628 2003-10-28 05:47:40Z sam $"); |
38 39#include "opt_inet.h" 40#include "opt_mac.h" 41#include "opt_zero.h" 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/fcntl.h> --- 837 unchanged lines hidden (view full) --- 883 goto release; 884 } 885 if (uio->uio_resid == 0) 886 goto release; 887 if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) { 888 error = EWOULDBLOCK; 889 goto release; 890 } |
891 SBLASTRECORDCHK(&so->so_rcv); 892 SBLASTMBUFCHK(&so->so_rcv); |
893 sbunlock(&so->so_rcv); 894 error = sbwait(&so->so_rcv); 895 splx(s); 896 if (error) 897 return (error); 898 goto restart; 899 } 900dontblock: 901 if (uio->uio_td) 902 uio->uio_td->td_proc->p_stats->p_ru.ru_msgrcv++; |
903 SBLASTRECORDCHK(&so->so_rcv); 904 SBLASTMBUFCHK(&so->so_rcv); |
905 nextrecord = m->m_nextpkt; 906 if (pr->pr_flags & PR_ADDR) { 907 KASSERT(m->m_type == MT_SONAME, 908 ("m->m_type == %d", m->m_type)); 909 orig_resid = 0; 910 if (psa) 911 *psa = dup_sockaddr(mtod(m, struct sockaddr *), 912 mp0 == 0); --- 25 unchanged lines hidden (view full) --- 938 } 939 if (controlp) { 940 orig_resid = 0; 941 while (*controlp != NULL) 942 controlp = &(*controlp)->m_next; 943 } 944 } 945 if (m) { |
946 if ((flags & MSG_PEEK) == 0) { |
947 m->m_nextpkt = nextrecord; |
948 /* 949 * If nextrecord == NULL (this is a single chain), 950 * then sb_lastrecord may not be valid here if m 951 * was changed earlier. 952 */ 953 if (nextrecord == NULL) { 954 KASSERT(so->so_rcv.sb_mb == m, 955 ("receive tailq 1")); 956 so->so_rcv.sb_lastrecord = m; 957 } 958 } |
959 type = m->m_type; 960 if (type == MT_OOBDATA) 961 flags |= MSG_OOB; |
962 } else { 963 if ((flags & MSG_PEEK) == 0) { 964 KASSERT(so->so_rcv.sb_mb == m,("receive tailq 2")); 965 so->so_rcv.sb_mb = nextrecord; 966 SB_EMPTY_FIXUP(&so->so_rcv); 967 } |
968 } |
969 SBLASTRECORDCHK(&so->so_rcv); 970 SBLASTMBUFCHK(&so->so_rcv); 971 |
972 moff = 0; 973 offset = 0; 974 while (m && uio->uio_resid > 0 && error == 0) { 975 if (m->m_type == MT_OOBDATA) { 976 if (type != MT_OOBDATA) 977 break; 978 } else if (type == MT_OOBDATA) 979 break; --- 10 unchanged lines hidden (view full) --- 990 * If mp is set, just pass back the mbufs. 991 * Otherwise copy them out via the uio, then free. 992 * Sockbuf must be consistent here (points to current mbuf, 993 * it points to next record) when we drop priority; 994 * we must note any additions to the sockbuf when we 995 * block interrupts again. 996 */ 997 if (mp == 0) { |
998 SBLASTRECORDCHK(&so->so_rcv); 999 SBLASTMBUFCHK(&so->so_rcv); |
1000 splx(s); 1001#ifdef ZERO_COPY_SOCKETS 1002 if (so_zero_copy_receive) { 1003 vm_page_t pg; 1004 int disposable; 1005 1006 if ((m->m_flags & M_EXT) 1007 && (m->m_ext.ext_type == EXT_DISPOSABLE)) --- 31 unchanged lines hidden (view full) --- 1039 *mp = m; 1040 mp = &m->m_next; 1041 so->so_rcv.sb_mb = m = m->m_next; 1042 *mp = (struct mbuf *)0; 1043 } else { 1044 so->so_rcv.sb_mb = m_free(m); 1045 m = so->so_rcv.sb_mb; 1046 } |
1047 if (m) { |
1048 m->m_nextpkt = nextrecord; |
1049 if (nextrecord == NULL) 1050 so->so_rcv.sb_lastrecord = m; 1051 } else { 1052 so->so_rcv.sb_mb = nextrecord; 1053 SB_EMPTY_FIXUP(&so->so_rcv); 1054 } 1055 SBLASTRECORDCHK(&so->so_rcv); 1056 SBLASTMBUFCHK(&so->so_rcv); |
1057 } 1058 } else { 1059 if (flags & MSG_PEEK) 1060 moff += len; 1061 else { 1062 if (mp) 1063 *mp = m_copym(m, 0, len, M_TRYWAIT); 1064 m->m_data += len; --- 28 unchanged lines hidden (view full) --- 1093 if (so->so_error || so->so_state & SS_CANTRCVMORE) 1094 break; 1095 /* 1096 * Notify the protocol that some data has been 1097 * drained before blocking. 1098 */ 1099 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 1100 (*pr->pr_usrreqs->pru_rcvd)(so, flags); |
1101 SBLASTRECORDCHK(&so->so_rcv); 1102 SBLASTMBUFCHK(&so->so_rcv); |
1103 error = sbwait(&so->so_rcv); 1104 if (error) { 1105 sbunlock(&so->so_rcv); 1106 splx(s); 1107 return (0); 1108 } 1109 m = so->so_rcv.sb_mb; 1110 if (m) 1111 nextrecord = m->m_nextpkt; 1112 } 1113 } 1114 1115 if (m && pr->pr_flags & PR_ATOMIC) { 1116 flags |= MSG_TRUNC; 1117 if ((flags & MSG_PEEK) == 0) 1118 (void) sbdroprecord(&so->so_rcv); 1119 } 1120 if ((flags & MSG_PEEK) == 0) { |
1121 if (m == 0) { 1122 /* 1123 * First part is an inline SB_EMPTY_FIXUP(). Second 1124 * part makes sure sb_lastrecord is up-to-date if 1125 * there is still data in the socket buffer. 1126 */ |
1127 so->so_rcv.sb_mb = nextrecord; |
1128 if (so->so_rcv.sb_mb == NULL) { 1129 so->so_rcv.sb_mbtail = NULL; 1130 so->so_rcv.sb_lastrecord = NULL; 1131 } else if (nextrecord->m_nextpkt == NULL) 1132 so->so_rcv.sb_lastrecord = nextrecord; 1133 } 1134 SBLASTRECORDCHK(&so->so_rcv); 1135 SBLASTMBUFCHK(&so->so_rcv); |
1136 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 1137 (*pr->pr_usrreqs->pru_rcvd)(so, flags); 1138 } 1139 if (orig_resid == uio->uio_resid && orig_resid && 1140 (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { 1141 sbunlock(&so->so_rcv); 1142 splx(s); 1143 goto restart; --- 763 unchanged lines hidden --- |