vl_probe.c (7620B)
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}