xref: /kernel/linux/linux-5.10/fs/afs/vl_rotate.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* Handle vlserver selection and rotation.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/sched.h>
108c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
118c2ecf20Sopenharmony_ci#include "internal.h"
128c2ecf20Sopenharmony_ci#include "afs_vl.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci/*
158c2ecf20Sopenharmony_ci * Begin an operation on a volume location server.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_cibool afs_begin_vlserver_operation(struct afs_vl_cursor *vc, struct afs_cell *cell,
188c2ecf20Sopenharmony_ci				  struct key *key)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	memset(vc, 0, sizeof(*vc));
218c2ecf20Sopenharmony_ci	vc->cell = cell;
228c2ecf20Sopenharmony_ci	vc->key = key;
238c2ecf20Sopenharmony_ci	vc->error = -EDESTADDRREQ;
248c2ecf20Sopenharmony_ci	vc->ac.error = SHRT_MAX;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	if (signal_pending(current)) {
278c2ecf20Sopenharmony_ci		vc->error = -EINTR;
288c2ecf20Sopenharmony_ci		vc->flags |= AFS_VL_CURSOR_STOP;
298c2ecf20Sopenharmony_ci		return false;
308c2ecf20Sopenharmony_ci	}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	return true;
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/*
368c2ecf20Sopenharmony_ci * Begin iteration through a server list, starting with the last used server if
378c2ecf20Sopenharmony_ci * possible, or the last recorded good server if not.
388c2ecf20Sopenharmony_ci */
398c2ecf20Sopenharmony_cistatic bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct afs_cell *cell = vc->cell;
428c2ecf20Sopenharmony_ci	unsigned int dns_lookup_count;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	if (cell->dns_source == DNS_RECORD_UNAVAILABLE ||
458c2ecf20Sopenharmony_ci	    cell->dns_expiry <= ktime_get_real_seconds()) {
468c2ecf20Sopenharmony_ci		dns_lookup_count = smp_load_acquire(&cell->dns_lookup_count);
478c2ecf20Sopenharmony_ci		set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
488c2ecf20Sopenharmony_ci		afs_queue_cell(cell, afs_cell_trace_get_queue_dns);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci		if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
518c2ecf20Sopenharmony_ci			if (wait_var_event_interruptible(
528c2ecf20Sopenharmony_ci				    &cell->dns_lookup_count,
538c2ecf20Sopenharmony_ci				    smp_load_acquire(&cell->dns_lookup_count)
548c2ecf20Sopenharmony_ci				    != dns_lookup_count) < 0) {
558c2ecf20Sopenharmony_ci				vc->error = -ERESTARTSYS;
568c2ecf20Sopenharmony_ci				return false;
578c2ecf20Sopenharmony_ci			}
588c2ecf20Sopenharmony_ci		}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci		/* Status load is ordered after lookup counter load */
618c2ecf20Sopenharmony_ci		if (cell->dns_status == DNS_LOOKUP_GOT_NOT_FOUND) {
628c2ecf20Sopenharmony_ci			pr_warn("No record of cell %s\n", cell->name);
638c2ecf20Sopenharmony_ci			vc->error = -ENOENT;
648c2ecf20Sopenharmony_ci			return false;
658c2ecf20Sopenharmony_ci		}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci		if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
688c2ecf20Sopenharmony_ci			vc->error = -EDESTADDRREQ;
698c2ecf20Sopenharmony_ci			return false;
708c2ecf20Sopenharmony_ci		}
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	read_lock(&cell->vl_servers_lock);
748c2ecf20Sopenharmony_ci	vc->server_list = afs_get_vlserverlist(
758c2ecf20Sopenharmony_ci		rcu_dereference_protected(cell->vl_servers,
768c2ecf20Sopenharmony_ci					  lockdep_is_held(&cell->vl_servers_lock)));
778c2ecf20Sopenharmony_ci	read_unlock(&cell->vl_servers_lock);
788c2ecf20Sopenharmony_ci	if (!vc->server_list->nr_servers)
798c2ecf20Sopenharmony_ci		return false;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	vc->untried = (1UL << vc->server_list->nr_servers) - 1;
828c2ecf20Sopenharmony_ci	vc->index = -1;
838c2ecf20Sopenharmony_ci	return true;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci/*
878c2ecf20Sopenharmony_ci * Select the vlserver to use.  May be called multiple times to rotate
888c2ecf20Sopenharmony_ci * through the vlservers.
898c2ecf20Sopenharmony_ci */
908c2ecf20Sopenharmony_cibool afs_select_vlserver(struct afs_vl_cursor *vc)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	struct afs_addr_list *alist;
938c2ecf20Sopenharmony_ci	struct afs_vlserver *vlserver;
948c2ecf20Sopenharmony_ci	struct afs_error e;
958c2ecf20Sopenharmony_ci	u32 rtt;
968c2ecf20Sopenharmony_ci	int error = vc->ac.error, i;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	_enter("%lx[%d],%lx[%d],%d,%d",
998c2ecf20Sopenharmony_ci	       vc->untried, vc->index,
1008c2ecf20Sopenharmony_ci	       vc->ac.tried, vc->ac.index,
1018c2ecf20Sopenharmony_ci	       error, vc->ac.abort_code);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (vc->flags & AFS_VL_CURSOR_STOP) {
1048c2ecf20Sopenharmony_ci		_leave(" = f [stopped]");
1058c2ecf20Sopenharmony_ci		return false;
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	vc->nr_iterations++;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	/* Evaluate the result of the previous operation, if there was one. */
1118c2ecf20Sopenharmony_ci	switch (error) {
1128c2ecf20Sopenharmony_ci	case SHRT_MAX:
1138c2ecf20Sopenharmony_ci		goto start;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	default:
1168c2ecf20Sopenharmony_ci	case 0:
1178c2ecf20Sopenharmony_ci		/* Success or local failure.  Stop. */
1188c2ecf20Sopenharmony_ci		vc->error = error;
1198c2ecf20Sopenharmony_ci		vc->flags |= AFS_VL_CURSOR_STOP;
1208c2ecf20Sopenharmony_ci		_leave(" = f [okay/local %d]", vc->ac.error);
1218c2ecf20Sopenharmony_ci		return false;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	case -ECONNABORTED:
1248c2ecf20Sopenharmony_ci		/* The far side rejected the operation on some grounds.  This
1258c2ecf20Sopenharmony_ci		 * might involve the server being busy or the volume having been moved.
1268c2ecf20Sopenharmony_ci		 */
1278c2ecf20Sopenharmony_ci		switch (vc->ac.abort_code) {
1288c2ecf20Sopenharmony_ci		case AFSVL_IO:
1298c2ecf20Sopenharmony_ci		case AFSVL_BADVOLOPER:
1308c2ecf20Sopenharmony_ci		case AFSVL_NOMEM:
1318c2ecf20Sopenharmony_ci			/* The server went weird. */
1328c2ecf20Sopenharmony_ci			vc->error = -EREMOTEIO;
1338c2ecf20Sopenharmony_ci			//write_lock(&vc->cell->vl_servers_lock);
1348c2ecf20Sopenharmony_ci			//vc->server_list->weird_mask |= 1 << vc->index;
1358c2ecf20Sopenharmony_ci			//write_unlock(&vc->cell->vl_servers_lock);
1368c2ecf20Sopenharmony_ci			goto next_server;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci		default:
1398c2ecf20Sopenharmony_ci			vc->error = afs_abort_to_error(vc->ac.abort_code);
1408c2ecf20Sopenharmony_ci			goto failed;
1418c2ecf20Sopenharmony_ci		}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	case -ERFKILL:
1448c2ecf20Sopenharmony_ci	case -EADDRNOTAVAIL:
1458c2ecf20Sopenharmony_ci	case -ENETUNREACH:
1468c2ecf20Sopenharmony_ci	case -EHOSTUNREACH:
1478c2ecf20Sopenharmony_ci	case -EHOSTDOWN:
1488c2ecf20Sopenharmony_ci	case -ECONNREFUSED:
1498c2ecf20Sopenharmony_ci	case -ETIMEDOUT:
1508c2ecf20Sopenharmony_ci	case -ETIME:
1518c2ecf20Sopenharmony_ci		_debug("no conn %d", error);
1528c2ecf20Sopenharmony_ci		vc->error = error;
1538c2ecf20Sopenharmony_ci		goto iterate_address;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	case -ECONNRESET:
1568c2ecf20Sopenharmony_ci		_debug("call reset");
1578c2ecf20Sopenharmony_ci		vc->error = error;
1588c2ecf20Sopenharmony_ci		vc->flags |= AFS_VL_CURSOR_RETRY;
1598c2ecf20Sopenharmony_ci		goto next_server;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	case -EOPNOTSUPP:
1628c2ecf20Sopenharmony_ci		_debug("notsupp");
1638c2ecf20Sopenharmony_ci		goto next_server;
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cirestart_from_beginning:
1678c2ecf20Sopenharmony_ci	_debug("restart");
1688c2ecf20Sopenharmony_ci	afs_end_cursor(&vc->ac);
1698c2ecf20Sopenharmony_ci	afs_put_vlserverlist(vc->cell->net, vc->server_list);
1708c2ecf20Sopenharmony_ci	vc->server_list = NULL;
1718c2ecf20Sopenharmony_ci	if (vc->flags & AFS_VL_CURSOR_RETRIED)
1728c2ecf20Sopenharmony_ci		goto failed;
1738c2ecf20Sopenharmony_ci	vc->flags |= AFS_VL_CURSOR_RETRIED;
1748c2ecf20Sopenharmony_cistart:
1758c2ecf20Sopenharmony_ci	_debug("start");
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	if (!afs_start_vl_iteration(vc))
1788c2ecf20Sopenharmony_ci		goto failed;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	error = afs_send_vl_probes(vc->cell->net, vc->key, vc->server_list);
1818c2ecf20Sopenharmony_ci	if (error < 0)
1828c2ecf20Sopenharmony_ci		goto failed_set_error;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cipick_server:
1858c2ecf20Sopenharmony_ci	_debug("pick [%lx]", vc->untried);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	error = afs_wait_for_vl_probes(vc->server_list, vc->untried);
1888c2ecf20Sopenharmony_ci	if (error < 0)
1898c2ecf20Sopenharmony_ci		goto failed_set_error;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* Pick the untried server with the lowest RTT. */
1928c2ecf20Sopenharmony_ci	vc->index = vc->server_list->preferred;
1938c2ecf20Sopenharmony_ci	if (test_bit(vc->index, &vc->untried))
1948c2ecf20Sopenharmony_ci		goto selected_server;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	vc->index = -1;
1978c2ecf20Sopenharmony_ci	rtt = U32_MAX;
1988c2ecf20Sopenharmony_ci	for (i = 0; i < vc->server_list->nr_servers; i++) {
1998c2ecf20Sopenharmony_ci		struct afs_vlserver *s = vc->server_list->servers[i].server;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		if (!test_bit(i, &vc->untried) ||
2028c2ecf20Sopenharmony_ci		    !test_bit(AFS_VLSERVER_FL_RESPONDING, &s->flags))
2038c2ecf20Sopenharmony_ci			continue;
2048c2ecf20Sopenharmony_ci		if (s->probe.rtt < rtt) {
2058c2ecf20Sopenharmony_ci			vc->index = i;
2068c2ecf20Sopenharmony_ci			rtt = s->probe.rtt;
2078c2ecf20Sopenharmony_ci		}
2088c2ecf20Sopenharmony_ci	}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	if (vc->index == -1)
2118c2ecf20Sopenharmony_ci		goto no_more_servers;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ciselected_server:
2148c2ecf20Sopenharmony_ci	_debug("use %d", vc->index);
2158c2ecf20Sopenharmony_ci	__clear_bit(vc->index, &vc->untried);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	/* We're starting on a different vlserver from the list.  We need to
2188c2ecf20Sopenharmony_ci	 * check it, find its address list and probe its capabilities before we
2198c2ecf20Sopenharmony_ci	 * use it.
2208c2ecf20Sopenharmony_ci	 */
2218c2ecf20Sopenharmony_ci	ASSERTCMP(vc->ac.alist, ==, NULL);
2228c2ecf20Sopenharmony_ci	vlserver = vc->server_list->servers[vc->index].server;
2238c2ecf20Sopenharmony_ci	vc->server = vlserver;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	_debug("USING VLSERVER: %s", vlserver->name);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	read_lock(&vlserver->lock);
2288c2ecf20Sopenharmony_ci	alist = rcu_dereference_protected(vlserver->addresses,
2298c2ecf20Sopenharmony_ci					  lockdep_is_held(&vlserver->lock));
2308c2ecf20Sopenharmony_ci	afs_get_addrlist(alist);
2318c2ecf20Sopenharmony_ci	read_unlock(&vlserver->lock);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	memset(&vc->ac, 0, sizeof(vc->ac));
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (!vc->ac.alist)
2368c2ecf20Sopenharmony_ci		vc->ac.alist = alist;
2378c2ecf20Sopenharmony_ci	else
2388c2ecf20Sopenharmony_ci		afs_put_addrlist(alist);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	vc->ac.index = -1;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ciiterate_address:
2438c2ecf20Sopenharmony_ci	ASSERT(vc->ac.alist);
2448c2ecf20Sopenharmony_ci	/* Iterate over the current server's address list to try and find an
2458c2ecf20Sopenharmony_ci	 * address on which it will respond to us.
2468c2ecf20Sopenharmony_ci	 */
2478c2ecf20Sopenharmony_ci	if (!afs_iterate_addresses(&vc->ac))
2488c2ecf20Sopenharmony_ci		goto next_server;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	_debug("VL address %d/%d", vc->ac.index, vc->ac.alist->nr_addrs);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	_leave(" = t %pISpc", &vc->ac.alist->addrs[vc->ac.index].transport);
2538c2ecf20Sopenharmony_ci	return true;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cinext_server:
2568c2ecf20Sopenharmony_ci	_debug("next");
2578c2ecf20Sopenharmony_ci	afs_end_cursor(&vc->ac);
2588c2ecf20Sopenharmony_ci	goto pick_server;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cino_more_servers:
2618c2ecf20Sopenharmony_ci	/* That's all the servers poked to no good effect.  Try again if some
2628c2ecf20Sopenharmony_ci	 * of them were busy.
2638c2ecf20Sopenharmony_ci	 */
2648c2ecf20Sopenharmony_ci	if (vc->flags & AFS_VL_CURSOR_RETRY)
2658c2ecf20Sopenharmony_ci		goto restart_from_beginning;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	e.error = -EDESTADDRREQ;
2688c2ecf20Sopenharmony_ci	e.responded = false;
2698c2ecf20Sopenharmony_ci	for (i = 0; i < vc->server_list->nr_servers; i++) {
2708c2ecf20Sopenharmony_ci		struct afs_vlserver *s = vc->server_list->servers[i].server;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		if (test_bit(AFS_VLSERVER_FL_RESPONDING, &s->flags))
2738c2ecf20Sopenharmony_ci			e.responded = true;
2748c2ecf20Sopenharmony_ci		afs_prioritise_error(&e, READ_ONCE(s->probe.error),
2758c2ecf20Sopenharmony_ci				     s->probe.abort_code);
2768c2ecf20Sopenharmony_ci	}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	error = e.error;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cifailed_set_error:
2818c2ecf20Sopenharmony_ci	vc->error = error;
2828c2ecf20Sopenharmony_cifailed:
2838c2ecf20Sopenharmony_ci	vc->flags |= AFS_VL_CURSOR_STOP;
2848c2ecf20Sopenharmony_ci	afs_end_cursor(&vc->ac);
2858c2ecf20Sopenharmony_ci	_leave(" = f [failed %d]", vc->error);
2868c2ecf20Sopenharmony_ci	return false;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci/*
2908c2ecf20Sopenharmony_ci * Dump cursor state in the case of the error being EDESTADDRREQ.
2918c2ecf20Sopenharmony_ci */
2928c2ecf20Sopenharmony_cistatic void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
2938c2ecf20Sopenharmony_ci{
2948c2ecf20Sopenharmony_ci	struct afs_cell *cell = vc->cell;
2958c2ecf20Sopenharmony_ci	static int count;
2968c2ecf20Sopenharmony_ci	int i;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3)
2998c2ecf20Sopenharmony_ci		return;
3008c2ecf20Sopenharmony_ci	count++;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	rcu_read_lock();
3038c2ecf20Sopenharmony_ci	pr_notice("EDESTADDR occurred\n");
3048c2ecf20Sopenharmony_ci	pr_notice("CELL: %s err=%d\n", cell->name, cell->error);
3058c2ecf20Sopenharmony_ci	pr_notice("DNS: src=%u st=%u lc=%x\n",
3068c2ecf20Sopenharmony_ci		  cell->dns_source, cell->dns_status, cell->dns_lookup_count);
3078c2ecf20Sopenharmony_ci	pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd\n",
3088c2ecf20Sopenharmony_ci		  vc->untried, vc->index, vc->nr_iterations, vc->flags, vc->error);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	if (vc->server_list) {
3118c2ecf20Sopenharmony_ci		const struct afs_vlserver_list *sl = vc->server_list;
3128c2ecf20Sopenharmony_ci		pr_notice("VC: SL nr=%u ix=%u\n",
3138c2ecf20Sopenharmony_ci			  sl->nr_servers, sl->index);
3148c2ecf20Sopenharmony_ci		for (i = 0; i < sl->nr_servers; i++) {
3158c2ecf20Sopenharmony_ci			const struct afs_vlserver *s = sl->servers[i].server;
3168c2ecf20Sopenharmony_ci			pr_notice("VC: server %s+%hu fl=%lx E=%hd\n",
3178c2ecf20Sopenharmony_ci				  s->name, s->port, s->flags, s->probe.error);
3188c2ecf20Sopenharmony_ci			if (s->addresses) {
3198c2ecf20Sopenharmony_ci				const struct afs_addr_list *a =
3208c2ecf20Sopenharmony_ci					rcu_dereference(s->addresses);
3218c2ecf20Sopenharmony_ci				pr_notice("VC:  - nr=%u/%u/%u pf=%u\n",
3228c2ecf20Sopenharmony_ci					  a->nr_ipv4, a->nr_addrs, a->max_addrs,
3238c2ecf20Sopenharmony_ci					  a->preferred);
3248c2ecf20Sopenharmony_ci				pr_notice("VC:  - R=%lx F=%lx\n",
3258c2ecf20Sopenharmony_ci					  a->responded, a->failed);
3268c2ecf20Sopenharmony_ci				if (a == vc->ac.alist)
3278c2ecf20Sopenharmony_ci					pr_notice("VC:  - current\n");
3288c2ecf20Sopenharmony_ci			}
3298c2ecf20Sopenharmony_ci		}
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	pr_notice("AC: t=%lx ax=%u ac=%d er=%d r=%u ni=%u\n",
3338c2ecf20Sopenharmony_ci		  vc->ac.tried, vc->ac.index, vc->ac.abort_code, vc->ac.error,
3348c2ecf20Sopenharmony_ci		  vc->ac.responded, vc->ac.nr_iterations);
3358c2ecf20Sopenharmony_ci	rcu_read_unlock();
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci/*
3398c2ecf20Sopenharmony_ci * Tidy up a volume location server cursor and unlock the vnode.
3408c2ecf20Sopenharmony_ci */
3418c2ecf20Sopenharmony_ciint afs_end_vlserver_operation(struct afs_vl_cursor *vc)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	struct afs_net *net = vc->cell->net;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if (vc->error == -EDESTADDRREQ ||
3468c2ecf20Sopenharmony_ci	    vc->error == -EADDRNOTAVAIL ||
3478c2ecf20Sopenharmony_ci	    vc->error == -ENETUNREACH ||
3488c2ecf20Sopenharmony_ci	    vc->error == -EHOSTUNREACH)
3498c2ecf20Sopenharmony_ci		afs_vl_dump_edestaddrreq(vc);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	afs_end_cursor(&vc->ac);
3528c2ecf20Sopenharmony_ci	afs_put_vlserverlist(net, vc->server_list);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	if (vc->error == -ECONNABORTED)
3558c2ecf20Sopenharmony_ci		vc->error = afs_abort_to_error(vc->ac.abort_code);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return vc->error;
3588c2ecf20Sopenharmony_ci}
359