diff options
author | David Howells <dhowells@redhat.com> | 2020-04-22 02:02:46 +0300 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2020-06-04 17:37:58 +0300 |
commit | 8409f67b6437c4b327ee95a71081b9c7bfee0b00 (patch) | |
tree | 79e150c5ad3a0f22f03cebc6dd25fdd9d0473f4f /fs/afs/rotate.c | |
parent | 32275d3f758f1252511709b77b3bab060a0e1d4f (diff) | |
download | linux-8409f67b6437c4b327ee95a71081b9c7bfee0b00.tar.xz |
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.c | 29 |
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); |