diff options
Diffstat (limited to 'fs/afs/rxrpc.c')
-rw-r--r-- | fs/afs/rxrpc.c | 73 |
1 files changed, 45 insertions, 28 deletions
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 4832de84d52c..14d04c848465 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
@@ -150,10 +150,9 @@ void afs_close_socket(void) | |||
150 | } | 150 | } |
151 | 151 | ||
152 | /* | 152 | /* |
153 | * note that the data in a socket buffer is now delivered and that the buffer | 153 | * Note that the data in a socket buffer is now consumed. |
154 | * should be freed | ||
155 | */ | 154 | */ |
156 | static void afs_data_delivered(struct sk_buff *skb) | 155 | void afs_data_consumed(struct afs_call *call, struct sk_buff *skb) |
157 | { | 156 | { |
158 | if (!skb) { | 157 | if (!skb) { |
159 | _debug("DLVR NULL [%d]", atomic_read(&afs_outstanding_skbs)); | 158 | _debug("DLVR NULL [%d]", atomic_read(&afs_outstanding_skbs)); |
@@ -161,9 +160,7 @@ static void afs_data_delivered(struct sk_buff *skb) | |||
161 | } else { | 160 | } else { |
162 | _debug("DLVR %p{%u} [%d]", | 161 | _debug("DLVR %p{%u} [%d]", |
163 | skb, skb->mark, atomic_read(&afs_outstanding_skbs)); | 162 | skb, skb->mark, atomic_read(&afs_outstanding_skbs)); |
164 | if (atomic_dec_return(&afs_outstanding_skbs) == -1) | 163 | rxrpc_kernel_data_consumed(call->rxcall, skb); |
165 | BUG(); | ||
166 | rxrpc_kernel_data_delivered(skb); | ||
167 | } | 164 | } |
168 | } | 165 | } |
169 | 166 | ||
@@ -489,9 +486,15 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
489 | last = rxrpc_kernel_is_data_last(skb); | 486 | last = rxrpc_kernel_is_data_last(skb); |
490 | ret = call->type->deliver(call, skb, last); | 487 | ret = call->type->deliver(call, skb, last); |
491 | switch (ret) { | 488 | switch (ret) { |
489 | case -EAGAIN: | ||
490 | if (last) { | ||
491 | _debug("short data"); | ||
492 | goto unmarshal_error; | ||
493 | } | ||
494 | break; | ||
492 | case 0: | 495 | case 0: |
493 | if (last && | 496 | ASSERT(last); |
494 | call->state == AFS_CALL_AWAIT_REPLY) | 497 | if (call->state == AFS_CALL_AWAIT_REPLY) |
495 | call->state = AFS_CALL_COMPLETE; | 498 | call->state = AFS_CALL_COMPLETE; |
496 | break; | 499 | break; |
497 | case -ENOTCONN: | 500 | case -ENOTCONN: |
@@ -501,6 +504,7 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
501 | abort_code = RX_INVALID_OPERATION; | 504 | abort_code = RX_INVALID_OPERATION; |
502 | goto do_abort; | 505 | goto do_abort; |
503 | default: | 506 | default: |
507 | unmarshal_error: | ||
504 | abort_code = RXGEN_CC_UNMARSHAL; | 508 | abort_code = RXGEN_CC_UNMARSHAL; |
505 | if (call->state != AFS_CALL_AWAIT_REPLY) | 509 | if (call->state != AFS_CALL_AWAIT_REPLY) |
506 | abort_code = RXGEN_SS_UNMARSHAL; | 510 | abort_code = RXGEN_SS_UNMARSHAL; |
@@ -511,9 +515,7 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
511 | call->state = AFS_CALL_ERROR; | 515 | call->state = AFS_CALL_ERROR; |
512 | break; | 516 | break; |
513 | } | 517 | } |
514 | afs_data_delivered(skb); | 518 | break; |
515 | skb = NULL; | ||
516 | continue; | ||
517 | case RXRPC_SKB_MARK_FINAL_ACK: | 519 | case RXRPC_SKB_MARK_FINAL_ACK: |
518 | _debug("Rcv ACK"); | 520 | _debug("Rcv ACK"); |
519 | call->state = AFS_CALL_COMPLETE; | 521 | call->state = AFS_CALL_COMPLETE; |
@@ -685,15 +687,35 @@ static void afs_process_async_call(struct afs_call *call) | |||
685 | } | 687 | } |
686 | 688 | ||
687 | /* | 689 | /* |
688 | * empty a socket buffer into a flat reply buffer | 690 | * Empty a socket buffer into a flat reply buffer. |
689 | */ | 691 | */ |
690 | void afs_transfer_reply(struct afs_call *call, struct sk_buff *skb) | 692 | int afs_transfer_reply(struct afs_call *call, struct sk_buff *skb, bool last) |
691 | { | 693 | { |
692 | size_t len = skb->len; | 694 | size_t len = skb->len; |
693 | 695 | ||
694 | if (skb_copy_bits(skb, 0, call->buffer + call->reply_size, len) < 0) | 696 | if (len > call->reply_max - call->reply_size) { |
695 | BUG(); | 697 | _leave(" = -EBADMSG [%zu > %u]", |
696 | call->reply_size += len; | 698 | len, call->reply_max - call->reply_size); |
699 | return -EBADMSG; | ||
700 | } | ||
701 | |||
702 | if (len > 0) { | ||
703 | if (skb_copy_bits(skb, 0, call->buffer + call->reply_size, | ||
704 | len) < 0) | ||
705 | BUG(); | ||
706 | call->reply_size += len; | ||
707 | } | ||
708 | |||
709 | afs_data_consumed(call, skb); | ||
710 | if (!last) | ||
711 | return -EAGAIN; | ||
712 | |||
713 | if (call->reply_size != call->reply_max) { | ||
714 | _leave(" = -EBADMSG [%u != %u]", | ||
715 | call->reply_size, call->reply_max); | ||
716 | return -EBADMSG; | ||
717 | } | ||
718 | return 0; | ||
697 | } | 719 | } |
698 | 720 | ||
699 | /* | 721 | /* |
@@ -745,7 +767,8 @@ static void afs_collect_incoming_call(struct work_struct *work) | |||
745 | } | 767 | } |
746 | 768 | ||
747 | /* | 769 | /* |
748 | * grab the operation ID from an incoming cache manager call | 770 | * Grab the operation ID from an incoming cache manager call. The socket |
771 | * buffer is discarded on error or if we don't yet have sufficient data. | ||
749 | */ | 772 | */ |
750 | static int afs_deliver_cm_op_id(struct afs_call *call, struct sk_buff *skb, | 773 | static int afs_deliver_cm_op_id(struct afs_call *call, struct sk_buff *skb, |
751 | bool last) | 774 | bool last) |
@@ -766,12 +789,9 @@ static int afs_deliver_cm_op_id(struct afs_call *call, struct sk_buff *skb, | |||
766 | call->offset += len; | 789 | call->offset += len; |
767 | 790 | ||
768 | if (call->offset < 4) { | 791 | if (call->offset < 4) { |
769 | if (last) { | 792 | afs_data_consumed(call, skb); |
770 | _leave(" = -EBADMSG [op ID short]"); | 793 | _leave(" = -EAGAIN"); |
771 | return -EBADMSG; | 794 | return -EAGAIN; |
772 | } | ||
773 | _leave(" = 0 [incomplete]"); | ||
774 | return 0; | ||
775 | } | 795 | } |
776 | 796 | ||
777 | call->state = AFS_CALL_AWAIT_REQUEST; | 797 | call->state = AFS_CALL_AWAIT_REQUEST; |
@@ -855,7 +875,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) | |||
855 | } | 875 | } |
856 | 876 | ||
857 | /* | 877 | /* |
858 | * extract a piece of data from the received data socket buffers | 878 | * Extract a piece of data from the received data socket buffers. |
859 | */ | 879 | */ |
860 | int afs_extract_data(struct afs_call *call, struct sk_buff *skb, | 880 | int afs_extract_data(struct afs_call *call, struct sk_buff *skb, |
861 | bool last, void *buf, size_t count) | 881 | bool last, void *buf, size_t count) |
@@ -873,10 +893,7 @@ int afs_extract_data(struct afs_call *call, struct sk_buff *skb, | |||
873 | call->offset += len; | 893 | call->offset += len; |
874 | 894 | ||
875 | if (call->offset < count) { | 895 | if (call->offset < count) { |
876 | if (last) { | 896 | afs_data_consumed(call, skb); |
877 | _leave(" = -EBADMSG [%d < %zu]", call->offset, count); | ||
878 | return -EBADMSG; | ||
879 | } | ||
880 | _leave(" = -EAGAIN"); | 897 | _leave(" = -EAGAIN"); |
881 | return -EAGAIN; | 898 | return -EAGAIN; |
882 | } | 899 | } |