1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* AFS vlserver probing
4 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
8 #include <linux/sched.h>
9 #include <linux/slab.h>
12 #include "protocol_yfs.h"
16 * Handle the completion of a set of probes.
18 static void afs_finished_vl_probe(struct afs_vlserver
*server
)
20 if (!(server
->probe
.flags
& AFS_VLSERVER_PROBE_RESPONDED
)) {
21 server
->rtt
= UINT_MAX
;
22 clear_bit(AFS_VLSERVER_FL_RESPONDING
, &server
->flags
);
25 clear_bit_unlock(AFS_VLSERVER_FL_PROBING
, &server
->flags
);
26 wake_up_bit(&server
->flags
, AFS_VLSERVER_FL_PROBING
);
30 * Handle the completion of a probe RPC call.
32 static void afs_done_one_vl_probe(struct afs_vlserver
*server
, bool wake_up
)
34 if (atomic_dec_and_test(&server
->probe_outstanding
)) {
35 afs_finished_vl_probe(server
);
40 wake_up_all(&server
->probe_wq
);
44 * Process the result of probing a vlserver. This is called after successful
45 * or failed delivery of an VL.GetCapabilities operation.
47 void afs_vlserver_probe_result(struct afs_call
*call
)
49 struct afs_addr_list
*alist
= call
->alist
;
50 struct afs_vlserver
*server
= call
->vlserver
;
51 unsigned int server_index
= call
->server_index
;
52 unsigned int rtt_us
= 0;
53 unsigned int index
= call
->addr_ix
;
54 bool have_result
= false;
55 int ret
= call
->error
;
57 _enter("%s,%u,%u,%d,%d", server
->name
, server_index
, index
, ret
, call
->abort_code
);
59 spin_lock(&server
->probe_lock
);
63 server
->probe
.error
= 0;
66 if (!(server
->probe
.flags
& AFS_VLSERVER_PROBE_RESPONDED
)) {
67 server
->probe
.abort_code
= call
->abort_code
;
68 server
->probe
.error
= ret
;
76 server
->probe
.flags
|= AFS_VLSERVER_PROBE_LOCAL_FAILURE
;
77 if (server
->probe
.error
== 0)
78 server
->probe
.error
= ret
;
79 trace_afs_io_error(call
->debug_id
, ret
, afs_io_error_vl_probe_fail
);
81 case -ECONNRESET
: /* Responded, but call expired. */
91 clear_bit(index
, &alist
->responded
);
92 set_bit(index
, &alist
->failed
);
93 if (!(server
->probe
.flags
& AFS_VLSERVER_PROBE_RESPONDED
) &&
94 (server
->probe
.error
== 0 ||
95 server
->probe
.error
== -ETIMEDOUT
||
96 server
->probe
.error
== -ETIME
))
97 server
->probe
.error
= ret
;
98 trace_afs_io_error(call
->debug_id
, ret
, afs_io_error_vl_probe_fail
);
103 set_bit(index
, &alist
->responded
);
104 clear_bit(index
, &alist
->failed
);
106 if (call
->service_id
== YFS_VL_SERVICE
) {
107 server
->probe
.flags
|= AFS_VLSERVER_PROBE_IS_YFS
;
108 set_bit(AFS_VLSERVER_FL_IS_YFS
, &server
->flags
);
109 alist
->addrs
[index
].srx_service
= call
->service_id
;
111 server
->probe
.flags
|= AFS_VLSERVER_PROBE_NOT_YFS
;
112 if (!(server
->probe
.flags
& AFS_VLSERVER_PROBE_IS_YFS
)) {
113 clear_bit(AFS_VLSERVER_FL_IS_YFS
, &server
->flags
);
114 alist
->addrs
[index
].srx_service
= call
->service_id
;
118 if (rxrpc_kernel_get_srtt(call
->net
->socket
, call
->rxcall
, &rtt_us
) &&
119 rtt_us
< server
->probe
.rtt
) {
120 server
->probe
.rtt
= rtt_us
;
121 server
->rtt
= rtt_us
;
122 alist
->preferred
= index
;
125 smp_wmb(); /* Set rtt before responded. */
126 server
->probe
.flags
|= AFS_VLSERVER_PROBE_RESPONDED
;
127 set_bit(AFS_VLSERVER_FL_PROBED
, &server
->flags
);
128 set_bit(AFS_VLSERVER_FL_RESPONDING
, &server
->flags
);
131 spin_unlock(&server
->probe_lock
);
133 _debug("probe [%u][%u] %pISpc rtt=%u ret=%d",
134 server_index
, index
, &alist
->addrs
[index
].transport
, rtt_us
, ret
);
136 afs_done_one_vl_probe(server
, have_result
);
140 * Probe all of a vlserver's addresses to find out the best route and to
141 * query its capabilities.
143 static bool afs_do_probe_vlserver(struct afs_net
*net
,
144 struct afs_vlserver
*server
,
146 unsigned int server_index
,
147 struct afs_error
*_e
)
149 struct afs_addr_cursor ac
= {
152 struct afs_call
*call
;
153 bool in_progress
= false;
155 _enter("%s", server
->name
);
157 read_lock(&server
->lock
);
158 ac
.alist
= rcu_dereference_protected(server
->addresses
,
159 lockdep_is_held(&server
->lock
));
160 read_unlock(&server
->lock
);
162 atomic_set(&server
->probe_outstanding
, ac
.alist
->nr_addrs
);
163 memset(&server
->probe
, 0, sizeof(server
->probe
));
164 server
->probe
.rtt
= UINT_MAX
;
166 for (ac
.index
= 0; ac
.index
< ac
.alist
->nr_addrs
; ac
.index
++) {
167 call
= afs_vl_get_capabilities(net
, &ac
, key
, server
,
173 afs_prioritise_error(_e
, PTR_ERR(call
), ac
.abort_code
);
174 afs_done_one_vl_probe(server
, false);
182 * Send off probes to all unprobed servers.
184 int afs_send_vl_probes(struct afs_net
*net
, struct key
*key
,
185 struct afs_vlserver_list
*vllist
)
187 struct afs_vlserver
*server
;
189 bool in_progress
= false;
194 for (i
= 0; i
< vllist
->nr_servers
; i
++) {
195 server
= vllist
->servers
[i
].server
;
196 if (test_bit(AFS_VLSERVER_FL_PROBED
, &server
->flags
))
199 if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING
, &server
->flags
) &&
200 afs_do_probe_vlserver(net
, server
, key
, i
, &e
))
204 return in_progress
? 0 : e
.error
;
208 * Wait for the first as-yet untried server to respond.
210 int afs_wait_for_vl_probes(struct afs_vlserver_list
*vllist
,
211 unsigned long untried
)
213 struct wait_queue_entry
*waits
;
214 struct afs_vlserver
*server
;
215 unsigned int rtt
= UINT_MAX
, rtt_s
;
216 bool have_responders
= false;
219 _enter("%u,%lx", vllist
->nr_servers
, untried
);
221 /* Only wait for servers that have a probe outstanding. */
222 for (i
= 0; i
< vllist
->nr_servers
; i
++) {
223 if (test_bit(i
, &untried
)) {
224 server
= vllist
->servers
[i
].server
;
225 if (!test_bit(AFS_VLSERVER_FL_PROBING
, &server
->flags
))
226 __clear_bit(i
, &untried
);
227 if (server
->probe
.flags
& AFS_VLSERVER_PROBE_RESPONDED
)
228 have_responders
= true;
231 if (have_responders
|| !untried
)
234 waits
= kmalloc(array_size(vllist
->nr_servers
, sizeof(*waits
)), GFP_KERNEL
);
238 for (i
= 0; i
< vllist
->nr_servers
; i
++) {
239 if (test_bit(i
, &untried
)) {
240 server
= vllist
->servers
[i
].server
;
241 init_waitqueue_entry(&waits
[i
], current
);
242 add_wait_queue(&server
->probe_wq
, &waits
[i
]);
247 bool still_probing
= false;
249 set_current_state(TASK_INTERRUPTIBLE
);
250 for (i
= 0; i
< vllist
->nr_servers
; i
++) {
251 if (test_bit(i
, &untried
)) {
252 server
= vllist
->servers
[i
].server
;
253 if (server
->probe
.flags
& AFS_VLSERVER_PROBE_RESPONDED
)
255 if (test_bit(AFS_VLSERVER_FL_PROBING
, &server
->flags
))
256 still_probing
= true;
260 if (!still_probing
|| signal_pending(current
))
266 set_current_state(TASK_RUNNING
);
268 for (i
= 0; i
< vllist
->nr_servers
; i
++) {
269 if (test_bit(i
, &untried
)) {
270 server
= vllist
->servers
[i
].server
;
271 rtt_s
= READ_ONCE(server
->rtt
);
272 if (test_bit(AFS_VLSERVER_FL_RESPONDING
, &server
->flags
) &&
278 remove_wait_queue(&server
->probe_wq
, &waits
[i
]);
284 if (pref
== -1 && signal_pending(current
))
288 vllist
->preferred
= pref
;
290 _leave(" = 0 [%u]", pref
);