summaryrefslogtreecommitdiff
path: root/fs/afs/vl_rotate.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-10-20 02:57:58 +0300
committerDavid Howells <dhowells@redhat.com>2018-10-24 02:41:09 +0300
commit744bcd713a4eabb248246f7deccfad30c579b7f5 (patch)
tree60470fca4f54503cb844f02d12f25a4c67529972 /fs/afs/vl_rotate.c
parent30062bd13e3659a309d249a06d5f4ebb4a5c5251 (diff)
downloadlinux-744bcd713a4eabb248246f7deccfad30c579b7f5.tar.xz
afs: Allow dumping of server cursor on operation failure
Provide an option to allow the file or volume location server cursor to be dumped if the rotation routine falls off the end without managing to contact a server. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/vl_rotate.c')
-rw-r--r--fs/afs/vl_rotate.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/fs/afs/vl_rotate.c b/fs/afs/vl_rotate.c
index 44a936ad9c7a..5b99ea7be194 100644
--- a/fs/afs/vl_rotate.c
+++ b/fs/afs/vl_rotate.c
@@ -83,6 +83,8 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
return false;
}
+ vc->nr_iterations++;
+
/* Evaluate the result of the previous operation, if there was one. */
switch (error) {
case SHRT_MAX:
@@ -235,12 +237,63 @@ failed:
}
/*
+ * Dump cursor state in the case of the error being EDESTADDRREQ.
+ */
+static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
+{
+ static int count;
+ int i;
+
+ if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3)
+ return;
+ count++;
+
+ rcu_read_lock();
+ pr_notice("EDESTADDR occurred\n");
+ pr_notice("VC: st=%u ix=%u ni=%hu fl=%hx err=%hd\n",
+ vc->start, vc->index, vc->nr_iterations, vc->flags, vc->error);
+
+ if (vc->server_list) {
+ const struct afs_vlserver_list *sl = vc->server_list;
+ pr_notice("VC: SL nr=%u ix=%u\n",
+ sl->nr_servers, sl->index);
+ for (i = 0; i < sl->nr_servers; i++) {
+ const struct afs_vlserver *s = sl->servers[i].server;
+ pr_notice("VC: server fl=%lx %s+%hu\n",
+ s->flags, s->name, s->port);
+ if (s->addresses) {
+ const struct afs_addr_list *a =
+ rcu_dereference(s->addresses);
+ pr_notice("VC: - av=%u nr=%u/%u/%u ax=%u\n",
+ a->version,
+ a->nr_ipv4, a->nr_addrs, a->max_addrs,
+ a->index);
+ pr_notice("VC: - pr=%lx yf=%lx\n",
+ a->probed, a->yfs);
+ if (a == vc->ac.alist)
+ pr_notice("VC: - current\n");
+ }
+ }
+ }
+
+ pr_notice("AC: as=%u ax=%u ac=%d er=%d b=%u r=%u ni=%hu\n",
+ vc->ac.start, vc->ac.index, vc->ac.abort_code, vc->ac.error,
+ vc->ac.begun, vc->ac.responded, vc->ac.nr_iterations);
+ rcu_read_unlock();
+}
+
+/*
* Tidy up a volume location server cursor and unlock the vnode.
*/
int afs_end_vlserver_operation(struct afs_vl_cursor *vc)
{
struct afs_net *net = vc->cell->net;
+ if (vc->error == -EDESTADDRREQ ||
+ vc->error == -ENETUNREACH ||
+ vc->error == -EHOSTUNREACH)
+ afs_vl_dump_edestaddrreq(vc);
+
afs_end_cursor(&vc->ac);
afs_put_vlserverlist(net, vc->server_list);