diff options
Diffstat (limited to 'net/rxrpc/ar-accept.c')
-rw-r--r-- | net/rxrpc/ar-accept.c | 119 |
1 files changed, 112 insertions, 7 deletions
diff --git a/net/rxrpc/ar-accept.c b/net/rxrpc/ar-accept.c index e7af780cd6f9..92a87fde8bfe 100644 --- a/net/rxrpc/ar-accept.c +++ b/net/rxrpc/ar-accept.c | |||
@@ -139,7 +139,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, | |||
139 | call->conn->state = RXRPC_CONN_SERVER_CHALLENGING; | 139 | call->conn->state = RXRPC_CONN_SERVER_CHALLENGING; |
140 | atomic_inc(&call->conn->usage); | 140 | atomic_inc(&call->conn->usage); |
141 | set_bit(RXRPC_CONN_CHALLENGE, &call->conn->events); | 141 | set_bit(RXRPC_CONN_CHALLENGE, &call->conn->events); |
142 | schedule_work(&call->conn->processor); | 142 | rxrpc_queue_conn(call->conn); |
143 | } else { | 143 | } else { |
144 | _debug("conn ready"); | 144 | _debug("conn ready"); |
145 | call->state = RXRPC_CALL_SERVER_ACCEPTING; | 145 | call->state = RXRPC_CALL_SERVER_ACCEPTING; |
@@ -183,7 +183,7 @@ invalid_service: | |||
183 | if (!test_bit(RXRPC_CALL_RELEASE, &call->flags) && | 183 | if (!test_bit(RXRPC_CALL_RELEASE, &call->flags) && |
184 | !test_and_set_bit(RXRPC_CALL_RELEASE, &call->events)) { | 184 | !test_and_set_bit(RXRPC_CALL_RELEASE, &call->events)) { |
185 | rxrpc_get_call(call); | 185 | rxrpc_get_call(call); |
186 | schedule_work(&call->processor); | 186 | rxrpc_queue_call(call); |
187 | } | 187 | } |
188 | read_unlock_bh(&call->state_lock); | 188 | read_unlock_bh(&call->state_lock); |
189 | rxrpc_put_call(call); | 189 | rxrpc_put_call(call); |
@@ -310,7 +310,8 @@ security_mismatch: | |||
310 | * handle acceptance of a call by userspace | 310 | * handle acceptance of a call by userspace |
311 | * - assign the user call ID to the call at the front of the queue | 311 | * - assign the user call ID to the call at the front of the queue |
312 | */ | 312 | */ |
313 | int rxrpc_accept_call(struct rxrpc_sock *rx, unsigned long user_call_ID) | 313 | struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx, |
314 | unsigned long user_call_ID) | ||
314 | { | 315 | { |
315 | struct rxrpc_call *call; | 316 | struct rxrpc_call *call; |
316 | struct rb_node *parent, **pp; | 317 | struct rb_node *parent, **pp; |
@@ -374,12 +375,76 @@ int rxrpc_accept_call(struct rxrpc_sock *rx, unsigned long user_call_ID) | |||
374 | BUG(); | 375 | BUG(); |
375 | if (test_and_set_bit(RXRPC_CALL_ACCEPTED, &call->events)) | 376 | if (test_and_set_bit(RXRPC_CALL_ACCEPTED, &call->events)) |
376 | BUG(); | 377 | BUG(); |
377 | schedule_work(&call->processor); | 378 | rxrpc_queue_call(call); |
378 | 379 | ||
380 | rxrpc_get_call(call); | ||
379 | write_unlock_bh(&call->state_lock); | 381 | write_unlock_bh(&call->state_lock); |
380 | write_unlock(&rx->call_lock); | 382 | write_unlock(&rx->call_lock); |
381 | _leave(" = 0"); | 383 | _leave(" = %p{%d}", call, call->debug_id); |
382 | return 0; | 384 | return call; |
385 | |||
386 | /* if the call is already dying or dead, then we leave the socket's ref | ||
387 | * on it to be released by rxrpc_dead_call_expired() as induced by | ||
388 | * rxrpc_release_call() */ | ||
389 | out_release: | ||
390 | _debug("release %p", call); | ||
391 | if (!test_bit(RXRPC_CALL_RELEASED, &call->flags) && | ||
392 | !test_and_set_bit(RXRPC_CALL_RELEASE, &call->events)) | ||
393 | rxrpc_queue_call(call); | ||
394 | out_discard: | ||
395 | write_unlock_bh(&call->state_lock); | ||
396 | _debug("discard %p", call); | ||
397 | out: | ||
398 | write_unlock(&rx->call_lock); | ||
399 | _leave(" = %d", ret); | ||
400 | return ERR_PTR(ret); | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * handle rejectance of a call by userspace | ||
405 | * - reject the call at the front of the queue | ||
406 | */ | ||
407 | int rxrpc_reject_call(struct rxrpc_sock *rx) | ||
408 | { | ||
409 | struct rxrpc_call *call; | ||
410 | int ret; | ||
411 | |||
412 | _enter(""); | ||
413 | |||
414 | ASSERT(!irqs_disabled()); | ||
415 | |||
416 | write_lock(&rx->call_lock); | ||
417 | |||
418 | ret = -ENODATA; | ||
419 | if (list_empty(&rx->acceptq)) | ||
420 | goto out; | ||
421 | |||
422 | /* dequeue the first call and check it's still valid */ | ||
423 | call = list_entry(rx->acceptq.next, struct rxrpc_call, accept_link); | ||
424 | list_del_init(&call->accept_link); | ||
425 | sk_acceptq_removed(&rx->sk); | ||
426 | |||
427 | write_lock_bh(&call->state_lock); | ||
428 | switch (call->state) { | ||
429 | case RXRPC_CALL_SERVER_ACCEPTING: | ||
430 | call->state = RXRPC_CALL_SERVER_BUSY; | ||
431 | if (test_and_set_bit(RXRPC_CALL_REJECT_BUSY, &call->events)) | ||
432 | rxrpc_queue_call(call); | ||
433 | ret = 0; | ||
434 | goto out_release; | ||
435 | case RXRPC_CALL_REMOTELY_ABORTED: | ||
436 | case RXRPC_CALL_LOCALLY_ABORTED: | ||
437 | ret = -ECONNABORTED; | ||
438 | goto out_release; | ||
439 | case RXRPC_CALL_NETWORK_ERROR: | ||
440 | ret = call->conn->error; | ||
441 | goto out_release; | ||
442 | case RXRPC_CALL_DEAD: | ||
443 | ret = -ETIME; | ||
444 | goto out_discard; | ||
445 | default: | ||
446 | BUG(); | ||
447 | } | ||
383 | 448 | ||
384 | /* if the call is already dying or dead, then we leave the socket's ref | 449 | /* if the call is already dying or dead, then we leave the socket's ref |
385 | * on it to be released by rxrpc_dead_call_expired() as induced by | 450 | * on it to be released by rxrpc_dead_call_expired() as induced by |
@@ -388,7 +453,7 @@ out_release: | |||
388 | _debug("release %p", call); | 453 | _debug("release %p", call); |
389 | if (!test_bit(RXRPC_CALL_RELEASED, &call->flags) && | 454 | if (!test_bit(RXRPC_CALL_RELEASED, &call->flags) && |
390 | !test_and_set_bit(RXRPC_CALL_RELEASE, &call->events)) | 455 | !test_and_set_bit(RXRPC_CALL_RELEASE, &call->events)) |
391 | schedule_work(&call->processor); | 456 | rxrpc_queue_call(call); |
392 | out_discard: | 457 | out_discard: |
393 | write_unlock_bh(&call->state_lock); | 458 | write_unlock_bh(&call->state_lock); |
394 | _debug("discard %p", call); | 459 | _debug("discard %p", call); |
@@ -397,3 +462,43 @@ out: | |||
397 | _leave(" = %d", ret); | 462 | _leave(" = %d", ret); |
398 | return ret; | 463 | return ret; |
399 | } | 464 | } |
465 | |||
466 | /** | ||
467 | * rxrpc_kernel_accept_call - Allow a kernel service to accept an incoming call | ||
468 | * @sock: The socket on which the impending call is waiting | ||
469 | * @user_call_ID: The tag to attach to the call | ||
470 | * | ||
471 | * Allow a kernel service to accept an incoming call, assuming the incoming | ||
472 | * call is still valid. | ||
473 | */ | ||
474 | struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *sock, | ||
475 | unsigned long user_call_ID) | ||
476 | { | ||
477 | struct rxrpc_call *call; | ||
478 | |||
479 | _enter(",%lx", user_call_ID); | ||
480 | call = rxrpc_accept_call(rxrpc_sk(sock->sk), user_call_ID); | ||
481 | _leave(" = %p", call); | ||
482 | return call; | ||
483 | } | ||
484 | |||
485 | EXPORT_SYMBOL(rxrpc_kernel_accept_call); | ||
486 | |||
487 | /** | ||
488 | * rxrpc_kernel_reject_call - Allow a kernel service to reject an incoming call | ||
489 | * @sock: The socket on which the impending call is waiting | ||
490 | * | ||
491 | * Allow a kernel service to reject an incoming call with a BUSY message, | ||
492 | * assuming the incoming call is still valid. | ||
493 | */ | ||
494 | int rxrpc_kernel_reject_call(struct socket *sock) | ||
495 | { | ||
496 | int ret; | ||
497 | |||
498 | _enter(""); | ||
499 | ret = rxrpc_reject_call(rxrpc_sk(sock->sk)); | ||
500 | _leave(" = %d", ret); | ||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | EXPORT_SYMBOL(rxrpc_kernel_reject_call); | ||