linux/fs/afs/vl_probe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* AFS vlserver probing
   3 *
   4 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#include <linux/sched.h>
   9#include <linux/slab.h>
  10#include "afs_fs.h"
  11#include "internal.h"
  12#include "protocol_yfs.h"
  13
  14
  15/*
  16 * Handle the completion of a set of probes.
  17 */
  18static void afs_finished_vl_probe(struct afs_vlserver *server)
  19{
  20        if (!(server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED)) {
  21                server->rtt = UINT_MAX;
  22                clear_bit(AFS_VLSERVER_FL_RESPONDING, &server->flags);
  23        }
  24
  25        clear_bit_unlock(AFS_VLSERVER_FL_PROBING, &server->flags);
  26        wake_up_bit(&server->flags, AFS_VLSERVER_FL_PROBING);
  27}
  28
  29/*
  30 * Handle the completion of a probe RPC call.
  31 */
  32static void afs_done_one_vl_probe(struct afs_vlserver *server, bool wake_up)
  33{
  34        if (atomic_dec_and_test(&server->probe_outstanding)) {
  35                afs_finished_vl_probe(server);
  36                wake_up = true;
  37        }
  38
  39        if (wake_up)
  40                wake_up_all(&server->probe_wq);
  41}
  42
  43/*
  44 * Process the result of probing a vlserver.  This is called after successful
  45 * or failed delivery of an VL.GetCapabilities operation.
  46 */
  47void afs_vlserver_probe_result(struct afs_call *call)
  48{
  49        struct afs_addr_list *alist = call->alist;
  50        struct afs_vlserver *server = call->vlserver;
  51        unsigned int server_index = call->server_index;
  52        unsigned int rtt_us = 0;
  53        unsigned int index = call->addr_ix;
  54        bool have_result = false;
  55        int ret = call->error;
  56
  57        _enter("%s,%u,%u,%d,%d", server->name, server_index, index, ret, call->abort_code);
  58
  59        spin_lock(&server->probe_lock);
  60
  61        switch (ret) {
  62        case 0:
  63                server->probe.error = 0;
  64                goto responded;
  65        case -ECONNABORTED:
  66                if (!(server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED)) {
  67                        server->probe.abort_code = call->abort_code;
  68                        server->probe.error = ret;
  69                }
  70                goto responded;
  71        case -ENOMEM:
  72        case -ENONET:
  73        case -EKEYEXPIRED:
  74        case -EKEYREVOKED:
  75        case -EKEYREJECTED:
  76                server->probe.flags |= AFS_VLSERVER_PROBE_LOCAL_FAILURE;
  77                if (server->probe.error == 0)
  78                        server->probe.error = ret;
  79                trace_afs_io_error(call->debug_id, ret, afs_io_error_vl_probe_fail);
  80                goto out;
  81        case -ECONNRESET: /* Responded, but call expired. */
  82        case -ERFKILL:
  83        case -EADDRNOTAVAIL:
  84        case -ENETUNREACH:
  85        case -EHOSTUNREACH:
  86        case -EHOSTDOWN:
  87        case -ECONNREFUSED:
  88        case -ETIMEDOUT:
  89        case -ETIME:
  90        default:
  91                clear_bit(index, &alist->responded);
  92                set_bit(index, &alist->failed);
  93                if (!(server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED) &&
  94                    (server->probe.error == 0 ||
  95                     server->probe.error == -ETIMEDOUT ||
  96                     server->probe.error == -ETIME))
  97                        server->probe.error = ret;
  98                trace_afs_io_error(call->debug_id, ret, afs_io_error_vl_probe_fail);
  99                goto out;
 100        }
 101
 102responded:
 103        set_bit(index, &alist->responded);
 104        clear_bit(index, &alist->failed);
 105
 106        if (call->service_id == YFS_VL_SERVICE) {
 107                server->probe.flags |= AFS_VLSERVER_PROBE_IS_YFS;
 108                set_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags);
 109                alist->addrs[index].srx_service = call->service_id;
 110        } else {
 111                server->probe.flags |= AFS_VLSERVER_PROBE_NOT_YFS;
 112                if (!(server->probe.flags & AFS_VLSERVER_PROBE_IS_YFS)) {
 113                        clear_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags);
 114                        alist->addrs[index].srx_service = call->service_id;
 115                }
 116        }
 117
 118        if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) &&
 119            rtt_us < server->probe.rtt) {
 120                server->probe.rtt = rtt_us;
 121                server->rtt = rtt_us;
 122                alist->preferred = index;
 123        }
 124
 125        smp_wmb(); /* Set rtt before responded. */
 126        server->probe.flags |= AFS_VLSERVER_PROBE_RESPONDED;
 127        set_bit(AFS_VLSERVER_FL_PROBED, &server->flags);
 128        set_bit(AFS_VLSERVER_FL_RESPONDING, &server->flags);
 129        have_result = true;
 130out:
 131        spin_unlock(&server->probe_lock);
 132
 133        _debug("probe [%u][%u] %pISpc rtt=%u ret=%d",
 134               server_index, index, &alist->addrs[index].transport, rtt_us, ret);
 135
 136        afs_done_one_vl_probe(server, have_result);
 137}
 138
 139/*
 140 * Probe all of a vlserver's addresses to find out the best route and to
 141 * query its capabilities.
 142 */
 143static bool afs_do_probe_vlserver(struct afs_net *net,
 144                                  struct afs_vlserver *server,
 145                                  struct key *key,
 146                                  unsigned int server_index,
 147                                  struct afs_error *_e)
 148{
 149        struct afs_addr_cursor ac = {
 150                .index = 0,
 151        };
 152        struct afs_call *call;
 153        bool in_progress = false;
 154
 155        _enter("%s", server->name);
 156
 157        read_lock(&server->lock);
 158        ac.alist = rcu_dereference_protected(server->addresses,
 159                                             lockdep_is_held(&server->lock));
 160        read_unlock(&server->lock);
 161
 162        atomic_set(&server->probe_outstanding, ac.alist->nr_addrs);
 163        memset(&server->probe, 0, sizeof(server->probe));
 164        server->probe.rtt = UINT_MAX;
 165
 166        for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
 167                call = afs_vl_get_capabilities(net, &ac, key, server,
 168                                               server_index);
 169                if (!IS_ERR(call)) {
 170                        afs_put_call(call);
 171                        in_progress = true;
 172                } else {
 173                        afs_prioritise_error(_e, PTR_ERR(call), ac.abort_code);
 174                        afs_done_one_vl_probe(server, false);
 175                }
 176        }
 177
 178        return in_progress;
 179}
 180
 181/*
 182 * Send off probes to all unprobed servers.
 183 */
 184int afs_send_vl_probes(struct afs_net *net, struct key *key,
 185                       struct afs_vlserver_list *vllist)
 186{
 187        struct afs_vlserver *server;
 188        struct afs_error e;
 189        bool in_progress = false;
 190        int i;
 191
 192        e.error = 0;
 193        e.responded = false;
 194        for (i = 0; i < vllist->nr_servers; i++) {
 195                server = vllist->servers[i].server;
 196                if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags))
 197                        continue;
 198
 199                if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags) &&
 200                    afs_do_probe_vlserver(net, server, key, i, &e))
 201                        in_progress = true;
 202        }
 203
 204        return in_progress ? 0 : e.error;
 205}
 206
 207/*
 208 * Wait for the first as-yet untried server to respond.
 209 */
 210int afs_wait_for_vl_probes(struct afs_vlserver_list *vllist,
 211                           unsigned long untried)
 212{
 213        struct wait_queue_entry *waits;
 214        struct afs_vlserver *server;
 215        unsigned int rtt = UINT_MAX, rtt_s;
 216        bool have_responders = false;
 217        int pref = -1, i;
 218
 219        _enter("%u,%lx", vllist->nr_servers, untried);
 220
 221        /* Only wait for servers that have a probe outstanding. */
 222        for (i = 0; i < vllist->nr_servers; i++) {
 223                if (test_bit(i, &untried)) {
 224                        server = vllist->servers[i].server;
 225                        if (!test_bit(AFS_VLSERVER_FL_PROBING, &server->flags))
 226                                __clear_bit(i, &untried);
 227                        if (server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED)
 228                                have_responders = true;
 229                }
 230        }
 231        if (have_responders || !untried)
 232                return 0;
 233
 234        waits = kmalloc(array_size(vllist->nr_servers, sizeof(*waits)), GFP_KERNEL);
 235        if (!waits)
 236                return -ENOMEM;
 237
 238        for (i = 0; i < vllist->nr_servers; i++) {
 239                if (test_bit(i, &untried)) {
 240                        server = vllist->servers[i].server;
 241                        init_waitqueue_entry(&waits[i], current);
 242                        add_wait_queue(&server->probe_wq, &waits[i]);
 243                }
 244        }
 245
 246        for (;;) {
 247                bool still_probing = false;
 248
 249                set_current_state(TASK_INTERRUPTIBLE);
 250                for (i = 0; i < vllist->nr_servers; i++) {
 251                        if (test_bit(i, &untried)) {
 252                                server = vllist->servers[i].server;
 253                                if (server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED)
 254                                        goto stop;
 255                                if (test_bit(AFS_VLSERVER_FL_PROBING, &server->flags))
 256                                        still_probing = true;
 257                        }
 258                }
 259
 260                if (!still_probing || signal_pending(current))
 261                        goto stop;
 262                schedule();
 263        }
 264
 265stop:
 266        set_current_state(TASK_RUNNING);
 267
 268        for (i = 0; i < vllist->nr_servers; i++) {
 269                if (test_bit(i, &untried)) {
 270                        server = vllist->servers[i].server;
 271                        rtt_s = READ_ONCE(server->rtt);
 272                        if (test_bit(AFS_VLSERVER_FL_RESPONDING, &server->flags) &&
 273                            rtt_s < rtt) {
 274                                pref = i;
 275                                rtt = rtt_s;
 276                        }
 277
 278                        remove_wait_queue(&server->probe_wq, &waits[i]);
 279                }
 280        }
 281
 282        kfree(waits);
 283
 284        if (pref == -1 && signal_pending(current))
 285                return -ERESTARTSYS;
 286
 287        if (pref >= 0)
 288                vllist->preferred = pref;
 289
 290        _leave(" = 0 [%u]", pref);
 291        return 0;
 292}
 293