]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rxrpc: Pull out certain app callback funcs into an ops table
authorDavid Howells <dhowells@redhat.com>
Fri, 11 Apr 2025 09:52:47 +0000 (10:52 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 15 Apr 2025 00:36:41 +0000 (17:36 -0700)
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>
fs/afs/rxrpc.c
include/net/af_rxrpc.h
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_accept.c
net/rxrpc/rxperf.c

index d5e480a33859b0955661eb4b165dc22f13d4b8b2..a4734304e5421f1ca8f123780ac031bcd9064010 100644 (file)
@@ -24,8 +24,15 @@ static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned
 static void afs_process_async_call(struct work_struct *);
 static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
 static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
+static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID);
 static int afs_deliver_cm_op_id(struct afs_call *);
 
+static const struct rxrpc_kernel_ops afs_rxrpc_callback_ops = {
+       .notify_new_call        = afs_rx_new_call,
+       .discard_new_call       = afs_rx_discard_new_call,
+       .user_attach_call       = afs_rx_attach,
+};
+
 /* asynchronous incoming call initial processing */
 static const struct afs_call_type afs_RXCMxxxx = {
        .name           = "CB.xxxx",
@@ -84,8 +91,7 @@ int afs_open_socket(struct afs_net *net)
         * it sends back to us.
         */
 
-       rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
-                                          afs_rx_discard_new_call);
+       rxrpc_kernel_set_notifications(socket, &afs_rxrpc_callback_ops);
 
        ret = kernel_listen(socket, INT_MAX);
        if (ret < 0)
@@ -738,7 +744,6 @@ void afs_charge_preallocation(struct work_struct *work)
 
                if (rxrpc_kernel_charge_accept(net->socket,
                                               afs_wake_up_async_call,
-                                              afs_rx_attach,
                                               (unsigned long)call,
                                               GFP_KERNEL,
                                               call->debug_id) < 0)
index cf793d18e5df510be2929727e43fb496783ca92c..ebb6092c488b5c35fd5d4b9dc820530d87509ac9 100644 (file)
@@ -29,18 +29,23 @@ enum rxrpc_interruptibility {
  */
 extern atomic_t rxrpc_debug_id;
 
+/*
+ * Operations table for rxrpc to call out to a kernel application (e.g. kAFS).
+ */
+struct rxrpc_kernel_ops {
+       void (*notify_new_call)(struct sock *sk, struct rxrpc_call *call,
+                               unsigned long user_call_ID);
+       void (*discard_new_call)(struct rxrpc_call *call, unsigned long user_call_ID);
+       void (*user_attach_call)(struct rxrpc_call *call, unsigned long user_call_ID);
+};
+
 typedef void (*rxrpc_notify_rx_t)(struct sock *, struct rxrpc_call *,
                                  unsigned long);
 typedef void (*rxrpc_notify_end_tx_t)(struct sock *, struct rxrpc_call *,
                                      unsigned long);
-typedef void (*rxrpc_notify_new_call_t)(struct sock *, struct rxrpc_call *,
-                                       unsigned long);
-typedef void (*rxrpc_discard_new_call_t)(struct rxrpc_call *, unsigned long);
-typedef void (*rxrpc_user_attach_call_t)(struct rxrpc_call *, unsigned long);
 
-void rxrpc_kernel_new_call_notification(struct socket *,
-                                       rxrpc_notify_new_call_t,
-                                       rxrpc_discard_new_call_t);
+void rxrpc_kernel_set_notifications(struct socket *sock,
+                                   const struct rxrpc_kernel_ops *app_ops);
 struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
                                           struct rxrpc_peer *peer,
                                           struct key *key,
@@ -72,9 +77,9 @@ const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *peer);
 unsigned long rxrpc_kernel_set_peer_data(struct rxrpc_peer *peer, unsigned long app_data);
 unsigned long rxrpc_kernel_get_peer_data(const struct rxrpc_peer *peer);
 unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *);
-int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
-                              rxrpc_user_attach_call_t, unsigned long, gfp_t,
-                              unsigned int);
+int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx,
+                              unsigned long user_call_ID, gfp_t gfp,
+                              unsigned int debug_id);
 void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
 bool rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
 u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
index 2841ce72d7b894f7873ec5ddbfa4fe6409015695..2e4f6c9ef3de8900560067ef9e13798b9126f544 100644 (file)
@@ -477,24 +477,20 @@ u32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call)
 EXPORT_SYMBOL(rxrpc_kernel_get_epoch);
 
 /**
- * rxrpc_kernel_new_call_notification - Get notifications of new calls
- * @sock: The socket to intercept received messages on
- * @notify_new_call: Function to be called when new calls appear
- * @discard_new_call: Function to discard preallocated calls
+ * rxrpc_kernel_set_notifications - Set table of callback operations
+ * @sock: The socket to install table upon
+ * @app_ops: Callback operation table to set
  *
- * Allow a kernel service to be given notifications about new calls.
+ * Allow a kernel service to set a table of event notifications on a socket.
  */
-void rxrpc_kernel_new_call_notification(
-       struct socket *sock,
-       rxrpc_notify_new_call_t notify_new_call,
-       rxrpc_discard_new_call_t discard_new_call)
+void rxrpc_kernel_set_notifications(struct socket *sock,
+                                   const struct rxrpc_kernel_ops *app_ops)
 {
        struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
 
-       rx->notify_new_call = notify_new_call;
-       rx->discard_new_call = discard_new_call;
+       rx->app_ops = app_ops;
 }
-EXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
+EXPORT_SYMBOL(rxrpc_kernel_set_notifications);
 
 /**
  * rxrpc_kernel_set_max_life - Set maximum lifespan on a call
index 3cc3af15086ff1b2dda5a333299abccbb8ef1b3e..55810c6b4be89715f7764d08619626456f067eac 100644 (file)
@@ -146,8 +146,7 @@ struct rxrpc_backlog {
 struct rxrpc_sock {
        /* WARNING: sk has to be the first member */
        struct sock             sk;
-       rxrpc_notify_new_call_t notify_new_call; /* Func to notify of new call */
-       rxrpc_discard_new_call_t discard_new_call; /* Func to discard a new call */
+       const struct rxrpc_kernel_ops *app_ops; /* Table of kernel app notification funcs */
        struct rxrpc_local      *local;         /* local endpoint */
        struct rxrpc_backlog    *backlog;       /* Preallocation for services */
        spinlock_t              incoming_lock;  /* Incoming call vs service shutdown lock */
index e685034ce4f7cecb3595b57257969ea7940dee92..a4b363b47ccadfbc241f03cfffe1d4d7dbc9b16e 100644 (file)
@@ -34,7 +34,6 @@ static void rxrpc_dummy_notify(struct sock *sk, struct rxrpc_call *call,
 static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
                                      struct rxrpc_backlog *b,
                                      rxrpc_notify_rx_t notify_rx,
-                                     rxrpc_user_attach_call_t user_attach_call,
                                      unsigned long user_call_ID, gfp_t gfp,
                                      unsigned int debug_id)
 {
@@ -123,9 +122,10 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
 
        call->user_call_ID = user_call_ID;
        call->notify_rx = notify_rx;
-       if (user_attach_call) {
+       if (rx->app_ops &&
+           rx->app_ops->user_attach_call) {
                rxrpc_get_call(call, rxrpc_call_get_kernel_service);
-               user_attach_call(call, user_call_ID);
+               rx->app_ops->user_attach_call(call, user_call_ID);
        }
 
        rxrpc_get_call(call, rxrpc_call_get_userid);
@@ -219,9 +219,10 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
        while (CIRC_CNT(head, tail, size) > 0) {
                struct rxrpc_call *call = b->call_backlog[tail];
                rcu_assign_pointer(call->socket, rx);
-               if (rx->discard_new_call) {
+               if (rx->app_ops &&
+                   rx->app_ops->discard_new_call) {
                        _debug("discard %lx", call->user_call_ID);
-                       rx->discard_new_call(call, call->user_call_ID);
+                       rx->app_ops->discard_new_call(call, call->user_call_ID);
                        if (call->notify_rx)
                                call->notify_rx = rxrpc_dummy_notify;
                        rxrpc_put_call(call, rxrpc_call_put_kernel);
@@ -387,8 +388,9 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
        rxrpc_incoming_call(rx, call, skb);
        conn = call->conn;
 
-       if (rx->notify_new_call)
-               rx->notify_new_call(&rx->sk, call, call->user_call_ID);
+       if (rx->app_ops &&
+           rx->app_ops->notify_new_call)
+               rx->app_ops->notify_new_call(&rx->sk, call, call->user_call_ID);
 
        spin_lock(&conn->state_lock);
        if (conn->state == RXRPC_CONN_SERVICE_UNSECURED) {
@@ -440,8 +442,7 @@ int rxrpc_user_charge_accept(struct rxrpc_sock *rx, unsigned long user_call_ID)
        if (rx->sk.sk_state == RXRPC_CLOSE)
                return -ESHUTDOWN;
 
-       return rxrpc_service_prealloc_one(rx, b, NULL, NULL, user_call_ID,
-                                         GFP_KERNEL,
+       return rxrpc_service_prealloc_one(rx, b, NULL, user_call_ID, GFP_KERNEL,
                                          atomic_inc_return(&rxrpc_debug_id));
 }
 
@@ -449,20 +450,18 @@ int rxrpc_user_charge_accept(struct rxrpc_sock *rx, unsigned long user_call_ID)
  * rxrpc_kernel_charge_accept - Charge up socket with preallocated calls
  * @sock: The socket on which to preallocate
  * @notify_rx: Event notification function for the call
- * @user_attach_call: Func to attach call to user_call_ID
  * @user_call_ID: The tag to attach to the preallocated call
  * @gfp: The allocation conditions.
  * @debug_id: The tracing debug ID.
  *
- * Charge up the socket with preallocated calls, each with a user ID.  A
- * function should be provided to effect the attachment from the user's side.
- * The user is given a ref to hold on the call.
+ * Charge up the socket with preallocated calls, each with a user ID.  The
+ * ->user_attach_call() callback function should be provided to effect the
+ * attachment from the user's side.  The user is given a ref to hold on the
+ * call.
  *
  * Note that the call may be come connected before this function returns.
  */
-int rxrpc_kernel_charge_accept(struct socket *sock,
-                              rxrpc_notify_rx_t notify_rx,
-                              rxrpc_user_attach_call_t user_attach_call,
+int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx,
                               unsigned long user_call_ID, gfp_t gfp,
                               unsigned int debug_id)
 {
@@ -472,8 +471,7 @@ int rxrpc_kernel_charge_accept(struct socket *sock,
        if (sock->sk->sk_state == RXRPC_CLOSE)
                return -ESHUTDOWN;
 
-       return rxrpc_service_prealloc_one(rx, b, notify_rx,
-                                         user_attach_call, user_call_ID,
+       return rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
                                          gfp, debug_id);
 }
 EXPORT_SYMBOL(rxrpc_kernel_charge_accept);
index e848a4777b8c7d9ac56f07a35ce87df3641a8cdc..c76fbccfbb91ce7e5ed67e01284c8cc9abaa6679 100644 (file)
@@ -136,6 +136,12 @@ static void rxperf_notify_end_reply_tx(struct sock *sock,
                              RXPERF_CALL_SV_AWAIT_ACK);
 }
 
+static const struct rxrpc_kernel_ops rxperf_rxrpc_callback_ops = {
+       .notify_new_call        = rxperf_rx_new_call,
+       .discard_new_call       = rxperf_rx_discard_new_call,
+       .user_attach_call       = rxperf_rx_attach,
+};
+
 /*
  * Charge the incoming call preallocation.
  */
@@ -161,7 +167,6 @@ static void rxperf_charge_preallocation(struct work_struct *work)
 
                if (rxrpc_kernel_charge_accept(rxperf_socket,
                                               rxperf_notify_rx,
-                                              rxperf_rx_attach,
                                               (unsigned long)call,
                                               GFP_KERNEL,
                                               call->debug_id) < 0)
@@ -209,8 +214,7 @@ static int rxperf_open_socket(void)
        if (ret < 0)
                goto error_2;
 
-       rxrpc_kernel_new_call_notification(socket, rxperf_rx_new_call,
-                                          rxperf_rx_discard_new_call);
+       rxrpc_kernel_set_notifications(socket, &rxperf_rxrpc_callback_ops);
 
        ret = kernel_listen(socket, INT_MAX);
        if (ret < 0)