summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-10-19 19:57:58 -0400
committerDavid Howells <dhowells@redhat.com>2018-10-23 19:41:09 -0400
commit744bcd713a4eabb248246f7deccfad30c579b7f5 (patch)
tree60470fca4f54503cb844f02d12f25a4c67529972
parent30062bd13e3659a309d249a06d5f4ebb4a5c5251 (diff)
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>
-rw-r--r--fs/afs/Kconfig12
-rw-r--r--fs/afs/addr_list.c2
-rw-r--r--fs/afs/internal.h3
-rw-r--r--fs/afs/rotate.c57
-rw-r--r--fs/afs/vl_rotate.c53
5 files changed, 127 insertions, 0 deletions
diff --git a/fs/afs/Kconfig b/fs/afs/Kconfig
index ebba3b18e5da..701aaa9b1899 100644
--- a/fs/afs/Kconfig
+++ b/fs/afs/Kconfig
@@ -27,3 +27,15 @@ config AFS_FSCACHE
27 help 27 help
28 Say Y here if you want AFS data to be cached locally on disk through 28 Say Y here if you want AFS data to be cached locally on disk through
29 the generic filesystem cache manager 29 the generic filesystem cache manager
30
31config AFS_DEBUG_CURSOR
32 bool "AFS server cursor debugging"
33 depends on AFS_FS
34 help
35 Say Y here to cause the contents of a server cursor to be dumped to
36 the dmesg log if the server rotation algorithm fails to successfully
37 contact a server.
38
39 See <file:Documentation/filesystems/afs.txt> for more information.
40
41 If unsure, say N.
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c
index 3f60b4012587..bc5ce31a4ae4 100644
--- a/fs/afs/addr_list.c
+++ b/fs/afs/addr_list.c
@@ -358,6 +358,8 @@ bool afs_iterate_addresses(struct afs_addr_cursor *ac)
358 if (!ac->alist) 358 if (!ac->alist)
359 return false; 359 return false;
360 360
361 ac->nr_iterations++;
362
361 if (ac->begun) { 363 if (ac->begun) {
362 ac->index++; 364 ac->index++;
363 if (ac->index == ac->alist->nr_addrs) 365 if (ac->index == ac->alist->nr_addrs)
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index ce79bd514331..ac9da1e4050e 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -660,6 +660,7 @@ struct afs_addr_cursor {
660 short error; 660 short error;
661 bool begun; /* T if we've begun iteration */ 661 bool begun; /* T if we've begun iteration */
662 bool responded; /* T if the current address responded */ 662 bool responded; /* T if the current address responded */
663 unsigned short nr_iterations; /* Number of address iterations */
663}; 664};
664 665
665/* 666/*
@@ -677,6 +678,7 @@ struct afs_vl_cursor {
677#define AFS_VL_CURSOR_STOP 0x0001 /* Set to cease iteration */ 678#define AFS_VL_CURSOR_STOP 0x0001 /* Set to cease iteration */
678#define AFS_VL_CURSOR_RETRY 0x0002 /* Set to do a retry */ 679#define AFS_VL_CURSOR_RETRY 0x0002 /* Set to do a retry */
679#define AFS_VL_CURSOR_RETRIED 0x0004 /* Set if started a retry */ 680#define AFS_VL_CURSOR_RETRIED 0x0004 /* Set if started a retry */
681 unsigned short nr_iterations; /* Number of server iterations */
680}; 682};
681 683
682/* 684/*
@@ -700,6 +702,7 @@ struct afs_fs_cursor {
700#define AFS_FS_CURSOR_VNOVOL 0x0008 /* Set if seen VNOVOL */ 702#define AFS_FS_CURSOR_VNOVOL 0x0008 /* Set if seen VNOVOL */
701#define AFS_FS_CURSOR_CUR_ONLY 0x0010 /* Set if current server only (file lock held) */ 703#define AFS_FS_CURSOR_CUR_ONLY 0x0010 /* Set if current server only (file lock held) */
702#define AFS_FS_CURSOR_NO_VSLEEP 0x0020 /* Set to prevent sleep on VBUSY, VOFFLINE, ... */ 704#define AFS_FS_CURSOR_NO_VSLEEP 0x0020 /* Set to prevent sleep on VBUSY, VOFFLINE, ... */
705 unsigned short nr_iterations; /* Number of server iterations */
703}; 706};
704 707
705/* 708/*
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c
index 41405dde0113..7c4487781637 100644
--- a/fs/afs/rotate.c
+++ b/fs/afs/rotate.c
@@ -156,6 +156,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
156 return false; 156 return false;
157 } 157 }
158 158
159 fc->nr_iterations++;
160
159 /* Evaluate the result of the previous operation, if there was one. */ 161 /* Evaluate the result of the previous operation, if there was one. */
160 switch (error) { 162 switch (error) {
161 case SHRT_MAX: 163 case SHRT_MAX:
@@ -520,12 +522,67 @@ iterate_address:
520} 522}
521 523
522/* 524/*
525 * Dump cursor state in the case of the error being EDESTADDRREQ.
526 */
527static void afs_dump_edestaddrreq(const struct afs_fs_cursor *fc)
528{
529 static int count;
530 int i;
531
532 if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3)
533 return;
534 count++;
535
536 rcu_read_lock();
537
538 pr_notice("EDESTADDR occurred\n");
539 pr_notice("FC: cbb=%x cbb2=%x fl=%hx err=%hd\n",
540 fc->cb_break, fc->cb_break_2, fc->flags, fc->error);
541 pr_notice("FC: st=%u ix=%u ni=%u\n",
542 fc->start, fc->index, fc->nr_iterations);
543
544 if (fc->server_list) {
545 const struct afs_server_list *sl = fc->server_list;
546 pr_notice("FC: SL nr=%u ix=%u vnov=%hx\n",
547 sl->nr_servers, sl->index, sl->vnovol_mask);
548 for (i = 0; i < sl->nr_servers; i++) {
549 const struct afs_server *s = sl->servers[i].server;
550 pr_notice("FC: server fl=%lx av=%u %pU\n",
551 s->flags, s->addr_version, &s->uuid);
552 if (s->addresses) {
553 const struct afs_addr_list *a =
554 rcu_dereference(s->addresses);
555 pr_notice("FC: - av=%u nr=%u/%u/%u ax=%u\n",
556 a->version,
557 a->nr_ipv4, a->nr_addrs, a->max_addrs,
558 a->index);
559 pr_notice("FC: - pr=%lx yf=%lx\n",
560 a->probed, a->yfs);
561 if (a == fc->ac.alist)
562 pr_notice("FC: - current\n");
563 }
564 }
565 }
566
567 pr_notice("AC: as=%u ax=%u ac=%d er=%d b=%u r=%u ni=%u\n",
568 fc->ac.start, fc->ac.index, fc->ac.abort_code, fc->ac.error,
569 fc->ac.begun, fc->ac.responded, fc->ac.nr_iterations);
570
571 rcu_read_unlock();
572}
573
574/*
523 * Tidy up a filesystem cursor and unlock the vnode. 575 * Tidy up a filesystem cursor and unlock the vnode.
524 */ 576 */
525int afs_end_vnode_operation(struct afs_fs_cursor *fc) 577int afs_end_vnode_operation(struct afs_fs_cursor *fc)
526{ 578{
527 struct afs_net *net = afs_v2net(fc->vnode); 579 struct afs_net *net = afs_v2net(fc->vnode);
528 580
581 if (fc->error == -EDESTADDRREQ ||
582 fc->error == -ENETUNREACH ||
583 fc->error == -EHOSTUNREACH)
584 afs_dump_edestaddrreq(fc);
585
529 mutex_unlock(&fc->vnode->io_lock); 586 mutex_unlock(&fc->vnode->io_lock);
530 587
531 afs_end_cursor(&fc->ac); 588 afs_end_cursor(&fc->ac);
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)
83 return false; 83 return false;
84 } 84 }
85 85
86 vc->nr_iterations++;
87
86 /* Evaluate the result of the previous operation, if there was one. */ 88 /* Evaluate the result of the previous operation, if there was one. */
87 switch (error) { 89 switch (error) {
88 case SHRT_MAX: 90 case SHRT_MAX:
@@ -235,12 +237,63 @@ failed:
235} 237}
236 238
237/* 239/*
240 * Dump cursor state in the case of the error being EDESTADDRREQ.
241 */
242static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
243{
244 static int count;
245 int i;
246
247 if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3)
248 return;
249 count++;
250
251 rcu_read_lock();
252 pr_notice("EDESTADDR occurred\n");
253 pr_notice("VC: st=%u ix=%u ni=%hu fl=%hx err=%hd\n",
254 vc->start, vc->index, vc->nr_iterations, vc->flags, vc->error);
255
256 if (vc->server_list) {
257 const struct afs_vlserver_list *sl = vc->server_list;
258 pr_notice("VC: SL nr=%u ix=%u\n",
259 sl->nr_servers, sl->index);
260 for (i = 0; i < sl->nr_servers; i++) {
261 const struct afs_vlserver *s = sl->servers[i].server;
262 pr_notice("VC: server fl=%lx %s+%hu\n",
263 s->flags, s->name, s->port);
264 if (s->addresses) {
265 const struct afs_addr_list *a =
266 rcu_dereference(s->addresses);
267 pr_notice("VC: - av=%u nr=%u/%u/%u ax=%u\n",
268 a->version,
269 a->nr_ipv4, a->nr_addrs, a->max_addrs,
270 a->index);
271 pr_notice("VC: - pr=%lx yf=%lx\n",
272 a->probed, a->yfs);
273 if (a == vc->ac.alist)
274 pr_notice("VC: - current\n");
275 }
276 }
277 }
278
279 pr_notice("AC: as=%u ax=%u ac=%d er=%d b=%u r=%u ni=%hu\n",
280 vc->ac.start, vc->ac.index, vc->ac.abort_code, vc->ac.error,
281 vc->ac.begun, vc->ac.responded, vc->ac.nr_iterations);
282 rcu_read_unlock();
283}
284
285/*
238 * Tidy up a volume location server cursor and unlock the vnode. 286 * Tidy up a volume location server cursor and unlock the vnode.
239 */ 287 */
240int afs_end_vlserver_operation(struct afs_vl_cursor *vc) 288int afs_end_vlserver_operation(struct afs_vl_cursor *vc)
241{ 289{
242 struct afs_net *net = vc->cell->net; 290 struct afs_net *net = vc->cell->net;
243 291
292 if (vc->error == -EDESTADDRREQ ||
293 vc->error == -ENETUNREACH ||
294 vc->error == -EHOSTUNREACH)
295 afs_vl_dump_edestaddrreq(vc);
296
244 afs_end_cursor(&vc->ac); 297 afs_end_cursor(&vc->ac);
245 afs_put_vlserverlist(net, vc->server_list); 298 afs_put_vlserverlist(net, vc->server_list);
246 299