aboutsummaryrefslogtreecommitdiffstats
path: root/net/rxrpc/recvmsg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rxrpc/recvmsg.c')
-rw-r--r--net/rxrpc/recvmsg.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 1edf2cf62cc5..8b8d7e14f800 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -134,6 +134,8 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call)
134{ 134{
135 _enter("%d,%s", call->debug_id, rxrpc_call_states[call->state]); 135 _enter("%d,%s", call->debug_id, rxrpc_call_states[call->state]);
136 136
137 ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
138
137 if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) { 139 if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
138 rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, 0, true, false); 140 rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, 0, true, false);
139 rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK); 141 rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK);
@@ -163,8 +165,10 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call)
163 */ 165 */
164static void rxrpc_rotate_rx_window(struct rxrpc_call *call) 166static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
165{ 167{
168 struct rxrpc_skb_priv *sp;
166 struct sk_buff *skb; 169 struct sk_buff *skb;
167 rxrpc_seq_t hard_ack, top; 170 rxrpc_seq_t hard_ack, top;
171 u8 flags;
168 int ix; 172 int ix;
169 173
170 _enter("%d", call->debug_id); 174 _enter("%d", call->debug_id);
@@ -177,6 +181,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
177 ix = hard_ack & RXRPC_RXTX_BUFF_MASK; 181 ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
178 skb = call->rxtx_buffer[ix]; 182 skb = call->rxtx_buffer[ix];
179 rxrpc_see_skb(skb); 183 rxrpc_see_skb(skb);
184 sp = rxrpc_skb(skb);
185 flags = sp->hdr.flags;
180 call->rxtx_buffer[ix] = NULL; 186 call->rxtx_buffer[ix] = NULL;
181 call->rxtx_annotations[ix] = 0; 187 call->rxtx_annotations[ix] = 0;
182 /* Barrier against rxrpc_input_data(). */ 188 /* Barrier against rxrpc_input_data(). */
@@ -184,8 +190,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
184 190
185 rxrpc_free_skb(skb); 191 rxrpc_free_skb(skb);
186 192
187 _debug("%u,%u,%lx", hard_ack, top, call->flags); 193 _debug("%u,%u,%02x", hard_ack, top, flags);
188 if (hard_ack == top && test_bit(RXRPC_CALL_RX_LAST, &call->flags)) 194 if (flags & RXRPC_LAST_PACKET)
189 rxrpc_end_rx_phase(call); 195 rxrpc_end_rx_phase(call);
190} 196}
191 197
@@ -278,13 +284,19 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
278 size_t remain; 284 size_t remain;
279 bool last; 285 bool last;
280 unsigned int rx_pkt_offset, rx_pkt_len; 286 unsigned int rx_pkt_offset, rx_pkt_len;
281 int ix, copy, ret = 0; 287 int ix, copy, ret = -EAGAIN, ret2;
282 288
283 _enter(""); 289 _enter("");
284 290
285 rx_pkt_offset = call->rx_pkt_offset; 291 rx_pkt_offset = call->rx_pkt_offset;
286 rx_pkt_len = call->rx_pkt_len; 292 rx_pkt_len = call->rx_pkt_len;
287 293
294 if (call->state >= RXRPC_CALL_SERVER_ACK_REQUEST) {
295 seq = call->rx_hard_ack;
296 ret = 1;
297 goto done;
298 }
299
288 /* Barriers against rxrpc_input_data(). */ 300 /* Barriers against rxrpc_input_data(). */
289 hard_ack = call->rx_hard_ack; 301 hard_ack = call->rx_hard_ack;
290 top = smp_load_acquire(&call->rx_top); 302 top = smp_load_acquire(&call->rx_top);
@@ -301,11 +313,13 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
301 sock_recv_timestamp(msg, sock->sk, skb); 313 sock_recv_timestamp(msg, sock->sk, skb);
302 314
303 if (rx_pkt_offset == 0) { 315 if (rx_pkt_offset == 0) {
304 ret = rxrpc_locate_data(call, skb, 316 ret2 = rxrpc_locate_data(call, skb,
305 &call->rxtx_annotations[ix], 317 &call->rxtx_annotations[ix],
306 &rx_pkt_offset, &rx_pkt_len); 318 &rx_pkt_offset, &rx_pkt_len);
307 if (ret < 0) 319 if (ret2 < 0) {
320 ret = ret2;
308 goto out; 321 goto out;
322 }
309 } 323 }
310 _debug("recvmsg %x DATA #%u { %d, %d }", 324 _debug("recvmsg %x DATA #%u { %d, %d }",
311 sp->hdr.callNumber, seq, rx_pkt_offset, rx_pkt_len); 325 sp->hdr.callNumber, seq, rx_pkt_offset, rx_pkt_len);
@@ -316,10 +330,12 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
316 if (copy > remain) 330 if (copy > remain)
317 copy = remain; 331 copy = remain;
318 if (copy > 0) { 332 if (copy > 0) {
319 ret = skb_copy_datagram_iter(skb, rx_pkt_offset, iter, 333 ret2 = skb_copy_datagram_iter(skb, rx_pkt_offset, iter,
320 copy); 334 copy);
321 if (ret < 0) 335 if (ret2 < 0) {
336 ret = ret2;
322 goto out; 337 goto out;
338 }
323 339
324 /* handle piecemeal consumption of data packets */ 340 /* handle piecemeal consumption of data packets */
325 _debug("copied %d @%zu", copy, *_offset); 341 _debug("copied %d @%zu", copy, *_offset);
@@ -332,6 +348,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
332 if (rx_pkt_len > 0) { 348 if (rx_pkt_len > 0) {
333 _debug("buffer full"); 349 _debug("buffer full");
334 ASSERTCMP(*_offset, ==, len); 350 ASSERTCMP(*_offset, ==, len);
351 ret = 0;
335 break; 352 break;
336 } 353 }
337 354
@@ -342,19 +359,19 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
342 rx_pkt_offset = 0; 359 rx_pkt_offset = 0;
343 rx_pkt_len = 0; 360 rx_pkt_len = 0;
344 361
345 ASSERTIFCMP(last, seq, ==, top); 362 if (last) {
346 } 363 ASSERTCMP(seq, ==, READ_ONCE(call->rx_top));
347
348 if (after(seq, top)) {
349 ret = -EAGAIN;
350 if (test_bit(RXRPC_CALL_RX_LAST, &call->flags))
351 ret = 1; 364 ret = 1;
365 goto out;
366 }
352 } 367 }
368
353out: 369out:
354 if (!(flags & MSG_PEEK)) { 370 if (!(flags & MSG_PEEK)) {
355 call->rx_pkt_offset = rx_pkt_offset; 371 call->rx_pkt_offset = rx_pkt_offset;
356 call->rx_pkt_len = rx_pkt_len; 372 call->rx_pkt_len = rx_pkt_len;
357 } 373 }
374done:
358 _leave(" = %d [%u/%u]", ret, seq, top); 375 _leave(" = %d [%u/%u]", ret, seq, top);
359 return ret; 376 return ret;
360} 377}