diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-30 13:47:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-30 13:47:50 -0500 |
commit | 5f1ca5c619c2af5e03114b0276642cdc15d11a94 (patch) | |
tree | 9dde48dc03bd345e184bbed650282adff68dd739 /fs/afs | |
parent | 49afe6614321e78727729680b97e96998695249a (diff) | |
parent | 73116df7bb90435ccb2817f44113295240d15034 (diff) |
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro:
"Assorted fixes all over the place.
The iov_iter one is this cycle regression (splice from UDP triggering
WARN_ON()), the rest is older"
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
afs: Use d_instantiate() rather than d_add() and don't d_drop()
afs: Fix missing net error handling
afs: Fix validation/callback interaction
iov_iter: teach csum_and_copy_to_iter() to handle pipe-backed ones
exportfs: do not read dentry after free
exportfs: fix 'passing zero to ERR_PTR()' warning
aio: fix failure to put the file pointer
sysv: return 'err' instead of 0 in __sysv_write_inode
Diffstat (limited to 'fs/afs')
-rw-r--r-- | fs/afs/dir.c | 4 | ||||
-rw-r--r-- | fs/afs/fs_probe.c | 39 | ||||
-rw-r--r-- | fs/afs/inode.c | 18 | ||||
-rw-r--r-- | fs/afs/internal.h | 9 | ||||
-rw-r--r-- | fs/afs/misc.c | 52 | ||||
-rw-r--r-- | fs/afs/rotate.c | 53 | ||||
-rw-r--r-- | fs/afs/vl_probe.c | 45 | ||||
-rw-r--r-- | fs/afs/vl_rotate.c | 50 |
8 files changed, 148 insertions, 122 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 43dea3b00c29..8a2562e3a316 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -1075,8 +1075,6 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc, | |||
1075 | if (fc->ac.error < 0) | 1075 | if (fc->ac.error < 0) |
1076 | return; | 1076 | return; |
1077 | 1077 | ||
1078 | d_drop(new_dentry); | ||
1079 | |||
1080 | inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key, | 1078 | inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key, |
1081 | newfid, newstatus, newcb, fc->cbi); | 1079 | newfid, newstatus, newcb, fc->cbi); |
1082 | if (IS_ERR(inode)) { | 1080 | if (IS_ERR(inode)) { |
@@ -1090,7 +1088,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc, | |||
1090 | vnode = AFS_FS_I(inode); | 1088 | vnode = AFS_FS_I(inode); |
1091 | set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); | 1089 | set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); |
1092 | afs_vnode_commit_status(fc, vnode, 0); | 1090 | afs_vnode_commit_status(fc, vnode, 0); |
1093 | d_add(new_dentry, inode); | 1091 | d_instantiate(new_dentry, inode); |
1094 | } | 1092 | } |
1095 | 1093 | ||
1096 | /* | 1094 | /* |
diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index d049cb459742..fde6b4d4121e 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c | |||
@@ -61,8 +61,11 @@ void afs_fileserver_probe_result(struct afs_call *call) | |||
61 | afs_io_error(call, afs_io_error_fs_probe_fail); | 61 | afs_io_error(call, afs_io_error_fs_probe_fail); |
62 | goto out; | 62 | goto out; |
63 | case -ECONNRESET: /* Responded, but call expired. */ | 63 | case -ECONNRESET: /* Responded, but call expired. */ |
64 | case -ERFKILL: | ||
65 | case -EADDRNOTAVAIL: | ||
64 | case -ENETUNREACH: | 66 | case -ENETUNREACH: |
65 | case -EHOSTUNREACH: | 67 | case -EHOSTUNREACH: |
68 | case -EHOSTDOWN: | ||
66 | case -ECONNREFUSED: | 69 | case -ECONNREFUSED: |
67 | case -ETIMEDOUT: | 70 | case -ETIMEDOUT: |
68 | case -ETIME: | 71 | case -ETIME: |
@@ -132,12 +135,14 @@ out: | |||
132 | static int afs_do_probe_fileserver(struct afs_net *net, | 135 | static int afs_do_probe_fileserver(struct afs_net *net, |
133 | struct afs_server *server, | 136 | struct afs_server *server, |
134 | struct key *key, | 137 | struct key *key, |
135 | unsigned int server_index) | 138 | unsigned int server_index, |
139 | struct afs_error *_e) | ||
136 | { | 140 | { |
137 | struct afs_addr_cursor ac = { | 141 | struct afs_addr_cursor ac = { |
138 | .index = 0, | 142 | .index = 0, |
139 | }; | 143 | }; |
140 | int ret; | 144 | bool in_progress = false; |
145 | int err; | ||
141 | 146 | ||
142 | _enter("%pU", &server->uuid); | 147 | _enter("%pU", &server->uuid); |
143 | 148 | ||
@@ -151,15 +156,17 @@ static int afs_do_probe_fileserver(struct afs_net *net, | |||
151 | server->probe.rtt = UINT_MAX; | 156 | server->probe.rtt = UINT_MAX; |
152 | 157 | ||
153 | for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) { | 158 | for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) { |
154 | ret = afs_fs_get_capabilities(net, server, &ac, key, server_index, | 159 | err = afs_fs_get_capabilities(net, server, &ac, key, server_index, |
155 | true); | 160 | true); |
156 | if (ret != -EINPROGRESS) { | 161 | if (err == -EINPROGRESS) |
157 | afs_fs_probe_done(server); | 162 | in_progress = true; |
158 | return ret; | 163 | else |
159 | } | 164 | afs_prioritise_error(_e, err, ac.abort_code); |
160 | } | 165 | } |
161 | 166 | ||
162 | return 0; | 167 | if (!in_progress) |
168 | afs_fs_probe_done(server); | ||
169 | return in_progress; | ||
163 | } | 170 | } |
164 | 171 | ||
165 | /* | 172 | /* |
@@ -169,21 +176,23 @@ int afs_probe_fileservers(struct afs_net *net, struct key *key, | |||
169 | struct afs_server_list *list) | 176 | struct afs_server_list *list) |
170 | { | 177 | { |
171 | struct afs_server *server; | 178 | struct afs_server *server; |
172 | int i, ret; | 179 | struct afs_error e; |
180 | bool in_progress = false; | ||
181 | int i; | ||
173 | 182 | ||
183 | e.error = 0; | ||
184 | e.responded = false; | ||
174 | for (i = 0; i < list->nr_servers; i++) { | 185 | for (i = 0; i < list->nr_servers; i++) { |
175 | server = list->servers[i].server; | 186 | server = list->servers[i].server; |
176 | if (test_bit(AFS_SERVER_FL_PROBED, &server->flags)) | 187 | if (test_bit(AFS_SERVER_FL_PROBED, &server->flags)) |
177 | continue; | 188 | continue; |
178 | 189 | ||
179 | if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags)) { | 190 | if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags) && |
180 | ret = afs_do_probe_fileserver(net, server, key, i); | 191 | afs_do_probe_fileserver(net, server, key, i, &e)) |
181 | if (ret) | 192 | in_progress = true; |
182 | return ret; | ||
183 | } | ||
184 | } | 193 | } |
185 | 194 | ||
186 | return 0; | 195 | return in_progress ? 0 : e.error; |
187 | } | 196 | } |
188 | 197 | ||
189 | /* | 198 | /* |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 4c6d8e1112c2..6b17d3620414 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
@@ -382,7 +382,7 @@ void afs_zap_data(struct afs_vnode *vnode) | |||
382 | int afs_validate(struct afs_vnode *vnode, struct key *key) | 382 | int afs_validate(struct afs_vnode *vnode, struct key *key) |
383 | { | 383 | { |
384 | time64_t now = ktime_get_real_seconds(); | 384 | time64_t now = ktime_get_real_seconds(); |
385 | bool valid = false; | 385 | bool valid; |
386 | int ret; | 386 | int ret; |
387 | 387 | ||
388 | _enter("{v={%llx:%llu} fl=%lx},%x", | 388 | _enter("{v={%llx:%llu} fl=%lx},%x", |
@@ -402,15 +402,21 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
402 | vnode->cb_v_break = vnode->volume->cb_v_break; | 402 | vnode->cb_v_break = vnode->volume->cb_v_break; |
403 | valid = false; | 403 | valid = false; |
404 | } else if (vnode->status.type == AFS_FTYPE_DIR && | 404 | } else if (vnode->status.type == AFS_FTYPE_DIR && |
405 | test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) && | 405 | (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) || |
406 | vnode->cb_expires_at - 10 > now) { | 406 | vnode->cb_expires_at - 10 <= now)) { |
407 | valid = true; | 407 | valid = false; |
408 | } else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) && | 408 | } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) || |
409 | vnode->cb_expires_at - 10 > now) { | 409 | vnode->cb_expires_at - 10 <= now) { |
410 | valid = false; | ||
411 | } else { | ||
410 | valid = true; | 412 | valid = true; |
411 | } | 413 | } |
412 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { | 414 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { |
413 | valid = true; | 415 | valid = true; |
416 | } else { | ||
417 | vnode->cb_s_break = vnode->cb_interest->server->cb_s_break; | ||
418 | vnode->cb_v_break = vnode->volume->cb_v_break; | ||
419 | valid = false; | ||
414 | } | 420 | } |
415 | 421 | ||
416 | read_sequnlock_excl(&vnode->cb_lock); | 422 | read_sequnlock_excl(&vnode->cb_lock); |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 5da3b09b7518..8871b9e8645f 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -696,6 +696,14 @@ struct afs_interface { | |||
696 | }; | 696 | }; |
697 | 697 | ||
698 | /* | 698 | /* |
699 | * Error prioritisation and accumulation. | ||
700 | */ | ||
701 | struct afs_error { | ||
702 | short error; /* Accumulated error */ | ||
703 | bool responded; /* T if server responded */ | ||
704 | }; | ||
705 | |||
706 | /* | ||
699 | * Cursor for iterating over a server's address list. | 707 | * Cursor for iterating over a server's address list. |
700 | */ | 708 | */ |
701 | struct afs_addr_cursor { | 709 | struct afs_addr_cursor { |
@@ -1015,6 +1023,7 @@ static inline void __afs_stat(atomic_t *s) | |||
1015 | * misc.c | 1023 | * misc.c |
1016 | */ | 1024 | */ |
1017 | extern int afs_abort_to_error(u32); | 1025 | extern int afs_abort_to_error(u32); |
1026 | extern void afs_prioritise_error(struct afs_error *, int, u32); | ||
1018 | 1027 | ||
1019 | /* | 1028 | /* |
1020 | * mntpt.c | 1029 | * mntpt.c |
diff --git a/fs/afs/misc.c b/fs/afs/misc.c index 700a5fa7f4ec..bbb1fd51b019 100644 --- a/fs/afs/misc.c +++ b/fs/afs/misc.c | |||
@@ -118,3 +118,55 @@ int afs_abort_to_error(u32 abort_code) | |||
118 | default: return -EREMOTEIO; | 118 | default: return -EREMOTEIO; |
119 | } | 119 | } |
120 | } | 120 | } |
121 | |||
122 | /* | ||
123 | * Select the error to report from a set of errors. | ||
124 | */ | ||
125 | void afs_prioritise_error(struct afs_error *e, int error, u32 abort_code) | ||
126 | { | ||
127 | switch (error) { | ||
128 | case 0: | ||
129 | return; | ||
130 | default: | ||
131 | if (e->error == -ETIMEDOUT || | ||
132 | e->error == -ETIME) | ||
133 | return; | ||
134 | case -ETIMEDOUT: | ||
135 | case -ETIME: | ||
136 | if (e->error == -ENOMEM || | ||
137 | e->error == -ENONET) | ||
138 | return; | ||
139 | case -ENOMEM: | ||
140 | case -ENONET: | ||
141 | if (e->error == -ERFKILL) | ||
142 | return; | ||
143 | case -ERFKILL: | ||
144 | if (e->error == -EADDRNOTAVAIL) | ||
145 | return; | ||
146 | case -EADDRNOTAVAIL: | ||
147 | if (e->error == -ENETUNREACH) | ||
148 | return; | ||
149 | case -ENETUNREACH: | ||
150 | if (e->error == -EHOSTUNREACH) | ||
151 | return; | ||
152 | case -EHOSTUNREACH: | ||
153 | if (e->error == -EHOSTDOWN) | ||
154 | return; | ||
155 | case -EHOSTDOWN: | ||
156 | if (e->error == -ECONNREFUSED) | ||
157 | return; | ||
158 | case -ECONNREFUSED: | ||
159 | if (e->error == -ECONNRESET) | ||
160 | return; | ||
161 | case -ECONNRESET: /* Responded, but call expired. */ | ||
162 | if (e->responded) | ||
163 | return; | ||
164 | e->error = error; | ||
165 | return; | ||
166 | |||
167 | case -ECONNABORTED: | ||
168 | e->responded = true; | ||
169 | e->error = afs_abort_to_error(abort_code); | ||
170 | return; | ||
171 | } | ||
172 | } | ||
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index 00504254c1c2..c3ae324781f8 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c | |||
@@ -136,7 +136,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
136 | struct afs_addr_list *alist; | 136 | struct afs_addr_list *alist; |
137 | struct afs_server *server; | 137 | struct afs_server *server; |
138 | struct afs_vnode *vnode = fc->vnode; | 138 | struct afs_vnode *vnode = fc->vnode; |
139 | u32 rtt, abort_code; | 139 | struct afs_error e; |
140 | u32 rtt; | ||
140 | int error = fc->ac.error, i; | 141 | int error = fc->ac.error, i; |
141 | 142 | ||
142 | _enter("%lx[%d],%lx[%d],%d,%d", | 143 | _enter("%lx[%d],%lx[%d],%d,%d", |
@@ -306,8 +307,11 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
306 | if (fc->error != -EDESTADDRREQ) | 307 | if (fc->error != -EDESTADDRREQ) |
307 | goto iterate_address; | 308 | goto iterate_address; |
308 | /* Fall through */ | 309 | /* Fall through */ |
310 | case -ERFKILL: | ||
311 | case -EADDRNOTAVAIL: | ||
309 | case -ENETUNREACH: | 312 | case -ENETUNREACH: |
310 | case -EHOSTUNREACH: | 313 | case -EHOSTUNREACH: |
314 | case -EHOSTDOWN: | ||
311 | case -ECONNREFUSED: | 315 | case -ECONNREFUSED: |
312 | _debug("no conn"); | 316 | _debug("no conn"); |
313 | fc->error = error; | 317 | fc->error = error; |
@@ -446,50 +450,15 @@ no_more_servers: | |||
446 | if (fc->flags & AFS_FS_CURSOR_VBUSY) | 450 | if (fc->flags & AFS_FS_CURSOR_VBUSY) |
447 | goto restart_from_beginning; | 451 | goto restart_from_beginning; |
448 | 452 | ||
449 | abort_code = 0; | 453 | e.error = -EDESTADDRREQ; |
450 | error = -EDESTADDRREQ; | 454 | e.responded = false; |
451 | for (i = 0; i < fc->server_list->nr_servers; i++) { | 455 | for (i = 0; i < fc->server_list->nr_servers; i++) { |
452 | struct afs_server *s = fc->server_list->servers[i].server; | 456 | struct afs_server *s = fc->server_list->servers[i].server; |
453 | int probe_error = READ_ONCE(s->probe.error); | ||
454 | 457 | ||
455 | switch (probe_error) { | 458 | afs_prioritise_error(&e, READ_ONCE(s->probe.error), |
456 | case 0: | 459 | s->probe.abort_code); |
457 | continue; | ||
458 | default: | ||
459 | if (error == -ETIMEDOUT || | ||
460 | error == -ETIME) | ||
461 | continue; | ||
462 | case -ETIMEDOUT: | ||
463 | case -ETIME: | ||
464 | if (error == -ENOMEM || | ||
465 | error == -ENONET) | ||
466 | continue; | ||
467 | case -ENOMEM: | ||
468 | case -ENONET: | ||
469 | if (error == -ENETUNREACH) | ||
470 | continue; | ||
471 | case -ENETUNREACH: | ||
472 | if (error == -EHOSTUNREACH) | ||
473 | continue; | ||
474 | case -EHOSTUNREACH: | ||
475 | if (error == -ECONNREFUSED) | ||
476 | continue; | ||
477 | case -ECONNREFUSED: | ||
478 | if (error == -ECONNRESET) | ||
479 | continue; | ||
480 | case -ECONNRESET: /* Responded, but call expired. */ | ||
481 | if (error == -ECONNABORTED) | ||
482 | continue; | ||
483 | case -ECONNABORTED: | ||
484 | abort_code = s->probe.abort_code; | ||
485 | error = probe_error; | ||
486 | continue; | ||
487 | } | ||
488 | } | 460 | } |
489 | 461 | ||
490 | if (error == -ECONNABORTED) | ||
491 | error = afs_abort_to_error(abort_code); | ||
492 | |||
493 | failed_set_error: | 462 | failed_set_error: |
494 | fc->error = error; | 463 | fc->error = error; |
495 | failed: | 464 | failed: |
@@ -553,8 +522,11 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | |||
553 | _leave(" = f [abort]"); | 522 | _leave(" = f [abort]"); |
554 | return false; | 523 | return false; |
555 | 524 | ||
525 | case -ERFKILL: | ||
526 | case -EADDRNOTAVAIL: | ||
556 | case -ENETUNREACH: | 527 | case -ENETUNREACH: |
557 | case -EHOSTUNREACH: | 528 | case -EHOSTUNREACH: |
529 | case -EHOSTDOWN: | ||
558 | case -ECONNREFUSED: | 530 | case -ECONNREFUSED: |
559 | case -ETIMEDOUT: | 531 | case -ETIMEDOUT: |
560 | case -ETIME: | 532 | case -ETIME: |
@@ -633,6 +605,7 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc) | |||
633 | struct afs_net *net = afs_v2net(fc->vnode); | 605 | struct afs_net *net = afs_v2net(fc->vnode); |
634 | 606 | ||
635 | if (fc->error == -EDESTADDRREQ || | 607 | if (fc->error == -EDESTADDRREQ || |
608 | fc->error == -EADDRNOTAVAIL || | ||
636 | fc->error == -ENETUNREACH || | 609 | fc->error == -ENETUNREACH || |
637 | fc->error == -EHOSTUNREACH) | 610 | fc->error == -EHOSTUNREACH) |
638 | afs_dump_edestaddrreq(fc); | 611 | afs_dump_edestaddrreq(fc); |
diff --git a/fs/afs/vl_probe.c b/fs/afs/vl_probe.c index c0f616bd70cb..f0b032976487 100644 --- a/fs/afs/vl_probe.c +++ b/fs/afs/vl_probe.c | |||
@@ -61,8 +61,11 @@ void afs_vlserver_probe_result(struct afs_call *call) | |||
61 | afs_io_error(call, afs_io_error_vl_probe_fail); | 61 | afs_io_error(call, afs_io_error_vl_probe_fail); |
62 | goto out; | 62 | goto out; |
63 | case -ECONNRESET: /* Responded, but call expired. */ | 63 | case -ECONNRESET: /* Responded, but call expired. */ |
64 | case -ERFKILL: | ||
65 | case -EADDRNOTAVAIL: | ||
64 | case -ENETUNREACH: | 66 | case -ENETUNREACH: |
65 | case -EHOSTUNREACH: | 67 | case -EHOSTUNREACH: |
68 | case -EHOSTDOWN: | ||
66 | case -ECONNREFUSED: | 69 | case -ECONNREFUSED: |
67 | case -ETIMEDOUT: | 70 | case -ETIMEDOUT: |
68 | case -ETIME: | 71 | case -ETIME: |
@@ -129,15 +132,17 @@ out: | |||
129 | * Probe all of a vlserver's addresses to find out the best route and to | 132 | * Probe all of a vlserver's addresses to find out the best route and to |
130 | * query its capabilities. | 133 | * query its capabilities. |
131 | */ | 134 | */ |
132 | static int afs_do_probe_vlserver(struct afs_net *net, | 135 | static bool afs_do_probe_vlserver(struct afs_net *net, |
133 | struct afs_vlserver *server, | 136 | struct afs_vlserver *server, |
134 | struct key *key, | 137 | struct key *key, |
135 | unsigned int server_index) | 138 | unsigned int server_index, |
139 | struct afs_error *_e) | ||
136 | { | 140 | { |
137 | struct afs_addr_cursor ac = { | 141 | struct afs_addr_cursor ac = { |
138 | .index = 0, | 142 | .index = 0, |
139 | }; | 143 | }; |
140 | int ret; | 144 | bool in_progress = false; |
145 | int err; | ||
141 | 146 | ||
142 | _enter("%s", server->name); | 147 | _enter("%s", server->name); |
143 | 148 | ||
@@ -151,15 +156,17 @@ static int afs_do_probe_vlserver(struct afs_net *net, | |||
151 | server->probe.rtt = UINT_MAX; | 156 | server->probe.rtt = UINT_MAX; |
152 | 157 | ||
153 | for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) { | 158 | for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) { |
154 | ret = afs_vl_get_capabilities(net, &ac, key, server, | 159 | err = afs_vl_get_capabilities(net, &ac, key, server, |
155 | server_index, true); | 160 | server_index, true); |
156 | if (ret != -EINPROGRESS) { | 161 | if (err == -EINPROGRESS) |
157 | afs_vl_probe_done(server); | 162 | in_progress = true; |
158 | return ret; | 163 | else |
159 | } | 164 | afs_prioritise_error(_e, err, ac.abort_code); |
160 | } | 165 | } |
161 | 166 | ||
162 | return 0; | 167 | if (!in_progress) |
168 | afs_vl_probe_done(server); | ||
169 | return in_progress; | ||
163 | } | 170 | } |
164 | 171 | ||
165 | /* | 172 | /* |
@@ -169,21 +176,23 @@ int afs_send_vl_probes(struct afs_net *net, struct key *key, | |||
169 | struct afs_vlserver_list *vllist) | 176 | struct afs_vlserver_list *vllist) |
170 | { | 177 | { |
171 | struct afs_vlserver *server; | 178 | struct afs_vlserver *server; |
172 | int i, ret; | 179 | struct afs_error e; |
180 | bool in_progress = false; | ||
181 | int i; | ||
173 | 182 | ||
183 | e.error = 0; | ||
184 | e.responded = false; | ||
174 | for (i = 0; i < vllist->nr_servers; i++) { | 185 | for (i = 0; i < vllist->nr_servers; i++) { |
175 | server = vllist->servers[i].server; | 186 | server = vllist->servers[i].server; |
176 | if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags)) | 187 | if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags)) |
177 | continue; | 188 | continue; |
178 | 189 | ||
179 | if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags)) { | 190 | if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags) && |
180 | ret = afs_do_probe_vlserver(net, server, key, i); | 191 | afs_do_probe_vlserver(net, server, key, i, &e)) |
181 | if (ret) | 192 | in_progress = true; |
182 | return ret; | ||
183 | } | ||
184 | } | 193 | } |
185 | 194 | ||
186 | return 0; | 195 | return in_progress ? 0 : e.error; |
187 | } | 196 | } |
188 | 197 | ||
189 | /* | 198 | /* |
diff --git a/fs/afs/vl_rotate.c b/fs/afs/vl_rotate.c index b64a284b99d2..7adde83a0648 100644 --- a/fs/afs/vl_rotate.c +++ b/fs/afs/vl_rotate.c | |||
@@ -71,8 +71,9 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc) | |||
71 | { | 71 | { |
72 | struct afs_addr_list *alist; | 72 | struct afs_addr_list *alist; |
73 | struct afs_vlserver *vlserver; | 73 | struct afs_vlserver *vlserver; |
74 | struct afs_error e; | ||
74 | u32 rtt; | 75 | u32 rtt; |
75 | int error = vc->ac.error, abort_code, i; | 76 | int error = vc->ac.error, i; |
76 | 77 | ||
77 | _enter("%lx[%d],%lx[%d],%d,%d", | 78 | _enter("%lx[%d],%lx[%d],%d,%d", |
78 | vc->untried, vc->index, | 79 | vc->untried, vc->index, |
@@ -119,8 +120,11 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc) | |||
119 | goto failed; | 120 | goto failed; |
120 | } | 121 | } |
121 | 122 | ||
123 | case -ERFKILL: | ||
124 | case -EADDRNOTAVAIL: | ||
122 | case -ENETUNREACH: | 125 | case -ENETUNREACH: |
123 | case -EHOSTUNREACH: | 126 | case -EHOSTUNREACH: |
127 | case -EHOSTDOWN: | ||
124 | case -ECONNREFUSED: | 128 | case -ECONNREFUSED: |
125 | case -ETIMEDOUT: | 129 | case -ETIMEDOUT: |
126 | case -ETIME: | 130 | case -ETIME: |
@@ -235,50 +239,15 @@ no_more_servers: | |||
235 | if (vc->flags & AFS_VL_CURSOR_RETRY) | 239 | if (vc->flags & AFS_VL_CURSOR_RETRY) |
236 | goto restart_from_beginning; | 240 | goto restart_from_beginning; |
237 | 241 | ||
238 | abort_code = 0; | 242 | e.error = -EDESTADDRREQ; |
239 | error = -EDESTADDRREQ; | 243 | e.responded = false; |
240 | for (i = 0; i < vc->server_list->nr_servers; i++) { | 244 | for (i = 0; i < vc->server_list->nr_servers; i++) { |
241 | struct afs_vlserver *s = vc->server_list->servers[i].server; | 245 | struct afs_vlserver *s = vc->server_list->servers[i].server; |
242 | int probe_error = READ_ONCE(s->probe.error); | ||
243 | 246 | ||
244 | switch (probe_error) { | 247 | afs_prioritise_error(&e, READ_ONCE(s->probe.error), |
245 | case 0: | 248 | s->probe.abort_code); |
246 | continue; | ||
247 | default: | ||
248 | if (error == -ETIMEDOUT || | ||
249 | error == -ETIME) | ||
250 | continue; | ||
251 | case -ETIMEDOUT: | ||
252 | case -ETIME: | ||
253 | if (error == -ENOMEM || | ||
254 | error == -ENONET) | ||
255 | continue; | ||
256 | case -ENOMEM: | ||
257 | case -ENONET: | ||
258 | if (error == -ENETUNREACH) | ||
259 | continue; | ||
260 | case -ENETUNREACH: | ||
261 | if (error == -EHOSTUNREACH) | ||
262 | continue; | ||
263 | case -EHOSTUNREACH: | ||
264 | if (error == -ECONNREFUSED) | ||
265 | continue; | ||
266 | case -ECONNREFUSED: | ||
267 | if (error == -ECONNRESET) | ||
268 | continue; | ||
269 | case -ECONNRESET: /* Responded, but call expired. */ | ||
270 | if (error == -ECONNABORTED) | ||
271 | continue; | ||
272 | case -ECONNABORTED: | ||
273 | abort_code = s->probe.abort_code; | ||
274 | error = probe_error; | ||
275 | continue; | ||
276 | } | ||
277 | } | 249 | } |
278 | 250 | ||
279 | if (error == -ECONNABORTED) | ||
280 | error = afs_abort_to_error(abort_code); | ||
281 | |||
282 | failed_set_error: | 251 | failed_set_error: |
283 | vc->error = error; | 252 | vc->error = error; |
284 | failed: | 253 | failed: |
@@ -341,6 +310,7 @@ int afs_end_vlserver_operation(struct afs_vl_cursor *vc) | |||
341 | struct afs_net *net = vc->cell->net; | 310 | struct afs_net *net = vc->cell->net; |
342 | 311 | ||
343 | if (vc->error == -EDESTADDRREQ || | 312 | if (vc->error == -EDESTADDRREQ || |
313 | vc->error == -EADDRNOTAVAIL || | ||
344 | vc->error == -ENETUNREACH || | 314 | vc->error == -ENETUNREACH || |
345 | vc->error == -EHOSTUNREACH) | 315 | vc->error == -EHOSTUNREACH) |
346 | afs_vl_dump_edestaddrreq(vc); | 316 | afs_vl_dump_edestaddrreq(vc); |