diff options
author | David Howells <dhowells@redhat.com> | 2020-04-22 01:02:46 +0200 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2020-06-04 16:37:58 +0200 |
commit | 8409f67b6437c4b327ee95a71081b9c7bfee0b00 (patch) | |
tree | 79e150c5ad3a0f22f03cebc6dd25fdd9d0473f4f /fs/afs/fs_probe.c | |
parent | afs: Show more a bit more server state in /proc/net/afs/servers (diff) | |
download | linux-8409f67b6437c4b327ee95a71081b9c7bfee0b00.tar.xz linux-8409f67b6437c4b327ee95a71081b9c7bfee0b00.zip |
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/fs_probe.c')
-rw-r--r-- | fs/afs/fs_probe.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index c41cf3b2ab89..b34f74b0f319 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c @@ -339,6 +339,18 @@ static void afs_dispatch_fs_probe(struct afs_net *net, struct afs_server *server } /* + * Probe a server immediately without waiting for its due time to come + * round. This is used when all of the addresses have been tried. + */ +void afs_probe_fileserver(struct afs_net *net, struct afs_server *server) +{ + write_seqlock(&net->fs_lock); + if (!list_empty(&server->probe_link)) + return afs_dispatch_fs_probe(net, server, true); + write_sequnlock(&net->fs_lock); +} + +/* * Probe dispatcher to regularly dispatch probes to keep NAT alive. */ void afs_fs_probe_dispatcher(struct work_struct *work) @@ -411,3 +423,38 @@ again: _leave(" [quiesce]"); } } + +/* + * Wait for a probe on a particular fileserver to complete for 2s. + */ +int afs_wait_for_one_fs_probe(struct afs_server *server, bool is_intr) +{ + struct wait_queue_entry wait; + unsigned long timo = 2 * HZ; + + if (atomic_read(&server->probe_outstanding) == 0) + goto dont_wait; + + init_wait_entry(&wait, 0); + for (;;) { + prepare_to_wait_event(&server->probe_wq, &wait, + is_intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); + if (timo == 0 || + server->probe.responded || + atomic_read(&server->probe_outstanding) == 0 || + (is_intr && signal_pending(current))) + break; + timo = schedule_timeout(timo); + } + + finish_wait(&server->probe_wq, &wait); + +dont_wait: + if (server->probe.responded) + return 0; + if (is_intr && signal_pending(current)) + return -ERESTARTSYS; + if (timo == 0) + return -ETIME; + return -EDESTADDRREQ; +} |