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