summaryrefslogtreecommitdiffstats
path: root/fs/afs/rotate.c
diff options
context:
space:
mode:
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);