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 */ 18 static 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 */ 32 static 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 */ 47 void afs_vlserver_probe_result(struct afs_call *call) 48 { 49 struct afs_addr_list *alist = call->vl_probe; 50 struct afs_vlserver *server = call->vlserver; 51 struct afs_address *addr = &alist->addrs[call->probe_index]; 52 unsigned int server_index = call->server_index; 53 unsigned int rtt_us = 0; 54 unsigned int index = call->probe_index; 55 bool have_result = false; 56 int ret = call->error; 57 58 _enter("%s,%u,%u,%d,%d", server->name, server_index, index, ret, call->abort_code); 59 60 spin_lock(&server->probe_lock); 61 62 switch (ret) { 63 case 0: 64 server->probe.error = 0; 65 goto responded; 66 case -ECONNABORTED: 67 if (!(server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED)) { 68 server->probe.abort_code = call->abort_code; 69 server->probe.error = ret; 70 } 71 goto responded; 72 case -ENOMEM: 73 case -ENONET: 74 case -EKEYEXPIRED: 75 case -EKEYREVOKED: 76 case -EKEYREJECTED: 77 server->probe.flags |= AFS_VLSERVER_PROBE_LOCAL_FAILURE; 78 if (server->probe.error == 0) 79 server->probe.error = ret; 80 trace_afs_io_error(call->debug_id, ret, afs_io_error_vl_probe_fail); 81 goto out; 82 case -ECONNRESET: /* Responded, but call expired. */ 83 case -ERFKILL: 84 case -EADDRNOTAVAIL: 85 case -ENETUNREACH: 86 case -EHOSTUNREACH: 87 case -EHOSTDOWN: 88 case -ECONNREFUSED: 89 case -ETIMEDOUT: 90 case -ETIME: 91 default: 92 clear_bit(index, &alist->responded); 93 set_bit(index, &alist->probe_failed); 94 if (!(server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED) && 95 (server->probe.error == 0 || 96 server->probe.error == -ETIMEDOUT || 97 server->probe.error == -ETIME)) 98 server->probe.error = ret; 99 trace_afs_io_error(call->debug_id, ret, afs_io_error_vl_probe_fail); 100 goto out; 101 } 102 103 responded: 104 set_bit(index, &alist->responded); 105 clear_bit(index, &alist->probe_failed); 106 107 if (call->service_id == YFS_VL_SERVICE) { 108 server->probe.flags |= AFS_VLSERVER_PROBE_IS_YFS; 109 set_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); 110 server->service_id = call->service_id; 111 } else { 112 server->probe.flags |= AFS_VLSERVER_PROBE_NOT_YFS; 113 if (!(server->probe.flags & AFS_VLSERVER_PROBE_IS_YFS)) { 114 clear_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); 115 server->service_id = call->service_id; 116 } 117 } 118 119 rtt_us = rxrpc_kernel_get_srtt(addr->peer); 120 if (rtt_us < server->probe.rtt) { 121 server->probe.rtt = rtt_us; 122 server->rtt = rtt_us; 123 alist->preferred = index; 124 } 125 126 smp_wmb(); /* Set rtt before responded. */ 127 server->probe.flags |= AFS_VLSERVER_PROBE_RESPONDED; 128 set_bit(AFS_VLSERVER_FL_PROBED, &server->flags); 129 set_bit(AFS_VLSERVER_FL_RESPONDING, &server->flags); 130 have_result = true; 131 out: 132 spin_unlock(&server->probe_lock); 133 134 trace_afs_vl_probe(server, false, alist, index, call->error, call->abort_code, rtt_us); 135 _debug("probe [%u][%u] %pISpc rtt=%d ret=%d", 136 server_index, index, rxrpc_kernel_remote_addr(addr->peer), 137 rtt_us, ret); 138 139 afs_done_one_vl_probe(server, have_result); 140 } 141 142 /* 143 * Probe all of a vlserver's addresses to find out the best route and to 144 * query its capabilities. 145 */ 146 static bool afs_do_probe_vlserver(struct afs_net *net, 147 struct afs_vlserver *server, 148 struct key *key, 149 unsigned int server_index, 150 struct afs_error *_e) 151 { 152 struct afs_addr_list *alist; 153 struct afs_call *call; 154 unsigned long unprobed; 155 unsigned int index, i; 156 bool in_progress = false; 157 int best_prio; 158 159 _enter("%s", server->name); 160 161 read_lock(&server->lock); 162 alist = rcu_dereference_protected(server->addresses, 163 lockdep_is_held(&server->lock)); 164 afs_get_addrlist(alist, afs_alist_trace_get_vlprobe); 165 read_unlock(&server->lock); 166 167 atomic_set(&server->probe_outstanding, alist->nr_addrs); 168 memset(&server->probe, 0, sizeof(server->probe)); 169 server->probe.rtt = UINT_MAX; 170 171 unprobed = (1UL << alist->nr_addrs) - 1; 172 while (unprobed) { 173 best_prio = -1; 174 index = 0; 175 for (i = 0; i < alist->nr_addrs; i++) { 176 if (test_bit(i, &unprobed) && 177 alist->addrs[i].prio > best_prio) { 178 index = i; 179 best_prio = alist->addrs[i].prio; 180 } 181 } 182 __clear_bit(index, &unprobed); 183 184 trace_afs_vl_probe(server, true, alist, index, 0, 0, 0); 185 call = afs_vl_get_capabilities(net, alist, index, key, server, 186 server_index); 187 if (!IS_ERR(call)) { 188 afs_prioritise_error(_e, call->error, call->abort_code); 189 afs_put_call(call); 190 in_progress = true; 191 } else { 192 afs_prioritise_error(_e, PTR_ERR(call), 0); 193 afs_done_one_vl_probe(server, false); 194 } 195 } 196 197 afs_put_addrlist(alist, afs_alist_trace_put_vlprobe); 198 return in_progress; 199 } 200 201 /* 202 * Send off probes to all unprobed servers. 203 */ 204 int afs_send_vl_probes(struct afs_net *net, struct key *key, 205 struct afs_vlserver_list *vllist) 206 { 207 struct afs_vlserver *server; 208 struct afs_error e = {}; 209 bool in_progress = false; 210 int i; 211 212 for (i = 0; i < vllist->nr_servers; i++) { 213 server = vllist->servers[i].server; 214 if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags)) 215 continue; 216 217 if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags) && 218 afs_do_probe_vlserver(net, server, key, i, &e)) 219 in_progress = true; 220 } 221 222 return in_progress ? 0 : e.error; 223 } 224 225 /* 226 * Wait for the first as-yet untried server to respond. 227 */ 228 int afs_wait_for_vl_probes(struct afs_vlserver_list *vllist, 229 unsigned long untried) 230 { 231 struct wait_queue_entry *waits; 232 struct afs_vlserver *server; 233 unsigned int rtt = UINT_MAX, rtt_s; 234 bool have_responders = false; 235 int pref = -1, i; 236 237 _enter("%u,%lx", vllist->nr_servers, untried); 238 239 /* Only wait for servers that have a probe outstanding. */ 240 for (i = 0; i < vllist->nr_servers; i++) { 241 if (test_bit(i, &untried)) { 242 server = vllist->servers[i].server; 243 if (!test_bit(AFS_VLSERVER_FL_PROBING, &server->flags)) 244 __clear_bit(i, &untried); 245 if (server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED) 246 have_responders = true; 247 } 248 } 249 if (have_responders || !untried) 250 return 0; 251 252 waits = kmalloc(array_size(vllist->nr_servers, sizeof(*waits)), GFP_KERNEL); 253 if (!waits) 254 return -ENOMEM; 255 256 for (i = 0; i < vllist->nr_servers; i++) { 257 if (test_bit(i, &untried)) { 258 server = vllist->servers[i].server; 259 init_waitqueue_entry(&waits[i], current); 260 add_wait_queue(&server->probe_wq, &waits[i]); 261 } 262 } 263 264 for (;;) { 265 bool still_probing = false; 266 267 set_current_state(TASK_INTERRUPTIBLE); 268 for (i = 0; i < vllist->nr_servers; i++) { 269 if (test_bit(i, &untried)) { 270 server = vllist->servers[i].server; 271 if (server->probe.flags & AFS_VLSERVER_PROBE_RESPONDED) 272 goto stop; 273 if (test_bit(AFS_VLSERVER_FL_PROBING, &server->flags)) 274 still_probing = true; 275 } 276 } 277 278 if (!still_probing || signal_pending(current)) 279 goto stop; 280 schedule(); 281 } 282 283 stop: 284 set_current_state(TASK_RUNNING); 285 286 for (i = 0; i < vllist->nr_servers; i++) { 287 if (test_bit(i, &untried)) { 288 server = vllist->servers[i].server; 289 rtt_s = READ_ONCE(server->rtt); 290 if (test_bit(AFS_VLSERVER_FL_RESPONDING, &server->flags) && 291 rtt_s < rtt) { 292 pref = i; 293 rtt = rtt_s; 294 } 295 296 remove_wait_queue(&server->probe_wq, &waits[i]); 297 } 298 } 299 300 kfree(waits); 301 302 if (pref == -1 && signal_pending(current)) 303 return -ERESTARTSYS; 304 305 if (pref >= 0) 306 vllist->preferred = pref; 307 308 _leave(" = 0 [%u]", pref); 309 return 0; 310 } 311
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.