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