diff options
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); |