rxrpc: Don't expose skbs to in-kernel users [ver #2]
Don't expose skbs to in-kernel users, such as the AFS filesystem, but instead provide a notification hook the indicates that a call needs attention and another that indicates that there's a new call to be collected. This makes the following possibilities more achievable: (1) Call refcounting can be made simpler if skbs don't hold refs to calls. (2) skbs referring to non-data events will be able to be freed much sooner rather than being queued for AFS to pick up as rxrpc_kernel_recv_data will be able to consult the call state. (3) We can shortcut the receive phase when a call is remotely aborted because we don't have to go through all the packets to get to the one cancelling the operation. (4) It makes it easier to do encryption/decryption directly between AFS's buffers and sk_buffs. (5) Encryption/decryption can more easily be done in the AFS's thread contexts - usually that of the userspace process that issued a syscall - rather than in one of rxrpc's background threads on a workqueue. (6) AFS will be able to wait synchronously on a call inside AF_RXRPC. To make this work, the following interface function has been added: int rxrpc_kernel_recv_data( struct socket *sock, struct rxrpc_call *call, void *buffer, size_t bufsize, size_t *_offset, bool want_more, u32 *_abort_code); This is the recvmsg equivalent. It allows the caller to find out about the state of a specific call and to transfer received data into a buffer piecemeal. afs_extract_data() and rxrpc_kernel_recv_data() now do all the extraction logic between them. They don't wait synchronously yet because the socket lock needs to be dealt with. Five interface functions have been removed: rxrpc_kernel_is_data_last() rxrpc_kernel_get_abort_code() rxrpc_kernel_get_error_number() rxrpc_kernel_free_skb() rxrpc_kernel_data_consumed() As a temporary hack, sk_buffs going to an in-kernel call are queued on the rxrpc_call struct (->knlrecv_queue) rather than being handed over to the in-kernel user. To process the queue internally, a temporary function, temp_deliver_data() has been added. This will be replaced with common code between the rxrpc_recvmsg() path and the kernel_rxrpc_recv_data() path in a future patch. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
95ac399451
commit
d001648ec7
@@ -136,6 +136,7 @@ static struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp)
|
||||
INIT_LIST_HEAD(&call->accept_link);
|
||||
skb_queue_head_init(&call->rx_queue);
|
||||
skb_queue_head_init(&call->rx_oos_queue);
|
||||
skb_queue_head_init(&call->knlrecv_queue);
|
||||
init_waitqueue_head(&call->waitq);
|
||||
spin_lock_init(&call->lock);
|
||||
rwlock_init(&call->state_lock);
|
||||
@@ -552,8 +553,6 @@ void rxrpc_release_call(struct rxrpc_call *call)
|
||||
spin_lock_bh(&call->lock);
|
||||
}
|
||||
spin_unlock_bh(&call->lock);
|
||||
|
||||
ASSERTCMP(call->state, !=, RXRPC_CALL_COMPLETE);
|
||||
}
|
||||
|
||||
del_timer_sync(&call->resend_timer);
|
||||
@@ -682,6 +681,7 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
|
||||
struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu);
|
||||
|
||||
rxrpc_purge_queue(&call->rx_queue);
|
||||
rxrpc_purge_queue(&call->knlrecv_queue);
|
||||
rxrpc_put_peer(call->peer);
|
||||
kmem_cache_free(rxrpc_call_jar, call);
|
||||
}
|
||||
@@ -737,6 +737,7 @@ static void rxrpc_cleanup_call(struct rxrpc_call *call)
|
||||
|
||||
rxrpc_purge_queue(&call->rx_queue);
|
||||
ASSERT(skb_queue_empty(&call->rx_oos_queue));
|
||||
rxrpc_purge_queue(&call->knlrecv_queue);
|
||||
sock_put(&call->socket->sk);
|
||||
call_rcu(&call->rcu, rxrpc_rcu_destroy_call);
|
||||
}
|
||||
|
Reference in New Issue
Block a user