afs: Dispatch vlserver probes in priority order
authorDavid Howells <dhowells@redhat.com>
Mon, 30 Oct 2023 11:53:16 +0000 (11:53 +0000)
committerDavid Howells <dhowells@redhat.com>
Mon, 1 Jan 2024 16:37:27 +0000 (16:37 +0000)
When probing all the addresses for a volume location server, dispatch them
in order of descending priority to try and get back highest priority one
first.

Also add a tracepoint to show the transmission and completion of the
probes.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org

fs/afs/internal.h
fs/afs/vl_list.c
fs/afs/vl_probe.c
include/trace/events/afs.h

index 9a1e151e77e7ef855d9c3878589b13cde0be56ed..88db042207734632d3656da31dec594243f4854d 100644 (file)
@@ -447,6 +447,7 @@ struct afs_vlserver {
        rwlock_t                lock;           /* Lock on addresses */
        refcount_t              ref;
        unsigned int            rtt;            /* Server's current RTT in uS */
+       unsigned int            debug_id;
 
        /* Probe state */
        wait_queue_head_t       probe_wq;
index 5c4cd71caccf912a678f3be5205ef838573d5f8a..9b1c20daac53bfe4bde40aa4b323dc6cb384307a 100644 (file)
@@ -13,6 +13,7 @@ struct afs_vlserver *afs_alloc_vlserver(const char *name, size_t name_len,
                                        unsigned short port)
 {
        struct afs_vlserver *vlserver;
+       static atomic_t debug_ids;
 
        vlserver = kzalloc(struct_size(vlserver, name, name_len + 1),
                           GFP_KERNEL);
@@ -21,6 +22,7 @@ struct afs_vlserver *afs_alloc_vlserver(const char *name, size_t name_len,
                rwlock_init(&vlserver->lock);
                init_waitqueue_head(&vlserver->probe_wq);
                spin_lock_init(&vlserver->probe_lock);
+               vlserver->debug_id = atomic_inc_return(&debug_ids);
                vlserver->rtt = UINT_MAX;
                vlserver->name_len = name_len;
                vlserver->service_id = VL_SERVICE;
index f868ae5d40e5fd944520bbcab8a076e2f4a60d12..b128dc3d8af7446034d8004a83814f897e7aa376 100644 (file)
@@ -131,6 +131,7 @@ responded:
 out:
        spin_unlock(&server->probe_lock);
 
+       trace_afs_vl_probe(server, false, alist, index, call->error, call->abort_code, rtt_us);
        _debug("probe [%u][%u] %pISpc rtt=%d ret=%d",
               server_index, index, rxrpc_kernel_remote_addr(addr->peer),
               rtt_us, ret);
@@ -150,8 +151,10 @@ static bool afs_do_probe_vlserver(struct afs_net *net,
 {
        struct afs_addr_list *alist;
        struct afs_call *call;
-       unsigned int index;
+       unsigned long unprobed;
+       unsigned int index, i;
        bool in_progress = false;
+       int best_prio;
 
        _enter("%s", server->name);
 
@@ -165,7 +168,20 @@ static bool afs_do_probe_vlserver(struct afs_net *net,
        memset(&server->probe, 0, sizeof(server->probe));
        server->probe.rtt = UINT_MAX;
 
-       for (index = 0; index < alist->nr_addrs; index++) {
+       unprobed = (1UL << alist->nr_addrs) - 1;
+       while (unprobed) {
+               best_prio = -1;
+               index = 0;
+               for (i = 0; i < alist->nr_addrs; i++) {
+                       if (test_bit(i, &unprobed) &&
+                           alist->addrs[i].prio > best_prio) {
+                               index = i;
+                               best_prio = alist->addrs[i].prio;
+                       }
+               }
+               __clear_bit(index, &unprobed);
+
+               trace_afs_vl_probe(server, true, alist, index, 0, 0, 0);
                call = afs_vl_get_capabilities(net, alist, index, key, server,
                                               server_index);
                if (!IS_ERR(call)) {
index 81eb87fbcfa7fde62f974435573d20bfb334530c..f1815b3dafb0203ba958236f645ab608c14102a1 100644 (file)
@@ -1420,6 +1420,40 @@ TRACE_EVENT(afs_fs_probe,
                      &__entry->srx.transport)
            );
 
+TRACE_EVENT(afs_vl_probe,
+           TP_PROTO(struct afs_vlserver *server, bool tx, struct afs_addr_list *alist,
+                    unsigned int addr_index, int error, s32 abort_code, unsigned int rtt_us),
+
+           TP_ARGS(server, tx, alist, addr_index, error, abort_code, rtt_us),
+
+           TP_STRUCT__entry(
+                   __field(unsigned int,               server)
+                   __field(bool,                       tx)
+                   __field(unsigned short,             flags)
+                   __field(u16,                        addr_index)
+                   __field(short,                      error)
+                   __field(s32,                        abort_code)
+                   __field(unsigned int,               rtt_us)
+                   __field_struct(struct sockaddr_rxrpc, srx)
+                            ),
+
+           TP_fast_assign(
+                   __entry->server = server->debug_id;
+                   __entry->tx = tx;
+                   __entry->addr_index = addr_index;
+                   __entry->error = error;
+                   __entry->abort_code = abort_code;
+                   __entry->rtt_us = rtt_us;
+                   memcpy(&__entry->srx, rxrpc_kernel_remote_srx(alist->addrs[addr_index].peer),
+                          sizeof(__entry->srx));
+                          ),
+
+           TP_printk("vl=%08x %s ax=%u e=%d ac=%d rtt=%d %pISpc",
+                     __entry->server, __entry->tx ? "tx" : "rx", __entry->addr_index,
+                     __entry->error, __entry->abort_code, __entry->rtt_us,
+                     &__entry->srx.transport)
+           );
+
 #endif /* _TRACE_AFS_H */
 
 /* This part must be outside protection */