summaryrefslogtreecommitdiff
path: root/fs/afs/rotate.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2020-04-22 00:02:46 +0100
committerDavid Howells <dhowells@redhat.com>2020-06-04 15:37:58 +0100
commit8409f67b6437c4b327ee95a71081b9c7bfee0b00 (patch)
tree79e150c5ad3a0f22f03cebc6dd25fdd9d0473f4f /fs/afs/rotate.c
parent32275d3f758f1252511709b77b3bab060a0e1d4f (diff)
afs: Adjust the fileserver rotation algorithm to reprobe/retry more quickly
Adjust the fileserver rotation algorithm so that if we've tried all the addresses on a server (cumulatively over multiple operations) until we've run out of untried addresses, immediately reprobe all that server's interfaces and retry the op at least once before we move onto the next server. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/rotate.c')
-rw-r--r--fs/afs/rotate.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c
index 14863678ae9e..6a0935cb822f 100644
--- a/fs/afs/rotate.c
+++ b/fs/afs/rotate.c
@@ -369,6 +369,7 @@ selected_server:
_debug("USING SERVER: %pU", &server->uuid);
+ op->flags |= AFS_OPERATION_RETRY_SERVER;
op->server = server;
if (vnode->cb_server != server) {
vnode->cb_server = server;
@@ -383,6 +384,7 @@ selected_server:
afs_get_addrlist(alist);
read_unlock(&server->fs_lock);
+retry_server:
memset(&op->ac, 0, sizeof(op->ac));
if (!op->ac.alist)
@@ -398,13 +400,36 @@ iterate_address:
* address on which it will respond to us.
*/
if (!afs_iterate_addresses(&op->ac))
- goto next_server;
+ goto out_of_addresses;
- _debug("address [%u] %u/%u", op->index, op->ac.index, op->ac.alist->nr_addrs);
+ _debug("address [%u] %u/%u %pISp",
+ op->index, op->ac.index, op->ac.alist->nr_addrs,
+ &op->ac.alist->addrs[op->ac.index].transport);
_leave(" = t");
return true;
+out_of_addresses:
+ /* We've now had a failure to respond on all of a server's addresses -
+ * immediately probe them again and consider retrying the server.
+ */
+ afs_probe_fileserver(op->net, op->server);
+ if (op->flags & AFS_OPERATION_RETRY_SERVER) {
+ alist = op->ac.alist;
+ error = afs_wait_for_one_fs_probe(
+ op->server, !(op->flags & AFS_OPERATION_UNINTR));
+ switch (error) {
+ case 0:
+ op->flags &= ~AFS_OPERATION_RETRY_SERVER;
+ goto retry_server;
+ case -ERESTARTSYS:
+ goto failed_set_error;
+ case -ETIME:
+ case -EDESTADDRREQ:
+ goto next_server;
+ }
+ }
+
next_server:
_debug("next");
afs_end_cursor(&op->ac);