diff options
Diffstat (limited to 'net/rxrpc/skbuff.c')
-rw-r--r-- | net/rxrpc/skbuff.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c index eee0cfd9ac8c..06c51d4b622d 100644 --- a/net/rxrpc/skbuff.c +++ b/net/rxrpc/skbuff.c | |||
@@ -98,11 +98,39 @@ static void rxrpc_hard_ACK_data(struct rxrpc_call *call, | |||
98 | spin_unlock_bh(&call->lock); | 98 | spin_unlock_bh(&call->lock); |
99 | } | 99 | } |
100 | 100 | ||
101 | /** | ||
102 | * rxrpc_kernel_data_consumed - Record consumption of data message | ||
103 | * @call: The call to which the message pertains. | ||
104 | * @skb: Message holding data | ||
105 | * | ||
106 | * Record the consumption of a data message and generate an ACK if appropriate. | ||
107 | * The call state is shifted if this was the final packet. The caller must be | ||
108 | * in process context with no spinlocks held. | ||
109 | * | ||
110 | * TODO: Actually generate the ACK here rather than punting this to the | ||
111 | * workqueue. | ||
112 | */ | ||
113 | void rxrpc_kernel_data_consumed(struct rxrpc_call *call, struct sk_buff *skb) | ||
114 | { | ||
115 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | ||
116 | |||
117 | _enter("%d,%p{%u}", call->debug_id, skb, sp->hdr.seq); | ||
118 | |||
119 | ASSERTCMP(sp->call, ==, call); | ||
120 | ASSERTCMP(sp->hdr.type, ==, RXRPC_PACKET_TYPE_DATA); | ||
121 | |||
122 | /* TODO: Fix the sequence number tracking */ | ||
123 | ASSERTCMP(sp->hdr.seq, >=, call->rx_data_recv); | ||
124 | ASSERTCMP(sp->hdr.seq, <=, call->rx_data_recv + 1); | ||
125 | ASSERTCMP(sp->hdr.seq, >, call->rx_data_eaten); | ||
126 | |||
127 | call->rx_data_recv = sp->hdr.seq; | ||
128 | rxrpc_hard_ACK_data(call, sp); | ||
129 | } | ||
130 | EXPORT_SYMBOL(rxrpc_kernel_data_consumed); | ||
131 | |||
101 | /* | 132 | /* |
102 | * destroy a packet that has an RxRPC control buffer | 133 | * Destroy a packet that has an RxRPC control buffer |
103 | * - advance the hard-ACK state of the parent call (done here in case something | ||
104 | * in the kernel bypasses recvmsg() and steals the packet directly off of the | ||
105 | * socket receive queue) | ||
106 | */ | 134 | */ |
107 | void rxrpc_packet_destructor(struct sk_buff *skb) | 135 | void rxrpc_packet_destructor(struct sk_buff *skb) |
108 | { | 136 | { |
@@ -112,9 +140,8 @@ void rxrpc_packet_destructor(struct sk_buff *skb) | |||
112 | _enter("%p{%p}", skb, call); | 140 | _enter("%p{%p}", skb, call); |
113 | 141 | ||
114 | if (call) { | 142 | if (call) { |
115 | /* send the final ACK on a client call */ | 143 | if (atomic_dec_return(&call->skb_count) < 0) |
116 | if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA) | 144 | BUG(); |
117 | rxrpc_hard_ACK_data(call, sp); | ||
118 | rxrpc_put_call(call); | 145 | rxrpc_put_call(call); |
119 | sp->call = NULL; | 146 | sp->call = NULL; |
120 | } | 147 | } |