Blame view
fs/afs/vl_rotate.c
8.52 KB
b4d0d230c treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
0a5143f2f afs: Implement VL... |
2 3 4 5 |
/* Handle vlserver selection and rotation. * * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) |
0a5143f2f afs: Implement VL... |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
*/ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/sched/signal.h> #include "internal.h" #include "afs_vl.h" /* * Begin an operation on a volume location server. */ bool afs_begin_vlserver_operation(struct afs_vl_cursor *vc, struct afs_cell *cell, struct key *key) { memset(vc, 0, sizeof(*vc)); vc->cell = cell; vc->key = key; vc->error = -EDESTADDRREQ; vc->ac.error = SHRT_MAX; if (signal_pending(current)) { vc->error = -EINTR; vc->flags |= AFS_VL_CURSOR_STOP; return false; } return true; } /* * Begin iteration through a server list, starting with the last used server if * possible, or the last recorded good server if not. */ static bool afs_start_vl_iteration(struct afs_vl_cursor *vc) { struct afs_cell *cell = vc->cell; |
d5c32c89b afs: Fix cell DNS... |
42 |
unsigned int dns_lookup_count; |
0a5143f2f afs: Implement VL... |
43 |
|
d5c32c89b afs: Fix cell DNS... |
44 45 46 47 |
if (cell->dns_source == DNS_RECORD_UNAVAILABLE || cell->dns_expiry <= ktime_get_real_seconds()) { dns_lookup_count = smp_load_acquire(&cell->dns_lookup_count); set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags); |
dca54a7bb afs: Add tracing ... |
48 |
afs_queue_cell(cell, afs_cell_trace_get_queue_dns); |
d5c32c89b afs: Fix cell DNS... |
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
if (cell->dns_source == DNS_RECORD_UNAVAILABLE) { if (wait_var_event_interruptible( &cell->dns_lookup_count, smp_load_acquire(&cell->dns_lookup_count) != dns_lookup_count) < 0) { vc->error = -ERESTARTSYS; return false; } } /* Status load is ordered after lookup counter load */ if (cell->dns_source == DNS_RECORD_UNAVAILABLE) { vc->error = -EDESTADDRREQ; return false; } |
0a5143f2f afs: Implement VL... |
65 66 67 68 69 70 71 |
} read_lock(&cell->vl_servers_lock); vc->server_list = afs_get_vlserverlist( rcu_dereference_protected(cell->vl_servers, lockdep_is_held(&cell->vl_servers_lock))); read_unlock(&cell->vl_servers_lock); |
ca1cbbdce afs: Fix afs_cell... |
72 |
if (!vc->server_list->nr_servers) |
0a5143f2f afs: Implement VL... |
73 |
return false; |
3bf0fb6f3 afs: Probe multip... |
74 75 |
vc->untried = (1UL << vc->server_list->nr_servers) - 1; vc->index = -1; |
0a5143f2f afs: Implement VL... |
76 77 78 79 80 81 82 83 84 85 86 |
return true; } /* * Select the vlserver to use. May be called multiple times to rotate * through the vlservers. */ bool afs_select_vlserver(struct afs_vl_cursor *vc) { struct afs_addr_list *alist; struct afs_vlserver *vlserver; |
4584ae96a afs: Fix missing ... |
87 |
struct afs_error e; |
3bf0fb6f3 afs: Probe multip... |
88 |
u32 rtt; |
4584ae96a afs: Fix missing ... |
89 |
int error = vc->ac.error, i; |
0a5143f2f afs: Implement VL... |
90 |
|
3bf0fb6f3 afs: Probe multip... |
91 92 93 |
_enter("%lx[%d],%lx[%d],%d,%d", vc->untried, vc->index, vc->ac.tried, vc->ac.index, |
0a5143f2f afs: Implement VL... |
94 95 96 97 98 99 |
error, vc->ac.abort_code); if (vc->flags & AFS_VL_CURSOR_STOP) { _leave(" = f [stopped]"); return false; } |
744bcd713 afs: Allow dumpin... |
100 |
vc->nr_iterations++; |
0a5143f2f afs: Implement VL... |
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
/* Evaluate the result of the previous operation, if there was one. */ switch (error) { case SHRT_MAX: goto start; default: case 0: /* Success or local failure. Stop. */ vc->error = error; vc->flags |= AFS_VL_CURSOR_STOP; _leave(" = f [okay/local %d]", vc->ac.error); return false; case -ECONNABORTED: /* The far side rejected the operation on some grounds. This * might involve the server being busy or the volume having been moved. */ switch (vc->ac.abort_code) { case AFSVL_IO: case AFSVL_BADVOLOPER: case AFSVL_NOMEM: /* The server went weird. */ vc->error = -EREMOTEIO; //write_lock(&vc->cell->vl_servers_lock); //vc->server_list->weird_mask |= 1 << vc->index; //write_unlock(&vc->cell->vl_servers_lock); goto next_server; default: vc->error = afs_abort_to_error(vc->ac.abort_code); goto failed; } |
4584ae96a afs: Fix missing ... |
133 134 |
case -ERFKILL: case -EADDRNOTAVAIL: |
0a5143f2f afs: Implement VL... |
135 136 |
case -ENETUNREACH: case -EHOSTUNREACH: |
4584ae96a afs: Fix missing ... |
137 |
case -EHOSTDOWN: |
0a5143f2f afs: Implement VL... |
138 139 140 141 142 143 144 145 146 147 148 149 |
case -ECONNREFUSED: case -ETIMEDOUT: case -ETIME: _debug("no conn %d", error); vc->error = error; goto iterate_address; case -ECONNRESET: _debug("call reset"); vc->error = error; vc->flags |= AFS_VL_CURSOR_RETRY; goto next_server; |
6dfdf5369 afs: Detect cell ... |
150 151 152 153 |
case -EOPNOTSUPP: _debug("notsupp"); goto next_server; |
0a5143f2f afs: Implement VL... |
154 155 156 157 158 159 160 161 162 163 164 165 |
} restart_from_beginning: _debug("restart"); afs_end_cursor(&vc->ac); afs_put_vlserverlist(vc->cell->net, vc->server_list); vc->server_list = NULL; if (vc->flags & AFS_VL_CURSOR_RETRIED) goto failed; vc->flags |= AFS_VL_CURSOR_RETRIED; start: _debug("start"); |
0a5143f2f afs: Implement VL... |
166 167 |
if (!afs_start_vl_iteration(vc)) goto failed; |
3bf0fb6f3 afs: Probe multip... |
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
error = afs_send_vl_probes(vc->cell->net, vc->key, vc->server_list); if (error < 0) goto failed_set_error; pick_server: _debug("pick [%lx]", vc->untried); error = afs_wait_for_vl_probes(vc->server_list, vc->untried); if (error < 0) goto failed_set_error; /* Pick the untried server with the lowest RTT. */ vc->index = vc->server_list->preferred; if (test_bit(vc->index, &vc->untried)) goto selected_server; vc->index = -1; rtt = U32_MAX; for (i = 0; i < vc->server_list->nr_servers; i++) { struct afs_vlserver *s = vc->server_list->servers[i].server; |
fb72cd3d4 afs: Expose infor... |
188 |
if (!test_bit(i, &vc->untried) || |
b95b30940 afs: Don't use VL... |
189 |
!test_bit(AFS_VLSERVER_FL_RESPONDING, &s->flags)) |
3bf0fb6f3 afs: Probe multip... |
190 191 192 193 194 195 196 197 198 199 200 201 202 |
continue; if (s->probe.rtt < rtt) { vc->index = i; rtt = s->probe.rtt; } } if (vc->index == -1) goto no_more_servers; selected_server: _debug("use %d", vc->index); __clear_bit(vc->index, &vc->untried); |
0a5143f2f afs: Implement VL... |
203 204 205 206 207 208 |
/* We're starting on a different vlserver from the list. We need to * check it, find its address list and probe its capabilities before we * use it. */ ASSERTCMP(vc->ac.alist, ==, NULL); vlserver = vc->server_list->servers[vc->index].server; |
3bf0fb6f3 afs: Probe multip... |
209 |
vc->server = vlserver; |
0a5143f2f afs: Implement VL... |
210 211 212 213 214 215 216 217 218 219 |
_debug("USING VLSERVER: %s", vlserver->name); read_lock(&vlserver->lock); alist = rcu_dereference_protected(vlserver->addresses, lockdep_is_held(&vlserver->lock)); afs_get_addrlist(alist); read_unlock(&vlserver->lock); memset(&vc->ac, 0, sizeof(vc->ac)); |
0a5143f2f afs: Implement VL... |
220 221 222 223 |
if (!vc->ac.alist) vc->ac.alist = alist; else afs_put_addrlist(alist); |
3bf0fb6f3 afs: Probe multip... |
224 |
vc->ac.index = -1; |
0a5143f2f afs: Implement VL... |
225 226 227 |
iterate_address: ASSERT(vc->ac.alist); |
0a5143f2f afs: Implement VL... |
228 229 230 231 232 |
/* Iterate over the current server's address list to try and find an * address on which it will respond to us. */ if (!afs_iterate_addresses(&vc->ac)) goto next_server; |
3bf0fb6f3 afs: Probe multip... |
233 |
_debug("VL address %d/%d", vc->ac.index, vc->ac.alist->nr_addrs); |
2feeaf843 afs: Eliminate th... |
234 |
_leave(" = t %pISpc", &vc->ac.alist->addrs[vc->ac.index].transport); |
0a5143f2f afs: Implement VL... |
235 236 237 238 239 |
return true; next_server: _debug("next"); afs_end_cursor(&vc->ac); |
3bf0fb6f3 afs: Probe multip... |
240 |
goto pick_server; |
0a5143f2f afs: Implement VL... |
241 |
|
3bf0fb6f3 afs: Probe multip... |
242 |
no_more_servers: |
0a5143f2f afs: Implement VL... |
243 244 245 246 247 |
/* That's all the servers poked to no good effect. Try again if some * of them were busy. */ if (vc->flags & AFS_VL_CURSOR_RETRY) goto restart_from_beginning; |
4584ae96a afs: Fix missing ... |
248 249 |
e.error = -EDESTADDRREQ; e.responded = false; |
3bf0fb6f3 afs: Probe multip... |
250 251 |
for (i = 0; i < vc->server_list->nr_servers; i++) { struct afs_vlserver *s = vc->server_list->servers[i].server; |
3bf0fb6f3 afs: Probe multip... |
252 |
|
e4686c79b afs: Fix error ha... |
253 254 |
if (test_bit(AFS_VLSERVER_FL_RESPONDING, &s->flags)) e.responded = true; |
4584ae96a afs: Fix missing ... |
255 256 |
afs_prioritise_error(&e, READ_ONCE(s->probe.error), s->probe.abort_code); |
3bf0fb6f3 afs: Probe multip... |
257 |
} |
e4686c79b afs: Fix error ha... |
258 |
error = e.error; |
3bf0fb6f3 afs: Probe multip... |
259 260 |
failed_set_error: vc->error = error; |
0a5143f2f afs: Implement VL... |
261 262 263 264 265 266 267 268 |
failed: vc->flags |= AFS_VL_CURSOR_STOP; afs_end_cursor(&vc->ac); _leave(" = f [failed %d]", vc->error); return false; } /* |
744bcd713 afs: Allow dumpin... |
269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
* Dump cursor state in the case of the error being EDESTADDRREQ. */ static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc) { static int count; int i; if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3) return; count++; rcu_read_lock(); pr_notice("EDESTADDR occurred "); |
3bf0fb6f3 afs: Probe multip... |
283 284 285 |
pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd ", vc->untried, vc->index, vc->nr_iterations, vc->flags, vc->error); |
744bcd713 afs: Allow dumpin... |
286 287 288 289 290 291 292 293 |
if (vc->server_list) { const struct afs_vlserver_list *sl = vc->server_list; pr_notice("VC: SL nr=%u ix=%u ", sl->nr_servers, sl->index); for (i = 0; i < sl->nr_servers; i++) { const struct afs_vlserver *s = sl->servers[i].server; |
3bf0fb6f3 afs: Probe multip... |
294 295 296 |
pr_notice("VC: server %s+%hu fl=%lx E=%hd ", s->name, s->port, s->flags, s->probe.error); |
744bcd713 afs: Allow dumpin... |
297 298 299 |
if (s->addresses) { const struct afs_addr_list *a = rcu_dereference(s->addresses); |
3bf0fb6f3 afs: Probe multip... |
300 301 |
pr_notice("VC: - nr=%u/%u/%u pf=%u ", |
744bcd713 afs: Allow dumpin... |
302 |
a->nr_ipv4, a->nr_addrs, a->max_addrs, |
3bf0fb6f3 afs: Probe multip... |
303 |
a->preferred); |
be59167c8 afs: Remove some ... |
304 305 306 |
pr_notice("VC: - R=%lx F=%lx ", a->responded, a->failed); |
744bcd713 afs: Allow dumpin... |
307 308 309 310 311 312 |
if (a == vc->ac.alist) pr_notice("VC: - current "); } } } |
3bf0fb6f3 afs: Probe multip... |
313 314 315 316 |
pr_notice("AC: t=%lx ax=%u ac=%d er=%d r=%u ni=%u ", vc->ac.tried, vc->ac.index, vc->ac.abort_code, vc->ac.error, vc->ac.responded, vc->ac.nr_iterations); |
744bcd713 afs: Allow dumpin... |
317 318 319 320 |
rcu_read_unlock(); } /* |
0a5143f2f afs: Implement VL... |
321 322 323 324 325 |
* Tidy up a volume location server cursor and unlock the vnode. */ int afs_end_vlserver_operation(struct afs_vl_cursor *vc) { struct afs_net *net = vc->cell->net; |
744bcd713 afs: Allow dumpin... |
326 |
if (vc->error == -EDESTADDRREQ || |
4584ae96a afs: Fix missing ... |
327 |
vc->error == -EADDRNOTAVAIL || |
744bcd713 afs: Allow dumpin... |
328 329 330 |
vc->error == -ENETUNREACH || vc->error == -EHOSTUNREACH) afs_vl_dump_edestaddrreq(vc); |
0a5143f2f afs: Implement VL... |
331 332 333 334 335 336 337 338 |
afs_end_cursor(&vc->ac); afs_put_vlserverlist(net, vc->server_list); if (vc->error == -ECONNABORTED) vc->error = afs_abort_to_error(vc->ac.abort_code); return vc->error; } |