]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
afs: Allow dumping of server cursor on operation failure
authorDavid Howells <dhowells@redhat.com>
Fri, 19 Oct 2018 23:57:58 +0000 (00:57 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 23 Oct 2018 23:41:09 +0000 (00:41 +0100)
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>
fs/afs/Kconfig
fs/afs/addr_list.c
fs/afs/internal.h
fs/afs/rotate.c
fs/afs/vl_rotate.c

index ebba3b18e5da6dd5ff7d27cd248218937ab19a0f..701aaa9b18994a1e789adad6e7544817c320bc2b 100644 (file)
@@ -27,3 +27,15 @@ config AFS_FSCACHE
        help
          Say Y here if you want AFS data to be cached locally on disk through
          the generic filesystem cache manager
+
+config AFS_DEBUG_CURSOR
+       bool "AFS server cursor debugging"
+       depends on AFS_FS
+       help
+         Say Y here to cause the contents of a server cursor to be dumped to
+         the dmesg log if the server rotation algorithm fails to successfully
+         contact a server.
+
+         See <file:Documentation/filesystems/afs.txt> for more information.
+
+         If unsure, say N.
index 3f60b4012587374041a7a2ba8a696df9e340ed58..bc5ce31a4ae45a9c960e6ef472ffb54ec8c1ea7e 100644 (file)
@@ -358,6 +358,8 @@ bool afs_iterate_addresses(struct afs_addr_cursor *ac)
        if (!ac->alist)
                return false;
 
+       ac->nr_iterations++;
+
        if (ac->begun) {
                ac->index++;
                if (ac->index == ac->alist->nr_addrs)
index ce79bd514331c48a932831bf313d47db5fccb802..ac9da1e4050ea5cba8da7fd767ae6b09b6138891 100644 (file)
@@ -660,6 +660,7 @@ struct afs_addr_cursor {
        short                   error;
        bool                    begun;          /* T if we've begun iteration */
        bool                    responded;      /* T if the current address responded */
+       unsigned short          nr_iterations;  /* Number of address iterations */
 };
 
 /*
@@ -677,6 +678,7 @@ struct afs_vl_cursor {
 #define AFS_VL_CURSOR_STOP     0x0001          /* Set to cease iteration */
 #define AFS_VL_CURSOR_RETRY    0x0002          /* Set to do a retry */
 #define AFS_VL_CURSOR_RETRIED  0x0004          /* Set if started a retry */
+       unsigned short          nr_iterations;  /* Number of server iterations */
 };
 
 /*
@@ -700,6 +702,7 @@ struct afs_fs_cursor {
 #define AFS_FS_CURSOR_VNOVOL   0x0008          /* Set if seen VNOVOL */
 #define AFS_FS_CURSOR_CUR_ONLY 0x0010          /* Set if current server only (file lock held) */
 #define AFS_FS_CURSOR_NO_VSLEEP        0x0020          /* Set to prevent sleep on VBUSY, VOFFLINE, ... */
+       unsigned short          nr_iterations;  /* Number of server iterations */
 };
 
 /*
index 41405dde0113372f4c5e6f5ccb09f53bed371619..7c4487781637db7bd39e327f1ec73fe8ae6d9ee5 100644 (file)
@@ -156,6 +156,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
                return false;
        }
 
+       fc->nr_iterations++;
+
        /* Evaluate the result of the previous operation, if there was one. */
        switch (error) {
        case SHRT_MAX:
@@ -519,6 +521,56 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
        return false;
 }
 
+/*
+ * Dump cursor state in the case of the error being EDESTADDRREQ.
+ */
+static void afs_dump_edestaddrreq(const struct afs_fs_cursor *fc)
+{
+       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("FC: cbb=%x cbb2=%x fl=%hx err=%hd\n",
+                 fc->cb_break, fc->cb_break_2, fc->flags, fc->error);
+       pr_notice("FC: st=%u ix=%u ni=%u\n",
+                 fc->start, fc->index, fc->nr_iterations);
+
+       if (fc->server_list) {
+               const struct afs_server_list *sl = fc->server_list;
+               pr_notice("FC: SL nr=%u ix=%u vnov=%hx\n",
+                         sl->nr_servers, sl->index, sl->vnovol_mask);
+               for (i = 0; i < sl->nr_servers; i++) {
+                       const struct afs_server *s = sl->servers[i].server;
+                       pr_notice("FC: server fl=%lx av=%u %pU\n",
+                                 s->flags, s->addr_version, &s->uuid);
+                       if (s->addresses) {
+                               const struct afs_addr_list *a =
+                                       rcu_dereference(s->addresses);
+                               pr_notice("FC:  - av=%u nr=%u/%u/%u ax=%u\n",
+                                         a->version,
+                                         a->nr_ipv4, a->nr_addrs, a->max_addrs,
+                                         a->index);
+                               pr_notice("FC:  - pr=%lx yf=%lx\n",
+                                         a->probed, a->yfs);
+                               if (a == fc->ac.alist)
+                                       pr_notice("FC:  - current\n");
+                       }
+               }
+       }
+
+       pr_notice("AC: as=%u ax=%u ac=%d er=%d b=%u r=%u ni=%u\n",
+                 fc->ac.start, fc->ac.index, fc->ac.abort_code, fc->ac.error,
+                 fc->ac.begun, fc->ac.responded, fc->ac.nr_iterations);
+
+       rcu_read_unlock();
+}
+
 /*
  * Tidy up a filesystem cursor and unlock the vnode.
  */
@@ -526,6 +578,11 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc)
 {
        struct afs_net *net = afs_v2net(fc->vnode);
 
+       if (fc->error == -EDESTADDRREQ ||
+           fc->error == -ENETUNREACH ||
+           fc->error == -EHOSTUNREACH)
+               afs_dump_edestaddrreq(fc);
+
        mutex_unlock(&fc->vnode->io_lock);
 
        afs_end_cursor(&fc->ac);
index 44a936ad9c7aacab2e00e279ef85974b6eaea159..5b99ea7be194ad64708d791c35d4d1027b6e05ef 100644 (file)
@@ -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:
@@ -234,6 +236,52 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
        return false;
 }
 
+/*
+ * 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.
  */
@@ -241,6 +289,11 @@ 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);