afs: Don't use probe running state to make decisions outside probe code
authorDavid Howells <dhowells@redhat.com>
Sat, 2 May 2020 12:39:57 +0000 (13:39 +0100)
committerDavid Howells <dhowells@redhat.com>
Thu, 4 Jun 2020 14:37:58 +0000 (15:37 +0100)
Don't use the running state for fileserver probes to make decisions about
which server to use as the state is cleared at the start of a probe and
also intermediate values might be misleading.

Instead, add a separate 'latest known' rtt in the afs_server struct and a
flag to indicate if the server is known to be responding and update these
as and when we know what to change them to.

Signed-off-by: David Howells <dhowells@redhat.com>
fs/afs/fs_probe.c
fs/afs/internal.h
fs/afs/rotate.c
fs/afs/server.c

index 442b5e7..c41cf3b 100644 (file)
@@ -42,10 +42,13 @@ static void afs_finished_fs_probe(struct afs_net *net, struct afs_server *server
        bool responded = server->probe.responded;
 
        write_seqlock(&net->fs_lock);
-       if (responded)
+       if (responded) {
                list_add_tail(&server->probe_link, &net->fs_probe_slow);
-       else
+       } else {
+               server->rtt = UINT_MAX;
+               clear_bit(AFS_SERVER_FL_RESPONDING, &server->flags);
                list_add_tail(&server->probe_link, &net->fs_probe_fast);
+       }
        write_sequnlock(&net->fs_lock);
 
        afs_schedule_fs_probe(net, server, !responded);
@@ -161,12 +164,14 @@ responded:
        rtt_us = rxrpc_kernel_get_srtt(call->net->socket, call->rxcall);
        if (rtt_us < server->probe.rtt) {
                server->probe.rtt = rtt_us;
+               server->rtt = rtt_us;
                alist->preferred = index;
        }
 
        smp_wmb(); /* Set rtt before responded. */
        server->probe.responded = true;
        set_bit(index, &alist->responded);
+       set_bit(AFS_SERVER_FL_RESPONDING, &server->flags);
 out:
        spin_unlock(&server->probe_lock);
 
@@ -224,7 +229,7 @@ int afs_wait_for_fs_probes(struct afs_server_list *slist, unsigned long untried)
 {
        struct wait_queue_entry *waits;
        struct afs_server *server;
-       unsigned int rtt = UINT_MAX;
+       unsigned int rtt = UINT_MAX, rtt_s;
        bool have_responders = false;
        int pref = -1, i;
 
@@ -280,10 +285,11 @@ stop:
        for (i = 0; i < slist->nr_servers; i++) {
                if (test_bit(i, &untried)) {
                        server = slist->servers[i].server;
-                       if (server->probe.responded &&
-                           server->probe.rtt < rtt) {
+                       rtt_s = READ_ONCE(server->rtt);
+                       if (test_bit(AFS_SERVER_FL_RESPONDING, &server->flags) &&
+                           rtt_s < rtt) {
                                pref = i;
-                               rtt = server->probe.rtt;
+                               rtt = rtt_s;
                        }
 
                        remove_wait_queue(&server->probe_wq, &waits[i]);
index e0dc14d..a4fe5d1 100644 (file)
@@ -496,6 +496,7 @@ struct afs_server {
        struct afs_server       *gc_next;       /* Next server in manager's list */
        time64_t                unuse_time;     /* Time at which last unused */
        unsigned long           flags;
+#define AFS_SERVER_FL_RESPONDING 0             /* The server is responding */
 #define AFS_SERVER_FL_NOT_READY        1               /* The record is not ready for use */
 #define AFS_SERVER_FL_NOT_FOUND        2               /* VL server says no such server */
 #define AFS_SERVER_FL_VL_FAIL  3               /* Failed to access VL server */
@@ -508,6 +509,7 @@ struct afs_server {
        atomic_t                ref;            /* Object refcount */
        atomic_t                active;         /* Active user count */
        u32                     addr_version;   /* Address list version */
+       unsigned int            rtt;            /* Server's current RTT in uS */
        unsigned int            debug_id;       /* Debugging ID for traces */
 
        /* file service access */
@@ -522,7 +524,7 @@ struct afs_server {
        atomic_t                probe_outstanding;
        spinlock_t              probe_lock;
        struct {
-               unsigned int    rtt;            /* RTT as ktime/64 */
+               unsigned int    rtt;            /* RTT in uS */
                u32             abort_code;
                short           error;
                bool            responded:1;
index 8d5473c..1486367 100644 (file)
@@ -341,7 +341,8 @@ pick_server:
        for (i = 0; i < op->server_list->nr_servers; i++) {
                struct afs_server *s = op->server_list->servers[i].server;
 
-               if (!test_bit(i, &op->untried) || !s->probe.responded)
+               if (!test_bit(i, &op->untried) ||
+                   !test_bit(AFS_SERVER_FL_RESPONDING, &s->flags))
                        continue;
                if (s->probe.rtt < rtt) {
                        op->index = i;
index 88593ff..039e348 100644 (file)
@@ -239,6 +239,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell,
        INIT_LIST_HEAD(&server->probe_link);
        spin_lock_init(&server->probe_lock);
        server->cell = cell;
+       server->rtt = UINT_MAX;
 
        afs_inc_servers_outstanding(net);
        trace_afs_server(server, 1, 1, afs_server_trace_alloc);