Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rxrpc: Pull out certain app callback funcs into an ops table

A number of functions separately furnish an AF_RXRPC socket with callback
function pointers into a kernel app (such as the AFS filesystem) that is
using it. Replace most of these with an ops table for the entire socket.
This makes it easier to add more callback functions.

Note that the call incoming data processing callback is retaind as that
gets set to different things, depending on the type of op.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20250411095303.2316168-3-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

David Howells and committed by
Jakub Kicinski
23738cc8 28a79fc9

+55 -48
+8 -3
fs/afs/rxrpc.c
··· 24 24 static void afs_process_async_call(struct work_struct *); 25 25 static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long); 26 26 static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long); 27 + static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID); 27 28 static int afs_deliver_cm_op_id(struct afs_call *); 29 + 30 + static const struct rxrpc_kernel_ops afs_rxrpc_callback_ops = { 31 + .notify_new_call = afs_rx_new_call, 32 + .discard_new_call = afs_rx_discard_new_call, 33 + .user_attach_call = afs_rx_attach, 34 + }; 28 35 29 36 /* asynchronous incoming call initial processing */ 30 37 static const struct afs_call_type afs_RXCMxxxx = { ··· 91 84 * it sends back to us. 92 85 */ 93 86 94 - rxrpc_kernel_new_call_notification(socket, afs_rx_new_call, 95 - afs_rx_discard_new_call); 87 + rxrpc_kernel_set_notifications(socket, &afs_rxrpc_callback_ops); 96 88 97 89 ret = kernel_listen(socket, INT_MAX); 98 90 if (ret < 0) ··· 744 738 745 739 if (rxrpc_kernel_charge_accept(net->socket, 746 740 afs_wake_up_async_call, 747 - afs_rx_attach, 748 741 (unsigned long)call, 749 742 GFP_KERNEL, 750 743 call->debug_id) < 0)
+15 -10
include/net/af_rxrpc.h
··· 29 29 */ 30 30 extern atomic_t rxrpc_debug_id; 31 31 32 + /* 33 + * Operations table for rxrpc to call out to a kernel application (e.g. kAFS). 34 + */ 35 + struct rxrpc_kernel_ops { 36 + void (*notify_new_call)(struct sock *sk, struct rxrpc_call *call, 37 + unsigned long user_call_ID); 38 + void (*discard_new_call)(struct rxrpc_call *call, unsigned long user_call_ID); 39 + void (*user_attach_call)(struct rxrpc_call *call, unsigned long user_call_ID); 40 + }; 41 + 32 42 typedef void (*rxrpc_notify_rx_t)(struct sock *, struct rxrpc_call *, 33 43 unsigned long); 34 44 typedef void (*rxrpc_notify_end_tx_t)(struct sock *, struct rxrpc_call *, 35 45 unsigned long); 36 - typedef void (*rxrpc_notify_new_call_t)(struct sock *, struct rxrpc_call *, 37 - unsigned long); 38 - typedef void (*rxrpc_discard_new_call_t)(struct rxrpc_call *, unsigned long); 39 - typedef void (*rxrpc_user_attach_call_t)(struct rxrpc_call *, unsigned long); 40 46 41 - void rxrpc_kernel_new_call_notification(struct socket *, 42 - rxrpc_notify_new_call_t, 43 - rxrpc_discard_new_call_t); 47 + void rxrpc_kernel_set_notifications(struct socket *sock, 48 + const struct rxrpc_kernel_ops *app_ops); 44 49 struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, 45 50 struct rxrpc_peer *peer, 46 51 struct key *key, ··· 77 72 unsigned long rxrpc_kernel_set_peer_data(struct rxrpc_peer *peer, unsigned long app_data); 78 73 unsigned long rxrpc_kernel_get_peer_data(const struct rxrpc_peer *peer); 79 74 unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *); 80 - int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t, 81 - rxrpc_user_attach_call_t, unsigned long, gfp_t, 82 - unsigned int); 75 + int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx, 76 + unsigned long user_call_ID, gfp_t gfp, 77 + unsigned int debug_id); 83 78 void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64); 84 79 bool rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *); 85 80 u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
+8 -12
net/rxrpc/af_rxrpc.c
··· 477 477 EXPORT_SYMBOL(rxrpc_kernel_get_epoch); 478 478 479 479 /** 480 - * rxrpc_kernel_new_call_notification - Get notifications of new calls 481 - * @sock: The socket to intercept received messages on 482 - * @notify_new_call: Function to be called when new calls appear 483 - * @discard_new_call: Function to discard preallocated calls 480 + * rxrpc_kernel_set_notifications - Set table of callback operations 481 + * @sock: The socket to install table upon 482 + * @app_ops: Callback operation table to set 484 483 * 485 - * Allow a kernel service to be given notifications about new calls. 484 + * Allow a kernel service to set a table of event notifications on a socket. 486 485 */ 487 - void rxrpc_kernel_new_call_notification( 488 - struct socket *sock, 489 - rxrpc_notify_new_call_t notify_new_call, 490 - rxrpc_discard_new_call_t discard_new_call) 486 + void rxrpc_kernel_set_notifications(struct socket *sock, 487 + const struct rxrpc_kernel_ops *app_ops) 491 488 { 492 489 struct rxrpc_sock *rx = rxrpc_sk(sock->sk); 493 490 494 - rx->notify_new_call = notify_new_call; 495 - rx->discard_new_call = discard_new_call; 491 + rx->app_ops = app_ops; 496 492 } 497 - EXPORT_SYMBOL(rxrpc_kernel_new_call_notification); 493 + EXPORT_SYMBOL(rxrpc_kernel_set_notifications); 498 494 499 495 /** 500 496 * rxrpc_kernel_set_max_life - Set maximum lifespan on a call
+1 -2
net/rxrpc/ar-internal.h
··· 146 146 struct rxrpc_sock { 147 147 /* WARNING: sk has to be the first member */ 148 148 struct sock sk; 149 - rxrpc_notify_new_call_t notify_new_call; /* Func to notify of new call */ 150 - rxrpc_discard_new_call_t discard_new_call; /* Func to discard a new call */ 149 + const struct rxrpc_kernel_ops *app_ops; /* Table of kernel app notification funcs */ 151 150 struct rxrpc_local *local; /* local endpoint */ 152 151 struct rxrpc_backlog *backlog; /* Preallocation for services */ 153 152 spinlock_t incoming_lock; /* Incoming call vs service shutdown lock */
+16 -18
net/rxrpc/call_accept.c
··· 34 34 static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, 35 35 struct rxrpc_backlog *b, 36 36 rxrpc_notify_rx_t notify_rx, 37 - rxrpc_user_attach_call_t user_attach_call, 38 37 unsigned long user_call_ID, gfp_t gfp, 39 38 unsigned int debug_id) 40 39 { ··· 122 123 123 124 call->user_call_ID = user_call_ID; 124 125 call->notify_rx = notify_rx; 125 - if (user_attach_call) { 126 + if (rx->app_ops && 127 + rx->app_ops->user_attach_call) { 126 128 rxrpc_get_call(call, rxrpc_call_get_kernel_service); 127 - user_attach_call(call, user_call_ID); 129 + rx->app_ops->user_attach_call(call, user_call_ID); 128 130 } 129 131 130 132 rxrpc_get_call(call, rxrpc_call_get_userid); ··· 219 219 while (CIRC_CNT(head, tail, size) > 0) { 220 220 struct rxrpc_call *call = b->call_backlog[tail]; 221 221 rcu_assign_pointer(call->socket, rx); 222 - if (rx->discard_new_call) { 222 + if (rx->app_ops && 223 + rx->app_ops->discard_new_call) { 223 224 _debug("discard %lx", call->user_call_ID); 224 - rx->discard_new_call(call, call->user_call_ID); 225 + rx->app_ops->discard_new_call(call, call->user_call_ID); 225 226 if (call->notify_rx) 226 227 call->notify_rx = rxrpc_dummy_notify; 227 228 rxrpc_put_call(call, rxrpc_call_put_kernel); ··· 388 387 rxrpc_incoming_call(rx, call, skb); 389 388 conn = call->conn; 390 389 391 - if (rx->notify_new_call) 392 - rx->notify_new_call(&rx->sk, call, call->user_call_ID); 390 + if (rx->app_ops && 391 + rx->app_ops->notify_new_call) 392 + rx->app_ops->notify_new_call(&rx->sk, call, call->user_call_ID); 393 393 394 394 spin_lock(&conn->state_lock); 395 395 if (conn->state == RXRPC_CONN_SERVICE_UNSECURED) { ··· 442 440 if (rx->sk.sk_state == RXRPC_CLOSE) 443 441 return -ESHUTDOWN; 444 442 445 - return rxrpc_service_prealloc_one(rx, b, NULL, NULL, user_call_ID, 446 - GFP_KERNEL, 443 + return rxrpc_service_prealloc_one(rx, b, NULL, user_call_ID, GFP_KERNEL, 447 444 atomic_inc_return(&rxrpc_debug_id)); 448 445 } 449 446 ··· 450 449 * rxrpc_kernel_charge_accept - Charge up socket with preallocated calls 451 450 * @sock: The socket on which to preallocate 452 451 * @notify_rx: Event notification function for the call 453 - * @user_attach_call: Func to attach call to user_call_ID 454 452 * @user_call_ID: The tag to attach to the preallocated call 455 453 * @gfp: The allocation conditions. 456 454 * @debug_id: The tracing debug ID. 457 455 * 458 - * Charge up the socket with preallocated calls, each with a user ID. A 459 - * function should be provided to effect the attachment from the user's side. 460 - * The user is given a ref to hold on the call. 456 + * Charge up the socket with preallocated calls, each with a user ID. The 457 + * ->user_attach_call() callback function should be provided to effect the 458 + * attachment from the user's side. The user is given a ref to hold on the 459 + * call. 461 460 * 462 461 * Note that the call may be come connected before this function returns. 463 462 */ 464 - int rxrpc_kernel_charge_accept(struct socket *sock, 465 - rxrpc_notify_rx_t notify_rx, 466 - rxrpc_user_attach_call_t user_attach_call, 463 + int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx, 467 464 unsigned long user_call_ID, gfp_t gfp, 468 465 unsigned int debug_id) 469 466 { ··· 471 472 if (sock->sk->sk_state == RXRPC_CLOSE) 472 473 return -ESHUTDOWN; 473 474 474 - return rxrpc_service_prealloc_one(rx, b, notify_rx, 475 - user_attach_call, user_call_ID, 475 + return rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID, 476 476 gfp, debug_id); 477 477 } 478 478 EXPORT_SYMBOL(rxrpc_kernel_charge_accept);
+7 -3
net/rxrpc/rxperf.c
··· 136 136 RXPERF_CALL_SV_AWAIT_ACK); 137 137 } 138 138 139 + static const struct rxrpc_kernel_ops rxperf_rxrpc_callback_ops = { 140 + .notify_new_call = rxperf_rx_new_call, 141 + .discard_new_call = rxperf_rx_discard_new_call, 142 + .user_attach_call = rxperf_rx_attach, 143 + }; 144 + 139 145 /* 140 146 * Charge the incoming call preallocation. 141 147 */ ··· 167 161 168 162 if (rxrpc_kernel_charge_accept(rxperf_socket, 169 163 rxperf_notify_rx, 170 - rxperf_rx_attach, 171 164 (unsigned long)call, 172 165 GFP_KERNEL, 173 166 call->debug_id) < 0) ··· 214 209 if (ret < 0) 215 210 goto error_2; 216 211 217 - rxrpc_kernel_new_call_notification(socket, rxperf_rx_new_call, 218 - rxperf_rx_discard_new_call); 212 + rxrpc_kernel_set_notifications(socket, &rxperf_rxrpc_callback_ops); 219 213 220 214 ret = kernel_listen(socket, INT_MAX); 221 215 if (ret < 0)