xref: /linux/fs/afs/vl_rotate.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
1b4d0d230SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20a5143f2SDavid Howells /* Handle vlserver selection and rotation.
30a5143f2SDavid Howells  *
40a5143f2SDavid Howells  * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
50a5143f2SDavid Howells  * Written by David Howells (dhowells@redhat.com)
60a5143f2SDavid Howells  */
70a5143f2SDavid Howells 
80a5143f2SDavid Howells #include <linux/kernel.h>
90a5143f2SDavid Howells #include <linux/sched.h>
100a5143f2SDavid Howells #include <linux/sched/signal.h>
110a5143f2SDavid Howells #include "internal.h"
120a5143f2SDavid Howells #include "afs_vl.h"
130a5143f2SDavid Howells 
140a5143f2SDavid Howells /*
150a5143f2SDavid Howells  * Begin an operation on a volume location server.
160a5143f2SDavid Howells  */
afs_begin_vlserver_operation(struct afs_vl_cursor * vc,struct afs_cell * cell,struct key * key)170a5143f2SDavid Howells bool afs_begin_vlserver_operation(struct afs_vl_cursor *vc, struct afs_cell *cell,
180a5143f2SDavid Howells 				  struct key *key)
190a5143f2SDavid Howells {
2098f9fda2SDavid Howells 	static atomic_t debug_ids;
2198f9fda2SDavid Howells 
220a5143f2SDavid Howells 	memset(vc, 0, sizeof(*vc));
230a5143f2SDavid Howells 	vc->cell = cell;
240a5143f2SDavid Howells 	vc->key = key;
25aa453becSDavid Howells 	vc->cumul_error.error = -EDESTADDRREQ;
26aa453becSDavid Howells 	vc->nr_iterations = -1;
270a5143f2SDavid Howells 
280a5143f2SDavid Howells 	if (signal_pending(current)) {
29aa453becSDavid Howells 		vc->cumul_error.error = -EINTR;
300a5143f2SDavid Howells 		vc->flags |= AFS_VL_CURSOR_STOP;
310a5143f2SDavid Howells 		return false;
320a5143f2SDavid Howells 	}
330a5143f2SDavid Howells 
3498f9fda2SDavid Howells 	vc->debug_id = atomic_inc_return(&debug_ids);
350a5143f2SDavid Howells 	return true;
360a5143f2SDavid Howells }
370a5143f2SDavid Howells 
380a5143f2SDavid Howells /*
390a5143f2SDavid Howells  * Begin iteration through a server list, starting with the last used server if
400a5143f2SDavid Howells  * possible, or the last recorded good server if not.
410a5143f2SDavid Howells  */
afs_start_vl_iteration(struct afs_vl_cursor * vc)420a5143f2SDavid Howells static bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
430a5143f2SDavid Howells {
440a5143f2SDavid Howells 	struct afs_cell *cell = vc->cell;
45d5c32c89SDavid Howells 	unsigned int dns_lookup_count;
460a5143f2SDavid Howells 
47d5c32c89SDavid Howells 	if (cell->dns_source == DNS_RECORD_UNAVAILABLE ||
48d5c32c89SDavid Howells 	    cell->dns_expiry <= ktime_get_real_seconds()) {
49d5c32c89SDavid Howells 		dns_lookup_count = smp_load_acquire(&cell->dns_lookup_count);
50d5c32c89SDavid Howells 		set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
51dca54a7bSDavid Howells 		afs_queue_cell(cell, afs_cell_trace_get_queue_dns);
52d5c32c89SDavid Howells 
53d5c32c89SDavid Howells 		if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
54d5c32c89SDavid Howells 			if (wait_var_event_interruptible(
55d5c32c89SDavid Howells 				    &cell->dns_lookup_count,
56d5c32c89SDavid Howells 				    smp_load_acquire(&cell->dns_lookup_count)
57d5c32c89SDavid Howells 				    != dns_lookup_count) < 0) {
58aa453becSDavid Howells 				vc->cumul_error.error = -ERESTARTSYS;
590a5143f2SDavid Howells 				return false;
600a5143f2SDavid Howells 			}
61d5c32c89SDavid Howells 		}
62d5c32c89SDavid Howells 
63d5c32c89SDavid Howells 		/* Status load is ordered after lookup counter load */
640167236eSDavid Howells 		if (cell->dns_status == DNS_LOOKUP_GOT_NOT_FOUND) {
650167236eSDavid Howells 			pr_warn("No record of cell %s\n", cell->name);
66aa453becSDavid Howells 			vc->cumul_error.error = -ENOENT;
670167236eSDavid Howells 			return false;
680167236eSDavid Howells 		}
690167236eSDavid Howells 
70d5c32c89SDavid Howells 		if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
71aa453becSDavid Howells 			vc->cumul_error.error = -EDESTADDRREQ;
72d5c32c89SDavid Howells 			return false;
73d5c32c89SDavid Howells 		}
74d5c32c89SDavid Howells 	}
750a5143f2SDavid Howells 
760a5143f2SDavid Howells 	read_lock(&cell->vl_servers_lock);
770a5143f2SDavid Howells 	vc->server_list = afs_get_vlserverlist(
780a5143f2SDavid Howells 		rcu_dereference_protected(cell->vl_servers,
790a5143f2SDavid Howells 					  lockdep_is_held(&cell->vl_servers_lock)));
800a5143f2SDavid Howells 	read_unlock(&cell->vl_servers_lock);
81ca1cbbdcSDavid Howells 	if (!vc->server_list->nr_servers)
820a5143f2SDavid Howells 		return false;
830a5143f2SDavid Howells 
84905b8615SDavid Howells 	vc->untried_servers = (1UL << vc->server_list->nr_servers) - 1;
85905b8615SDavid Howells 	vc->server_index = -1;
860a5143f2SDavid Howells 	return true;
870a5143f2SDavid Howells }
880a5143f2SDavid Howells 
890a5143f2SDavid Howells /*
900a5143f2SDavid Howells  * Select the vlserver to use.  May be called multiple times to rotate
910a5143f2SDavid Howells  * through the vlservers.
920a5143f2SDavid Howells  */
afs_select_vlserver(struct afs_vl_cursor * vc)930a5143f2SDavid Howells bool afs_select_vlserver(struct afs_vl_cursor *vc)
940a5143f2SDavid Howells {
9598f9fda2SDavid Howells 	struct afs_addr_list *alist = vc->alist;
960a5143f2SDavid Howells 	struct afs_vlserver *vlserver;
9798f9fda2SDavid Howells 	unsigned long set, failed;
9872904d7bSDavid Howells 	unsigned int rtt;
99aa453becSDavid Howells 	s32 abort_code = vc->call_abort_code;
100aa453becSDavid Howells 	int error = vc->call_error, i;
101aa453becSDavid Howells 
102aa453becSDavid Howells 	vc->nr_iterations++;
1030a5143f2SDavid Howells 
10498f9fda2SDavid Howells 	_enter("VC=%x+%x,%d{%lx},%d{%lx},%d,%d",
10598f9fda2SDavid Howells 	       vc->debug_id, vc->nr_iterations, vc->server_index, vc->untried_servers,
10698f9fda2SDavid Howells 	       vc->addr_index, vc->addr_tried,
107aa453becSDavid Howells 	       error, abort_code);
1080a5143f2SDavid Howells 
1090a5143f2SDavid Howells 	if (vc->flags & AFS_VL_CURSOR_STOP) {
1100a5143f2SDavid Howells 		_leave(" = f [stopped]");
1110a5143f2SDavid Howells 		return false;
1120a5143f2SDavid Howells 	}
1130a5143f2SDavid Howells 
114aa453becSDavid Howells 	if (vc->nr_iterations == 0)
115aa453becSDavid Howells 		goto start;
116744bcd71SDavid Howells 
117*af9a5b49SDavid Howells 	WRITE_ONCE(alist->addrs[vc->addr_index].last_error, error);
118*af9a5b49SDavid Howells 
1190a5143f2SDavid Howells 	/* Evaluate the result of the previous operation, if there was one. */
1200a5143f2SDavid Howells 	switch (error) {
1210a5143f2SDavid Howells 	default:
1220a5143f2SDavid Howells 	case 0:
1230a5143f2SDavid Howells 		/* Success or local failure.  Stop. */
124aa453becSDavid Howells 		vc->cumul_error.error = error;
1250a5143f2SDavid Howells 		vc->flags |= AFS_VL_CURSOR_STOP;
126aa453becSDavid Howells 		_leave(" = f [okay/local %d]", vc->cumul_error.error);
1270a5143f2SDavid Howells 		return false;
1280a5143f2SDavid Howells 
1290a5143f2SDavid Howells 	case -ECONNABORTED:
1300a5143f2SDavid Howells 		/* The far side rejected the operation on some grounds.  This
1310a5143f2SDavid Howells 		 * might involve the server being busy or the volume having been moved.
1320a5143f2SDavid Howells 		 */
133aa453becSDavid Howells 		switch (abort_code) {
1340a5143f2SDavid Howells 		case AFSVL_IO:
1350a5143f2SDavid Howells 		case AFSVL_BADVOLOPER:
1360a5143f2SDavid Howells 		case AFSVL_NOMEM:
1370a5143f2SDavid Howells 			/* The server went weird. */
138aa453becSDavid Howells 			afs_prioritise_error(&vc->cumul_error, -EREMOTEIO, abort_code);
1390a5143f2SDavid Howells 			//write_lock(&vc->cell->vl_servers_lock);
140905b8615SDavid Howells 			//vc->server_list->weird_mask |= 1 << vc->server_index;
1410a5143f2SDavid Howells 			//write_unlock(&vc->cell->vl_servers_lock);
1420a5143f2SDavid Howells 			goto next_server;
1430a5143f2SDavid Howells 
1440a5143f2SDavid Howells 		default:
145aa453becSDavid Howells 			afs_prioritise_error(&vc->cumul_error, error, abort_code);
1460a5143f2SDavid Howells 			goto failed;
1470a5143f2SDavid Howells 		}
1480a5143f2SDavid Howells 
1494584ae96SDavid Howells 	case -ERFKILL:
1504584ae96SDavid Howells 	case -EADDRNOTAVAIL:
1510a5143f2SDavid Howells 	case -ENETUNREACH:
1520a5143f2SDavid Howells 	case -EHOSTUNREACH:
1534584ae96SDavid Howells 	case -EHOSTDOWN:
1540a5143f2SDavid Howells 	case -ECONNREFUSED:
1550a5143f2SDavid Howells 	case -ETIMEDOUT:
1560a5143f2SDavid Howells 	case -ETIME:
1570a5143f2SDavid Howells 		_debug("no conn %d", error);
158aa453becSDavid Howells 		afs_prioritise_error(&vc->cumul_error, error, 0);
1590a5143f2SDavid Howells 		goto iterate_address;
1600a5143f2SDavid Howells 
1610a5143f2SDavid Howells 	case -ECONNRESET:
1620a5143f2SDavid Howells 		_debug("call reset");
163aa453becSDavid Howells 		afs_prioritise_error(&vc->cumul_error, error, 0);
1640a5143f2SDavid Howells 		vc->flags |= AFS_VL_CURSOR_RETRY;
1650a5143f2SDavid Howells 		goto next_server;
1666dfdf536SDavid Howells 
1676dfdf536SDavid Howells 	case -EOPNOTSUPP:
1686dfdf536SDavid Howells 		_debug("notsupp");
1696dfdf536SDavid Howells 		goto next_server;
1700a5143f2SDavid Howells 	}
1710a5143f2SDavid Howells 
1720a5143f2SDavid Howells restart_from_beginning:
1730a5143f2SDavid Howells 	_debug("restart");
17498f9fda2SDavid Howells 	if (vc->call_responded &&
17598f9fda2SDavid Howells 	    vc->addr_index != vc->alist->preferred &&
17698f9fda2SDavid Howells 	    test_bit(alist->preferred, &vc->addr_tried))
17798f9fda2SDavid Howells 		WRITE_ONCE(alist->preferred, vc->addr_index);
17898f9fda2SDavid Howells 	afs_put_addrlist(alist, afs_alist_trace_put_vlrotate_restart);
17998f9fda2SDavid Howells 	alist = vc->alist = NULL;
18098f9fda2SDavid Howells 
1810a5143f2SDavid Howells 	afs_put_vlserverlist(vc->cell->net, vc->server_list);
1820a5143f2SDavid Howells 	vc->server_list = NULL;
1830a5143f2SDavid Howells 	if (vc->flags & AFS_VL_CURSOR_RETRIED)
1840a5143f2SDavid Howells 		goto failed;
1850a5143f2SDavid Howells 	vc->flags |= AFS_VL_CURSOR_RETRIED;
1860a5143f2SDavid Howells start:
1870a5143f2SDavid Howells 	_debug("start");
18898f9fda2SDavid Howells 	ASSERTCMP(alist, ==, NULL);
1890a5143f2SDavid Howells 
1900a5143f2SDavid Howells 	if (!afs_start_vl_iteration(vc))
1910a5143f2SDavid Howells 		goto failed;
1920a5143f2SDavid Howells 
1933bf0fb6fSDavid Howells 	error = afs_send_vl_probes(vc->cell->net, vc->key, vc->server_list);
194aa453becSDavid Howells 	if (error < 0) {
195aa453becSDavid Howells 		afs_prioritise_error(&vc->cumul_error, error, 0);
196aa453becSDavid Howells 		goto failed;
197aa453becSDavid Howells 	}
1983bf0fb6fSDavid Howells 
1993bf0fb6fSDavid Howells pick_server:
200905b8615SDavid Howells 	_debug("pick [%lx]", vc->untried_servers);
20198f9fda2SDavid Howells 	ASSERTCMP(alist, ==, NULL);
2023bf0fb6fSDavid Howells 
203905b8615SDavid Howells 	error = afs_wait_for_vl_probes(vc->server_list, vc->untried_servers);
204aa453becSDavid Howells 	if (error < 0) {
205aa453becSDavid Howells 		afs_prioritise_error(&vc->cumul_error, error, 0);
206aa453becSDavid Howells 		goto failed;
207aa453becSDavid Howells 	}
2083bf0fb6fSDavid Howells 
2093bf0fb6fSDavid Howells 	/* Pick the untried server with the lowest RTT. */
210905b8615SDavid Howells 	vc->server_index = vc->server_list->preferred;
211905b8615SDavid Howells 	if (test_bit(vc->server_index, &vc->untried_servers))
2123bf0fb6fSDavid Howells 		goto selected_server;
2133bf0fb6fSDavid Howells 
214905b8615SDavid Howells 	vc->server_index = -1;
21572904d7bSDavid Howells 	rtt = UINT_MAX;
2163bf0fb6fSDavid Howells 	for (i = 0; i < vc->server_list->nr_servers; i++) {
2173bf0fb6fSDavid Howells 		struct afs_vlserver *s = vc->server_list->servers[i].server;
2183bf0fb6fSDavid Howells 
219905b8615SDavid Howells 		if (!test_bit(i, &vc->untried_servers) ||
220b95b3094SDavid Howells 		    !test_bit(AFS_VLSERVER_FL_RESPONDING, &s->flags))
2213bf0fb6fSDavid Howells 			continue;
222a2aff7b5SDavid Howells 		if (s->probe.rtt <= rtt) {
223905b8615SDavid Howells 			vc->server_index = i;
2243bf0fb6fSDavid Howells 			rtt = s->probe.rtt;
2253bf0fb6fSDavid Howells 		}
2263bf0fb6fSDavid Howells 	}
2273bf0fb6fSDavid Howells 
228905b8615SDavid Howells 	if (vc->server_index == -1)
2293bf0fb6fSDavid Howells 		goto no_more_servers;
2303bf0fb6fSDavid Howells 
2313bf0fb6fSDavid Howells selected_server:
232905b8615SDavid Howells 	_debug("use %d", vc->server_index);
233905b8615SDavid Howells 	__clear_bit(vc->server_index, &vc->untried_servers);
2343bf0fb6fSDavid Howells 
2350a5143f2SDavid Howells 	/* We're starting on a different vlserver from the list.  We need to
2360a5143f2SDavid Howells 	 * check it, find its address list and probe its capabilities before we
2370a5143f2SDavid Howells 	 * use it.
2380a5143f2SDavid Howells 	 */
239905b8615SDavid Howells 	vlserver = vc->server_list->servers[vc->server_index].server;
2403bf0fb6fSDavid Howells 	vc->server = vlserver;
2410a5143f2SDavid Howells 
2420a5143f2SDavid Howells 	_debug("USING VLSERVER: %s", vlserver->name);
2430a5143f2SDavid Howells 
2440a5143f2SDavid Howells 	read_lock(&vlserver->lock);
2450a5143f2SDavid Howells 	alist = rcu_dereference_protected(vlserver->addresses,
2460a5143f2SDavid Howells 					  lockdep_is_held(&vlserver->lock));
24798f9fda2SDavid Howells 	vc->alist = afs_get_addrlist(alist, afs_alist_trace_get_vlrotate_set);
2480a5143f2SDavid Howells 	read_unlock(&vlserver->lock);
2490a5143f2SDavid Howells 
25098f9fda2SDavid Howells 	vc->addr_tried = 0;
25198f9fda2SDavid Howells 	vc->addr_index = -1;
2520a5143f2SDavid Howells 
2530a5143f2SDavid Howells iterate_address:
2540a5143f2SDavid Howells 	/* Iterate over the current server's address list to try and find an
2550a5143f2SDavid Howells 	 * address on which it will respond to us.
2560a5143f2SDavid Howells 	 */
25798f9fda2SDavid Howells 	set = READ_ONCE(alist->responded);
25898f9fda2SDavid Howells 	failed = READ_ONCE(alist->probe_failed);
25998f9fda2SDavid Howells 	vc->addr_index = READ_ONCE(alist->preferred);
26098f9fda2SDavid Howells 
26198f9fda2SDavid Howells 	_debug("%lx-%lx-%lx,%d", set, failed, vc->addr_tried, vc->addr_index);
26298f9fda2SDavid Howells 
26398f9fda2SDavid Howells 	set &= ~(failed | vc->addr_tried);
26498f9fda2SDavid Howells 
26598f9fda2SDavid Howells 	if (!set)
2660a5143f2SDavid Howells 		goto next_server;
2670a5143f2SDavid Howells 
26898f9fda2SDavid Howells 	if (!test_bit(vc->addr_index, &set))
26998f9fda2SDavid Howells 		vc->addr_index = __ffs(set);
27098f9fda2SDavid Howells 
27198f9fda2SDavid Howells 	set_bit(vc->addr_index, &vc->addr_tried);
27298f9fda2SDavid Howells 	vc->alist = alist;
27398f9fda2SDavid Howells 
27498f9fda2SDavid Howells 	_debug("VL address %d/%d", vc->addr_index, alist->nr_addrs);
2753bf0fb6fSDavid Howells 
276aa453becSDavid Howells 	vc->call_responded = false;
27798f9fda2SDavid Howells 	_leave(" = t %pISpc", rxrpc_kernel_remote_addr(alist->addrs[vc->addr_index].peer));
2780a5143f2SDavid Howells 	return true;
2790a5143f2SDavid Howells 
2800a5143f2SDavid Howells next_server:
2810a5143f2SDavid Howells 	_debug("next");
28298f9fda2SDavid Howells 	ASSERT(alist);
28398f9fda2SDavid Howells 	if (vc->call_responded &&
28498f9fda2SDavid Howells 	    vc->addr_index != alist->preferred &&
28598f9fda2SDavid Howells 	    test_bit(alist->preferred, &vc->addr_tried))
28698f9fda2SDavid Howells 		WRITE_ONCE(alist->preferred, vc->addr_index);
28798f9fda2SDavid Howells 	afs_put_addrlist(alist, afs_alist_trace_put_vlrotate_next);
28898f9fda2SDavid Howells 	alist = vc->alist = NULL;
2893bf0fb6fSDavid Howells 	goto pick_server;
2900a5143f2SDavid Howells 
2913bf0fb6fSDavid Howells no_more_servers:
2920a5143f2SDavid Howells 	/* That's all the servers poked to no good effect.  Try again if some
2930a5143f2SDavid Howells 	 * of them were busy.
2940a5143f2SDavid Howells 	 */
2950a5143f2SDavid Howells 	if (vc->flags & AFS_VL_CURSOR_RETRY)
2960a5143f2SDavid Howells 		goto restart_from_beginning;
2970a5143f2SDavid Howells 
2983bf0fb6fSDavid Howells 	for (i = 0; i < vc->server_list->nr_servers; i++) {
2993bf0fb6fSDavid Howells 		struct afs_vlserver *s = vc->server_list->servers[i].server;
3000a5143f2SDavid Howells 
301e4686c79SDavid Howells 		if (test_bit(AFS_VLSERVER_FL_RESPONDING, &s->flags))
302aa453becSDavid Howells 			vc->cumul_error.responded = true;
303aa453becSDavid Howells 		afs_prioritise_error(&vc->cumul_error, READ_ONCE(s->probe.error),
3044584ae96SDavid Howells 				     s->probe.abort_code);
3053bf0fb6fSDavid Howells 	}
3063bf0fb6fSDavid Howells 
3070a5143f2SDavid Howells failed:
30898f9fda2SDavid Howells 	if (alist) {
30998f9fda2SDavid Howells 		if (vc->call_responded &&
31098f9fda2SDavid Howells 		    vc->addr_index != alist->preferred &&
31198f9fda2SDavid Howells 		    test_bit(alist->preferred, &vc->addr_tried))
31298f9fda2SDavid Howells 			WRITE_ONCE(alist->preferred, vc->addr_index);
31398f9fda2SDavid Howells 		afs_put_addrlist(alist, afs_alist_trace_put_vlrotate_fail);
31498f9fda2SDavid Howells 		alist = vc->alist = NULL;
31598f9fda2SDavid Howells 	}
3160a5143f2SDavid Howells 	vc->flags |= AFS_VL_CURSOR_STOP;
317aa453becSDavid Howells 	_leave(" = f [failed %d]", vc->cumul_error.error);
3180a5143f2SDavid Howells 	return false;
3190a5143f2SDavid Howells }
3200a5143f2SDavid Howells 
3210a5143f2SDavid Howells /*
322744bcd71SDavid Howells  * Dump cursor state in the case of the error being EDESTADDRREQ.
323744bcd71SDavid Howells  */
afs_vl_dump_edestaddrreq(const struct afs_vl_cursor * vc)324744bcd71SDavid Howells static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
325744bcd71SDavid Howells {
3260167236eSDavid Howells 	struct afs_cell *cell = vc->cell;
327744bcd71SDavid Howells 	static int count;
328744bcd71SDavid Howells 	int i;
329744bcd71SDavid Howells 
330744bcd71SDavid Howells 	if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3)
331744bcd71SDavid Howells 		return;
332744bcd71SDavid Howells 	count++;
333744bcd71SDavid Howells 
334744bcd71SDavid Howells 	rcu_read_lock();
335744bcd71SDavid Howells 	pr_notice("EDESTADDR occurred\n");
3360167236eSDavid Howells 	pr_notice("CELL: %s err=%d\n", cell->name, cell->error);
3370167236eSDavid Howells 	pr_notice("DNS: src=%u st=%u lc=%x\n",
3380167236eSDavid Howells 		  cell->dns_source, cell->dns_status, cell->dns_lookup_count);
3393bf0fb6fSDavid Howells 	pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd\n",
34098f9fda2SDavid Howells 		  vc->untried_servers, vc->server_index, vc->nr_iterations,
34198f9fda2SDavid Howells 		  vc->flags, vc->cumul_error.error);
342aa453becSDavid Howells 	pr_notice("VC: call  er=%d ac=%d r=%u\n",
343aa453becSDavid Howells 		  vc->call_error, vc->call_abort_code, vc->call_responded);
344744bcd71SDavid Howells 
345744bcd71SDavid Howells 	if (vc->server_list) {
346744bcd71SDavid Howells 		const struct afs_vlserver_list *sl = vc->server_list;
347744bcd71SDavid Howells 		pr_notice("VC: SL nr=%u ix=%u\n",
348744bcd71SDavid Howells 			  sl->nr_servers, sl->index);
349744bcd71SDavid Howells 		for (i = 0; i < sl->nr_servers; i++) {
350744bcd71SDavid Howells 			const struct afs_vlserver *s = sl->servers[i].server;
3513bf0fb6fSDavid Howells 			pr_notice("VC: server %s+%hu fl=%lx E=%hd\n",
3523bf0fb6fSDavid Howells 				  s->name, s->port, s->flags, s->probe.error);
353744bcd71SDavid Howells 			if (s->addresses) {
354744bcd71SDavid Howells 				const struct afs_addr_list *a =
355744bcd71SDavid Howells 					rcu_dereference(s->addresses);
3563bf0fb6fSDavid Howells 				pr_notice("VC:  - nr=%u/%u/%u pf=%u\n",
357744bcd71SDavid Howells 					  a->nr_ipv4, a->nr_addrs, a->max_addrs,
3583bf0fb6fSDavid Howells 					  a->preferred);
359be59167cSDavid Howells 				pr_notice("VC:  - R=%lx F=%lx\n",
360aa4917d6SDavid Howells 					  a->responded, a->probe_failed);
36198f9fda2SDavid Howells 				if (a == vc->alist)
362744bcd71SDavid Howells 					pr_notice("VC:  - current\n");
363744bcd71SDavid Howells 			}
364744bcd71SDavid Howells 		}
365744bcd71SDavid Howells 	}
366744bcd71SDavid Howells 
36798f9fda2SDavid Howells 	pr_notice("AC: t=%lx ax=%u\n", vc->addr_tried, vc->addr_index);
368744bcd71SDavid Howells 	rcu_read_unlock();
369744bcd71SDavid Howells }
370744bcd71SDavid Howells 
371744bcd71SDavid Howells /*
3720a5143f2SDavid Howells  * Tidy up a volume location server cursor and unlock the vnode.
3730a5143f2SDavid Howells  */
afs_end_vlserver_operation(struct afs_vl_cursor * vc)3740a5143f2SDavid Howells int afs_end_vlserver_operation(struct afs_vl_cursor *vc)
3750a5143f2SDavid Howells {
3760a5143f2SDavid Howells 	struct afs_net *net = vc->cell->net;
3770a5143f2SDavid Howells 
37898f9fda2SDavid Howells 	_enter("VC=%x+%x", vc->debug_id, vc->nr_iterations);
37998f9fda2SDavid Howells 
380aa453becSDavid Howells 	switch (vc->cumul_error.error) {
381aa453becSDavid Howells 	case -EDESTADDRREQ:
382aa453becSDavid Howells 	case -EADDRNOTAVAIL:
383aa453becSDavid Howells 	case -ENETUNREACH:
384aa453becSDavid Howells 	case -EHOSTUNREACH:
385744bcd71SDavid Howells 		afs_vl_dump_edestaddrreq(vc);
386aa453becSDavid Howells 		break;
387aa453becSDavid Howells 	}
388744bcd71SDavid Howells 
38998f9fda2SDavid Howells 	if (vc->alist) {
39098f9fda2SDavid Howells 		if (vc->call_responded &&
39198f9fda2SDavid Howells 		    vc->addr_index != vc->alist->preferred &&
39298f9fda2SDavid Howells 		    test_bit(vc->alist->preferred, &vc->addr_tried))
39398f9fda2SDavid Howells 			WRITE_ONCE(vc->alist->preferred, vc->addr_index);
39498f9fda2SDavid Howells 		afs_put_addrlist(vc->alist, afs_alist_trace_put_vlrotate_end);
39598f9fda2SDavid Howells 		vc->alist = NULL;
39698f9fda2SDavid Howells 	}
3970a5143f2SDavid Howells 	afs_put_vlserverlist(net, vc->server_list);
398aa453becSDavid Howells 	return vc->cumul_error.error;
3990a5143f2SDavid Howells }
400