1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* AFS fileserver 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"
14 static bool afs_fs_probe_done(struct afs_server
*server
)
16 if (!atomic_dec_and_test(&server
->probe_outstanding
))
19 wake_up_var(&server
->probe_outstanding
);
20 clear_bit_unlock(AFS_SERVER_FL_PROBING
, &server
->flags
);
21 wake_up_bit(&server
->flags
, AFS_SERVER_FL_PROBING
);
26 * Process the result of probing a fileserver. This is called after successful
27 * or failed delivery of an FS.GetCapabilities operation.
29 void afs_fileserver_probe_result(struct afs_call
*call
)
31 struct afs_addr_list
*alist
= call
->alist
;
32 struct afs_server
*server
= call
->server
;
33 unsigned int server_index
= call
->server_index
;
34 unsigned int index
= call
->addr_ix
;
35 unsigned int rtt
= UINT_MAX
;
36 bool have_result
= false;
38 int ret
= call
->error
;
40 _enter("%pU,%u", &server
->uuid
, index
);
42 spin_lock(&server
->probe_lock
);
46 server
->probe
.error
= 0;
49 if (!server
->probe
.responded
) {
50 server
->probe
.abort_code
= call
->abort_code
;
51 server
->probe
.error
= ret
;
56 server
->probe
.local_failure
= true;
57 afs_io_error(call
, afs_io_error_fs_probe_fail
);
59 case -ECONNRESET
: /* Responded, but call expired. */
69 clear_bit(index
, &alist
->responded
);
70 set_bit(index
, &alist
->failed
);
71 if (!server
->probe
.responded
&&
72 (server
->probe
.error
== 0 ||
73 server
->probe
.error
== -ETIMEDOUT
||
74 server
->probe
.error
== -ETIME
))
75 server
->probe
.error
= ret
;
76 afs_io_error(call
, afs_io_error_fs_probe_fail
);
81 set_bit(index
, &alist
->responded
);
82 clear_bit(index
, &alist
->failed
);
84 if (call
->service_id
== YFS_FS_SERVICE
) {
85 server
->probe
.is_yfs
= true;
86 set_bit(AFS_SERVER_FL_IS_YFS
, &server
->flags
);
87 alist
->addrs
[index
].srx_service
= call
->service_id
;
89 server
->probe
.not_yfs
= true;
90 if (!server
->probe
.is_yfs
) {
91 clear_bit(AFS_SERVER_FL_IS_YFS
, &server
->flags
);
92 alist
->addrs
[index
].srx_service
= call
->service_id
;
96 /* Get the RTT and scale it to fit into a 32-bit value that represents
97 * over a minute of time so that we can access it with one instruction
100 _rtt
= rxrpc_kernel_get_rtt(call
->net
->socket
, call
->rxcall
);
102 rtt
= (_rtt
> UINT_MAX
) ? UINT_MAX
: _rtt
;
103 if (rtt
< server
->probe
.rtt
) {
104 server
->probe
.rtt
= rtt
;
105 alist
->preferred
= index
;
109 smp_wmb(); /* Set rtt before responded. */
110 server
->probe
.responded
= true;
111 set_bit(AFS_SERVER_FL_PROBED
, &server
->flags
);
113 spin_unlock(&server
->probe_lock
);
115 _debug("probe [%u][%u] %pISpc rtt=%u ret=%d",
116 server_index
, index
, &alist
->addrs
[index
].transport
,
117 (unsigned int)rtt
, ret
);
119 have_result
|= afs_fs_probe_done(server
);
121 server
->probe
.have_result
= true;
122 wake_up_var(&server
->probe
.have_result
);
123 wake_up_all(&server
->probe_wq
);
128 * Probe all of a fileserver's addresses to find out the best route and to
129 * query its capabilities.
131 static int afs_do_probe_fileserver(struct afs_net
*net
,
132 struct afs_server
*server
,
134 unsigned int server_index
,
135 struct afs_error
*_e
)
137 struct afs_addr_cursor ac
= {
140 struct afs_call
*call
;
141 bool in_progress
= false;
143 _enter("%pU", &server
->uuid
);
145 read_lock(&server
->fs_lock
);
146 ac
.alist
= rcu_dereference_protected(server
->addresses
,
147 lockdep_is_held(&server
->fs_lock
));
148 afs_get_addrlist(ac
.alist
);
149 read_unlock(&server
->fs_lock
);
151 atomic_set(&server
->probe_outstanding
, ac
.alist
->nr_addrs
);
152 memset(&server
->probe
, 0, sizeof(server
->probe
));
153 server
->probe
.rtt
= UINT_MAX
;
155 for (ac
.index
= 0; ac
.index
< ac
.alist
->nr_addrs
; ac
.index
++) {
156 call
= afs_fs_get_capabilities(net
, server
, &ac
, key
, server_index
);
161 afs_prioritise_error(_e
, PTR_ERR(call
), ac
.abort_code
);
166 afs_fs_probe_done(server
);
167 afs_put_addrlist(ac
.alist
);
172 * Send off probes to all unprobed servers.
174 int afs_probe_fileservers(struct afs_net
*net
, struct key
*key
,
175 struct afs_server_list
*list
)
177 struct afs_server
*server
;
179 bool in_progress
= false;
184 for (i
= 0; i
< list
->nr_servers
; i
++) {
185 server
= list
->servers
[i
].server
;
186 if (test_bit(AFS_SERVER_FL_PROBED
, &server
->flags
))
189 if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING
, &server
->flags
) &&
190 afs_do_probe_fileserver(net
, server
, key
, i
, &e
))
194 return in_progress
? 0 : e
.error
;
198 * Wait for the first as-yet untried fileserver to respond.
200 int afs_wait_for_fs_probes(struct afs_server_list
*slist
, unsigned long untried
)
202 struct wait_queue_entry
*waits
;
203 struct afs_server
*server
;
204 unsigned int rtt
= UINT_MAX
;
205 bool have_responders
= false;
208 _enter("%u,%lx", slist
->nr_servers
, untried
);
210 /* Only wait for servers that have a probe outstanding. */
211 for (i
= 0; i
< slist
->nr_servers
; i
++) {
212 if (test_bit(i
, &untried
)) {
213 server
= slist
->servers
[i
].server
;
214 if (!test_bit(AFS_SERVER_FL_PROBING
, &server
->flags
))
215 __clear_bit(i
, &untried
);
216 if (server
->probe
.responded
)
217 have_responders
= true;
220 if (have_responders
|| !untried
)
223 waits
= kmalloc(array_size(slist
->nr_servers
, sizeof(*waits
)), GFP_KERNEL
);
227 for (i
= 0; i
< slist
->nr_servers
; i
++) {
228 if (test_bit(i
, &untried
)) {
229 server
= slist
->servers
[i
].server
;
230 init_waitqueue_entry(&waits
[i
], current
);
231 add_wait_queue(&server
->probe_wq
, &waits
[i
]);
236 bool still_probing
= false;
238 set_current_state(TASK_INTERRUPTIBLE
);
239 for (i
= 0; i
< slist
->nr_servers
; i
++) {
240 if (test_bit(i
, &untried
)) {
241 server
= slist
->servers
[i
].server
;
242 if (server
->probe
.responded
)
244 if (test_bit(AFS_SERVER_FL_PROBING
, &server
->flags
))
245 still_probing
= true;
249 if (!still_probing
|| signal_pending(current
))
255 set_current_state(TASK_RUNNING
);
257 for (i
= 0; i
< slist
->nr_servers
; i
++) {
258 if (test_bit(i
, &untried
)) {
259 server
= slist
->servers
[i
].server
;
260 if (server
->probe
.responded
&&
261 server
->probe
.rtt
< rtt
) {
263 rtt
= server
->probe
.rtt
;
266 remove_wait_queue(&server
->probe_wq
, &waits
[i
]);
272 if (pref
== -1 && signal_pending(current
))
276 slist
->preferred
= pref
;