diff options
Diffstat (limited to 'fs/afs/rxrpc.c')
-rw-r--r-- | fs/afs/rxrpc.c | 137 |
1 files changed, 107 insertions, 30 deletions
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index b92774231b3c..e86c527d87a1 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
@@ -17,6 +17,8 @@ | |||
17 | 17 | ||
18 | static struct socket *afs_socket; /* my RxRPC socket */ | 18 | static struct socket *afs_socket; /* my RxRPC socket */ |
19 | static struct workqueue_struct *afs_async_calls; | 19 | static struct workqueue_struct *afs_async_calls; |
20 | static atomic_t afs_outstanding_calls; | ||
21 | static atomic_t afs_outstanding_skbs; | ||
20 | 22 | ||
21 | static void afs_wake_up_call_waiter(struct afs_call *); | 23 | static void afs_wake_up_call_waiter(struct afs_call *); |
22 | static int afs_wait_for_call_to_complete(struct afs_call *); | 24 | static int afs_wait_for_call_to_complete(struct afs_call *); |
@@ -45,6 +47,7 @@ static const struct afs_wait_mode afs_async_incoming_call = { | |||
45 | 47 | ||
46 | /* asynchronous incoming call initial processing */ | 48 | /* asynchronous incoming call initial processing */ |
47 | static const struct afs_call_type afs_RXCMxxxx = { | 49 | static const struct afs_call_type afs_RXCMxxxx = { |
50 | .name = "CB.xxxx", | ||
48 | .deliver = afs_deliver_cm_op_id, | 51 | .deliver = afs_deliver_cm_op_id, |
49 | .abort_to_error = afs_abort_to_error, | 52 | .abort_to_error = afs_abort_to_error, |
50 | }; | 53 | }; |
@@ -118,10 +121,67 @@ void afs_close_socket(void) | |||
118 | 121 | ||
119 | _debug("dework"); | 122 | _debug("dework"); |
120 | destroy_workqueue(afs_async_calls); | 123 | destroy_workqueue(afs_async_calls); |
124 | |||
125 | ASSERTCMP(atomic_read(&afs_outstanding_skbs), ==, 0); | ||
126 | ASSERTCMP(atomic_read(&afs_outstanding_calls), ==, 0); | ||
121 | _leave(""); | 127 | _leave(""); |
122 | } | 128 | } |
123 | 129 | ||
124 | /* | 130 | /* |
131 | * note that the data in a socket buffer is now delivered and that the buffer | ||
132 | * should be freed | ||
133 | */ | ||
134 | static void afs_data_delivered(struct sk_buff *skb) | ||
135 | { | ||
136 | if (!skb) { | ||
137 | _debug("DLVR NULL [%d]", atomic_read(&afs_outstanding_skbs)); | ||
138 | dump_stack(); | ||
139 | } else { | ||
140 | _debug("DLVR %p{%u} [%d]", | ||
141 | skb, skb->mark, atomic_read(&afs_outstanding_skbs)); | ||
142 | if (atomic_dec_return(&afs_outstanding_skbs) == -1) | ||
143 | BUG(); | ||
144 | rxrpc_kernel_data_delivered(skb); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * free a socket buffer | ||
150 | */ | ||
151 | static void afs_free_skb(struct sk_buff *skb) | ||
152 | { | ||
153 | if (!skb) { | ||
154 | _debug("FREE NULL [%d]", atomic_read(&afs_outstanding_skbs)); | ||
155 | dump_stack(); | ||
156 | } else { | ||
157 | _debug("FREE %p{%u} [%d]", | ||
158 | skb, skb->mark, atomic_read(&afs_outstanding_skbs)); | ||
159 | if (atomic_dec_return(&afs_outstanding_skbs) == -1) | ||
160 | BUG(); | ||
161 | rxrpc_kernel_free_skb(skb); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * free a call | ||
167 | */ | ||
168 | static void afs_free_call(struct afs_call *call) | ||
169 | { | ||
170 | _debug("DONE %p{%s} [%d]", | ||
171 | call, call->type->name, atomic_read(&afs_outstanding_calls)); | ||
172 | if (atomic_dec_return(&afs_outstanding_calls) == -1) | ||
173 | BUG(); | ||
174 | |||
175 | ASSERTCMP(call->rxcall, ==, NULL); | ||
176 | ASSERT(!work_pending(&call->async_work)); | ||
177 | ASSERT(skb_queue_empty(&call->rx_queue)); | ||
178 | ASSERT(call->type->name != NULL); | ||
179 | |||
180 | kfree(call->request); | ||
181 | kfree(call); | ||
182 | } | ||
183 | |||
184 | /* | ||
125 | * allocate a call with flat request and reply buffers | 185 | * allocate a call with flat request and reply buffers |
126 | */ | 186 | */ |
127 | struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type, | 187 | struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type, |
@@ -133,30 +193,32 @@ struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type, | |||
133 | if (!call) | 193 | if (!call) |
134 | goto nomem_call; | 194 | goto nomem_call; |
135 | 195 | ||
196 | _debug("CALL %p{%s} [%d]", | ||
197 | call, type->name, atomic_read(&afs_outstanding_calls)); | ||
198 | atomic_inc(&afs_outstanding_calls); | ||
199 | |||
200 | call->type = type; | ||
201 | call->request_size = request_size; | ||
202 | call->reply_max = reply_size; | ||
203 | |||
136 | if (request_size) { | 204 | if (request_size) { |
137 | call->request = kmalloc(request_size, GFP_NOFS); | 205 | call->request = kmalloc(request_size, GFP_NOFS); |
138 | if (!call->request) | 206 | if (!call->request) |
139 | goto nomem_request; | 207 | goto nomem_free; |
140 | } | 208 | } |
141 | 209 | ||
142 | if (reply_size) { | 210 | if (reply_size) { |
143 | call->buffer = kmalloc(reply_size, GFP_NOFS); | 211 | call->buffer = kmalloc(reply_size, GFP_NOFS); |
144 | if (!call->buffer) | 212 | if (!call->buffer) |
145 | goto nomem_buffer; | 213 | goto nomem_free; |
146 | } | 214 | } |
147 | 215 | ||
148 | call->type = type; | ||
149 | call->request_size = request_size; | ||
150 | call->reply_max = reply_size; | ||
151 | |||
152 | init_waitqueue_head(&call->waitq); | 216 | init_waitqueue_head(&call->waitq); |
153 | skb_queue_head_init(&call->rx_queue); | 217 | skb_queue_head_init(&call->rx_queue); |
154 | return call; | 218 | return call; |
155 | 219 | ||
156 | nomem_buffer: | 220 | nomem_free: |
157 | kfree(call->request); | 221 | afs_free_call(call); |
158 | nomem_request: | ||
159 | kfree(call); | ||
160 | nomem_call: | 222 | nomem_call: |
161 | return NULL; | 223 | return NULL; |
162 | } | 224 | } |
@@ -188,6 +250,12 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, | |||
188 | 250 | ||
189 | _enter("%x,{%d},", addr->s_addr, ntohs(call->port)); | 251 | _enter("%x,{%d},", addr->s_addr, ntohs(call->port)); |
190 | 252 | ||
253 | ASSERT(call->type != NULL); | ||
254 | ASSERT(call->type->name != NULL); | ||
255 | |||
256 | _debug("MAKE %p{%s} [%d]", | ||
257 | call, call->type->name, atomic_read(&afs_outstanding_calls)); | ||
258 | |||
191 | call->wait_mode = wait_mode; | 259 | call->wait_mode = wait_mode; |
192 | INIT_WORK(&call->async_work, afs_process_async_call); | 260 | INIT_WORK(&call->async_work, afs_process_async_call); |
193 | 261 | ||
@@ -203,6 +271,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, | |||
203 | /* create a call */ | 271 | /* create a call */ |
204 | rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key, | 272 | rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key, |
205 | (unsigned long) call, gfp); | 273 | (unsigned long) call, gfp); |
274 | call->key = NULL; | ||
206 | if (IS_ERR(rxcall)) { | 275 | if (IS_ERR(rxcall)) { |
207 | ret = PTR_ERR(rxcall); | 276 | ret = PTR_ERR(rxcall); |
208 | goto error_kill_call; | 277 | goto error_kill_call; |
@@ -237,10 +306,10 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, | |||
237 | error_do_abort: | 306 | error_do_abort: |
238 | rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT); | 307 | rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT); |
239 | rxrpc_kernel_end_call(rxcall); | 308 | rxrpc_kernel_end_call(rxcall); |
309 | call->rxcall = NULL; | ||
240 | error_kill_call: | 310 | error_kill_call: |
241 | call->type->destructor(call); | 311 | call->type->destructor(call); |
242 | ASSERT(skb_queue_empty(&call->rx_queue)); | 312 | afs_free_call(call); |
243 | kfree(call); | ||
244 | _leave(" = %d", ret); | 313 | _leave(" = %d", ret); |
245 | return ret; | 314 | return ret; |
246 | } | 315 | } |
@@ -257,15 +326,19 @@ static void afs_rx_interceptor(struct sock *sk, unsigned long user_call_ID, | |||
257 | 326 | ||
258 | _enter("%p,,%u", call, skb->mark); | 327 | _enter("%p,,%u", call, skb->mark); |
259 | 328 | ||
329 | _debug("ICPT %p{%u} [%d]", | ||
330 | skb, skb->mark, atomic_read(&afs_outstanding_skbs)); | ||
331 | |||
260 | ASSERTCMP(sk, ==, afs_socket->sk); | 332 | ASSERTCMP(sk, ==, afs_socket->sk); |
333 | atomic_inc(&afs_outstanding_skbs); | ||
261 | 334 | ||
262 | if (!call) { | 335 | if (!call) { |
263 | /* its an incoming call for our callback service */ | 336 | /* its an incoming call for our callback service */ |
264 | __skb_queue_tail(&afs_incoming_calls, skb); | 337 | skb_queue_tail(&afs_incoming_calls, skb); |
265 | schedule_work(&afs_collect_incoming_call_work); | 338 | schedule_work(&afs_collect_incoming_call_work); |
266 | } else { | 339 | } else { |
267 | /* route the messages directly to the appropriate call */ | 340 | /* route the messages directly to the appropriate call */ |
268 | __skb_queue_tail(&call->rx_queue, skb); | 341 | skb_queue_tail(&call->rx_queue, skb); |
269 | call->wait_mode->rx_wakeup(call); | 342 | call->wait_mode->rx_wakeup(call); |
270 | } | 343 | } |
271 | 344 | ||
@@ -317,9 +390,9 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
317 | call->state = AFS_CALL_ERROR; | 390 | call->state = AFS_CALL_ERROR; |
318 | break; | 391 | break; |
319 | } | 392 | } |
320 | rxrpc_kernel_data_delivered(skb); | 393 | afs_data_delivered(skb); |
321 | skb = NULL; | 394 | skb = NULL; |
322 | break; | 395 | continue; |
323 | case RXRPC_SKB_MARK_FINAL_ACK: | 396 | case RXRPC_SKB_MARK_FINAL_ACK: |
324 | _debug("Rcv ACK"); | 397 | _debug("Rcv ACK"); |
325 | call->state = AFS_CALL_COMPLETE; | 398 | call->state = AFS_CALL_COMPLETE; |
@@ -350,19 +423,19 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
350 | break; | 423 | break; |
351 | } | 424 | } |
352 | 425 | ||
353 | rxrpc_kernel_free_skb(skb); | 426 | afs_free_skb(skb); |
354 | } | 427 | } |
355 | 428 | ||
356 | /* make sure the queue is empty if the call is done with (we might have | 429 | /* make sure the queue is empty if the call is done with (we might have |
357 | * aborted the call early because of an unmarshalling error) */ | 430 | * aborted the call early because of an unmarshalling error) */ |
358 | if (call->state >= AFS_CALL_COMPLETE) { | 431 | if (call->state >= AFS_CALL_COMPLETE) { |
359 | while ((skb = skb_dequeue(&call->rx_queue))) | 432 | while ((skb = skb_dequeue(&call->rx_queue))) |
360 | rxrpc_kernel_free_skb(skb); | 433 | afs_free_skb(skb); |
361 | if (call->incoming) { | 434 | if (call->incoming) { |
362 | rxrpc_kernel_end_call(call->rxcall); | 435 | rxrpc_kernel_end_call(call->rxcall); |
436 | call->rxcall = NULL; | ||
363 | call->type->destructor(call); | 437 | call->type->destructor(call); |
364 | ASSERT(skb_queue_empty(&call->rx_queue)); | 438 | afs_free_call(call); |
365 | kfree(call); | ||
366 | } | 439 | } |
367 | } | 440 | } |
368 | 441 | ||
@@ -409,14 +482,14 @@ static int afs_wait_for_call_to_complete(struct afs_call *call) | |||
409 | _debug("call incomplete"); | 482 | _debug("call incomplete"); |
410 | rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD); | 483 | rxrpc_kernel_abort_call(call->rxcall, RX_CALL_DEAD); |
411 | while ((skb = skb_dequeue(&call->rx_queue))) | 484 | while ((skb = skb_dequeue(&call->rx_queue))) |
412 | rxrpc_kernel_free_skb(skb); | 485 | afs_free_skb(skb); |
413 | } | 486 | } |
414 | 487 | ||
415 | _debug("call complete"); | 488 | _debug("call complete"); |
416 | rxrpc_kernel_end_call(call->rxcall); | 489 | rxrpc_kernel_end_call(call->rxcall); |
490 | call->rxcall = NULL; | ||
417 | call->type->destructor(call); | 491 | call->type->destructor(call); |
418 | ASSERT(skb_queue_empty(&call->rx_queue)); | 492 | afs_free_call(call); |
419 | kfree(call); | ||
420 | _leave(" = %d", ret); | 493 | _leave(" = %d", ret); |
421 | return ret; | 494 | return ret; |
422 | } | 495 | } |
@@ -459,9 +532,7 @@ static void afs_delete_async_call(struct work_struct *work) | |||
459 | 532 | ||
460 | _enter(""); | 533 | _enter(""); |
461 | 534 | ||
462 | ASSERT(skb_queue_empty(&call->rx_queue)); | 535 | afs_free_call(call); |
463 | ASSERT(!work_pending(&call->async_work)); | ||
464 | kfree(call); | ||
465 | 536 | ||
466 | _leave(""); | 537 | _leave(""); |
467 | } | 538 | } |
@@ -489,6 +560,7 @@ static void afs_process_async_call(struct work_struct *work) | |||
489 | 560 | ||
490 | /* kill the call */ | 561 | /* kill the call */ |
491 | rxrpc_kernel_end_call(call->rxcall); | 562 | rxrpc_kernel_end_call(call->rxcall); |
563 | call->rxcall = NULL; | ||
492 | if (call->type->destructor) | 564 | if (call->type->destructor) |
493 | call->type->destructor(call); | 565 | call->type->destructor(call); |
494 | 566 | ||
@@ -526,7 +598,7 @@ static void afs_collect_incoming_call(struct work_struct *work) | |||
526 | _debug("new call"); | 598 | _debug("new call"); |
527 | 599 | ||
528 | /* don't need the notification */ | 600 | /* don't need the notification */ |
529 | rxrpc_kernel_free_skb(skb); | 601 | afs_free_skb(skb); |
530 | 602 | ||
531 | if (!call) { | 603 | if (!call) { |
532 | call = kzalloc(sizeof(struct afs_call), GFP_KERNEL); | 604 | call = kzalloc(sizeof(struct afs_call), GFP_KERNEL); |
@@ -541,6 +613,11 @@ static void afs_collect_incoming_call(struct work_struct *work) | |||
541 | init_waitqueue_head(&call->waitq); | 613 | init_waitqueue_head(&call->waitq); |
542 | skb_queue_head_init(&call->rx_queue); | 614 | skb_queue_head_init(&call->rx_queue); |
543 | call->state = AFS_CALL_AWAIT_OP_ID; | 615 | call->state = AFS_CALL_AWAIT_OP_ID; |
616 | |||
617 | _debug("CALL %p{%s} [%d]", | ||
618 | call, call->type->name, | ||
619 | atomic_read(&afs_outstanding_calls)); | ||
620 | atomic_inc(&afs_outstanding_calls); | ||
544 | } | 621 | } |
545 | 622 | ||
546 | rxcall = rxrpc_kernel_accept_call(afs_socket, | 623 | rxcall = rxrpc_kernel_accept_call(afs_socket, |
@@ -551,7 +628,8 @@ static void afs_collect_incoming_call(struct work_struct *work) | |||
551 | } | 628 | } |
552 | } | 629 | } |
553 | 630 | ||
554 | kfree(call); | 631 | if (call) |
632 | afs_free_call(call); | ||
555 | } | 633 | } |
556 | 634 | ||
557 | /* | 635 | /* |
@@ -629,8 +707,7 @@ void afs_send_empty_reply(struct afs_call *call) | |||
629 | rxrpc_kernel_end_call(call->rxcall); | 707 | rxrpc_kernel_end_call(call->rxcall); |
630 | call->rxcall = NULL; | 708 | call->rxcall = NULL; |
631 | call->type->destructor(call); | 709 | call->type->destructor(call); |
632 | ASSERT(skb_queue_empty(&call->rx_queue)); | 710 | afs_free_call(call); |
633 | kfree(call); | ||
634 | _leave(" [error]"); | 711 | _leave(" [error]"); |
635 | return; | 712 | return; |
636 | } | 713 | } |