aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/rotate.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-10-19 19:57:57 -0400
committerDavid Howells <dhowells@redhat.com>2018-10-23 19:41:07 -0400
commite7f680f45bd1deb4ca479c2348b395e1a4d44b17 (patch)
treefe6fbfbc8fcecf89c3d5db4a11d4c4a334e9d5ee /fs/afs/rotate.c
parent12bdcf333fe13ece2a487a699b1a0f4c5dbb594b (diff)
afs: Improve FS server rotation error handling
Improve the error handling in FS server rotation by: (1) Cache the latest useful error value for the fs operation as a whole in struct afs_fs_cursor separately from the error cached in the afs_addr_cursor struct. The one in the address cursor gets clobbered occasionally. Copy over the error to the fs operation only when it's something we'd be interested in passing to userspace. (2) Make it so that EDESTADDRREQ is the default that is seen only if no addresses are available to be accessed. (3) When calling utility functions, such as checking a volume status or probing a fileserver, don't let a successful result clobber the cached error in the cursor; instead, stash the result in a temporary variable until it has been assessed. (4) Don't return ETIMEDOUT or ETIME if a better error, such as ENETUNREACH, is already cached. (5) On leaving the rotation loop, turn any remote abort code into a more useful error than ECONNABORTED. Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation") Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/rotate.c')
-rw-r--r--fs/afs/rotate.c95
1 files changed, 53 insertions, 42 deletions
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c
index 1faef56b12bd..d7cbc3c230ee 100644
--- a/fs/afs/rotate.c
+++ b/fs/afs/rotate.c
@@ -39,9 +39,10 @@ bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode
39 fc->vnode = vnode; 39 fc->vnode = vnode;
40 fc->key = key; 40 fc->key = key;
41 fc->ac.error = SHRT_MAX; 41 fc->ac.error = SHRT_MAX;
42 fc->error = -EDESTADDRREQ;
42 43
43 if (mutex_lock_interruptible(&vnode->io_lock) < 0) { 44 if (mutex_lock_interruptible(&vnode->io_lock) < 0) {
44 fc->ac.error = -EINTR; 45 fc->error = -EINTR;
45 fc->flags |= AFS_FS_CURSOR_STOP; 46 fc->flags |= AFS_FS_CURSOR_STOP;
46 return false; 47 return false;
47 } 48 }
@@ -80,7 +81,7 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,
80 * and have to return an error. 81 * and have to return an error.
81 */ 82 */
82 if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) { 83 if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) {
83 fc->ac.error = -ESTALE; 84 fc->error = -ESTALE;
84 return false; 85 return false;
85 } 86 }
86 87
@@ -127,7 +128,7 @@ static bool afs_sleep_and_retry(struct afs_fs_cursor *fc)
127{ 128{
128 msleep_interruptible(1000); 129 msleep_interruptible(1000);
129 if (signal_pending(current)) { 130 if (signal_pending(current)) {
130 fc->ac.error = -ERESTARTSYS; 131 fc->error = -ERESTARTSYS;
131 return false; 132 return false;
132 } 133 }
133 134
@@ -143,11 +144,12 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
143 struct afs_addr_list *alist; 144 struct afs_addr_list *alist;
144 struct afs_server *server; 145 struct afs_server *server;
145 struct afs_vnode *vnode = fc->vnode; 146 struct afs_vnode *vnode = fc->vnode;
147 int error = fc->ac.error;
146 148
147 _enter("%u/%u,%u/%u,%d,%d", 149 _enter("%u/%u,%u/%u,%d,%d",
148 fc->index, fc->start, 150 fc->index, fc->start,
149 fc->ac.index, fc->ac.start, 151 fc->ac.index, fc->ac.start,
150 fc->ac.error, fc->ac.abort_code); 152 error, fc->ac.abort_code);
151 153
152 if (fc->flags & AFS_FS_CURSOR_STOP) { 154 if (fc->flags & AFS_FS_CURSOR_STOP) {
153 _leave(" = f [stopped]"); 155 _leave(" = f [stopped]");
@@ -155,15 +157,16 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
155 } 157 }
156 158
157 /* Evaluate the result of the previous operation, if there was one. */ 159 /* Evaluate the result of the previous operation, if there was one. */
158 switch (fc->ac.error) { 160 switch (error) {
159 case SHRT_MAX: 161 case SHRT_MAX:
160 goto start; 162 goto start;
161 163
162 case 0: 164 case 0:
163 default: 165 default:
164 /* Success or local failure. Stop. */ 166 /* Success or local failure. Stop. */
167 fc->error = error;
165 fc->flags |= AFS_FS_CURSOR_STOP; 168 fc->flags |= AFS_FS_CURSOR_STOP;
166 _leave(" = f [okay/local %d]", fc->ac.error); 169 _leave(" = f [okay/local %d]", error);
167 return false; 170 return false;
168 171
169 case -ECONNABORTED: 172 case -ECONNABORTED:
@@ -178,7 +181,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
178 * - May indicate that the fileserver couldn't attach to the vol. 181 * - May indicate that the fileserver couldn't attach to the vol.
179 */ 182 */
180 if (fc->flags & AFS_FS_CURSOR_VNOVOL) { 183 if (fc->flags & AFS_FS_CURSOR_VNOVOL) {
181 fc->ac.error = -EREMOTEIO; 184 fc->error = -EREMOTEIO;
182 goto next_server; 185 goto next_server;
183 } 186 }
184 187
@@ -187,12 +190,12 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
187 write_unlock(&vnode->volume->servers_lock); 190 write_unlock(&vnode->volume->servers_lock);
188 191
189 set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags); 192 set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags);
190 fc->ac.error = afs_check_volume_status(vnode->volume, fc->key); 193 error = afs_check_volume_status(vnode->volume, fc->key);
191 if (fc->ac.error < 0) 194 if (error < 0)
192 goto failed; 195 goto failed_set_error;
193 196
194 if (test_bit(AFS_VOLUME_DELETED, &vnode->volume->flags)) { 197 if (test_bit(AFS_VOLUME_DELETED, &vnode->volume->flags)) {
195 fc->ac.error = -ENOMEDIUM; 198 fc->error = -ENOMEDIUM;
196 goto failed; 199 goto failed;
197 } 200 }
198 201
@@ -200,7 +203,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
200 * it's the fileserver having trouble. 203 * it's the fileserver having trouble.
201 */ 204 */
202 if (vnode->volume->servers == fc->server_list) { 205 if (vnode->volume->servers == fc->server_list) {
203 fc->ac.error = -EREMOTEIO; 206 fc->error = -EREMOTEIO;
204 goto next_server; 207 goto next_server;
205 } 208 }
206 209
@@ -215,7 +218,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
215 case VONLINE: 218 case VONLINE:
216 case VDISKFULL: 219 case VDISKFULL:
217 case VOVERQUOTA: 220 case VOVERQUOTA:
218 fc->ac.error = afs_abort_to_error(fc->ac.abort_code); 221 fc->error = afs_abort_to_error(fc->ac.abort_code);
219 goto next_server; 222 goto next_server;
220 223
221 case VOFFLINE: 224 case VOFFLINE:
@@ -224,11 +227,11 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
224 clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags); 227 clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags);
225 } 228 }
226 if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) { 229 if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) {
227 fc->ac.error = -EADV; 230 fc->error = -EADV;
228 goto failed; 231 goto failed;
229 } 232 }
230 if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) { 233 if (fc->flags & AFS_FS_CURSOR_CUR_ONLY) {
231 fc->ac.error = -ESTALE; 234 fc->error = -ESTALE;
232 goto failed; 235 goto failed;
233 } 236 }
234 goto busy; 237 goto busy;
@@ -240,7 +243,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
240 * have a file lock we need to maintain. 243 * have a file lock we need to maintain.
241 */ 244 */
242 if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) { 245 if (fc->flags & AFS_FS_CURSOR_NO_VSLEEP) {
243 fc->ac.error = -EBUSY; 246 fc->error = -EBUSY;
244 goto failed; 247 goto failed;
245 } 248 }
246 if (!test_and_set_bit(AFS_VOLUME_BUSY, &vnode->volume->flags)) { 249 if (!test_and_set_bit(AFS_VOLUME_BUSY, &vnode->volume->flags)) {
@@ -269,16 +272,16 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
269 * honour, just in case someone sets up a loop. 272 * honour, just in case someone sets up a loop.
270 */ 273 */
271 if (fc->flags & AFS_FS_CURSOR_VMOVED) { 274 if (fc->flags & AFS_FS_CURSOR_VMOVED) {
272 fc->ac.error = -EREMOTEIO; 275 fc->error = -EREMOTEIO;
273 goto failed; 276 goto failed;
274 } 277 }
275 fc->flags |= AFS_FS_CURSOR_VMOVED; 278 fc->flags |= AFS_FS_CURSOR_VMOVED;
276 279
277 set_bit(AFS_VOLUME_WAIT, &vnode->volume->flags); 280 set_bit(AFS_VOLUME_WAIT, &vnode->volume->flags);
278 set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags); 281 set_bit(AFS_VOLUME_NEEDS_UPDATE, &vnode->volume->flags);
279 fc->ac.error = afs_check_volume_status(vnode->volume, fc->key); 282 error = afs_check_volume_status(vnode->volume, fc->key);
280 if (fc->ac.error < 0) 283 if (error < 0)
281 goto failed; 284 goto failed_set_error;
282 285
283 /* If the server list didn't change, then the VLDB is 286 /* If the server list didn't change, then the VLDB is
284 * out of sync with the fileservers. This is hopefully 287 * out of sync with the fileservers. This is hopefully
@@ -290,7 +293,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
290 * TODO: Retry a few times with sleeps. 293 * TODO: Retry a few times with sleeps.
291 */ 294 */
292 if (vnode->volume->servers == fc->server_list) { 295 if (vnode->volume->servers == fc->server_list) {
293 fc->ac.error = -ENOMEDIUM; 296 fc->error = -ENOMEDIUM;
294 goto failed; 297 goto failed;
295 } 298 }
296 299
@@ -299,20 +302,25 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
299 default: 302 default:
300 clear_bit(AFS_VOLUME_OFFLINE, &vnode->volume->flags); 303 clear_bit(AFS_VOLUME_OFFLINE, &vnode->volume->flags);
301 clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags); 304 clear_bit(AFS_VOLUME_BUSY, &vnode->volume->flags);
302 fc->ac.error = afs_abort_to_error(fc->ac.abort_code); 305 fc->error = afs_abort_to_error(fc->ac.abort_code);
303 goto failed; 306 goto failed;
304 } 307 }
305 308
309 case -ETIMEDOUT:
310 case -ETIME:
311 if (fc->error != -EDESTADDRREQ)
312 goto iterate_address;
313 /* Fall through */
306 case -ENETUNREACH: 314 case -ENETUNREACH:
307 case -EHOSTUNREACH: 315 case -EHOSTUNREACH:
308 case -ECONNREFUSED: 316 case -ECONNREFUSED:
309 case -ETIMEDOUT:
310 case -ETIME:
311 _debug("no conn"); 317 _debug("no conn");
318 fc->error = error;
312 goto iterate_address; 319 goto iterate_address;
313 320
314 case -ECONNRESET: 321 case -ECONNRESET:
315 _debug("call reset"); 322 _debug("call reset");
323 fc->error = error;
316 goto failed; 324 goto failed;
317 } 325 }
318 326
@@ -328,9 +336,9 @@ start:
328 /* See if we need to do an update of the volume record. Note that the 336 /* See if we need to do an update of the volume record. Note that the
329 * volume may have moved or even have been deleted. 337 * volume may have moved or even have been deleted.
330 */ 338 */
331 fc->ac.error = afs_check_volume_status(vnode->volume, fc->key); 339 error = afs_check_volume_status(vnode->volume, fc->key);
332 if (fc->ac.error < 0) 340 if (error < 0)
333 goto failed; 341 goto failed_set_error;
334 342
335 if (!afs_start_fs_iteration(fc, vnode)) 343 if (!afs_start_fs_iteration(fc, vnode))
336 goto failed; 344 goto failed;
@@ -354,10 +362,10 @@ use_server:
354 * break request before we've finished decoding the reply and 362 * break request before we've finished decoding the reply and
355 * installing the vnode. 363 * installing the vnode.
356 */ 364 */
357 fc->ac.error = afs_register_server_cb_interest(vnode, fc->server_list, 365 error = afs_register_server_cb_interest(vnode, fc->server_list,
358 fc->index); 366 fc->index);
359 if (fc->ac.error < 0) 367 if (error < 0)
360 goto failed; 368 goto failed_set_error;
361 369
362 fc->cbi = afs_get_cb_interest(vnode->cb_interest); 370 fc->cbi = afs_get_cb_interest(vnode->cb_interest);
363 371
@@ -422,13 +430,14 @@ next_server:
422 if (fc->flags & AFS_FS_CURSOR_VBUSY) 430 if (fc->flags & AFS_FS_CURSOR_VBUSY)
423 goto restart_from_beginning; 431 goto restart_from_beginning;
424 432
425 fc->ac.error = -EDESTADDRREQ;
426 goto failed; 433 goto failed;
427 434
435failed_set_error:
436 fc->error = error;
428failed: 437failed:
429 fc->flags |= AFS_FS_CURSOR_STOP; 438 fc->flags |= AFS_FS_CURSOR_STOP;
430 afs_end_cursor(&fc->ac); 439 afs_end_cursor(&fc->ac);
431 _leave(" = f [failed %d]", fc->ac.error); 440 _leave(" = f [failed %d]", fc->error);
432 return false; 441 return false;
433} 442}
434 443
@@ -442,13 +451,14 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
442 struct afs_vnode *vnode = fc->vnode; 451 struct afs_vnode *vnode = fc->vnode;
443 struct afs_cb_interest *cbi = vnode->cb_interest; 452 struct afs_cb_interest *cbi = vnode->cb_interest;
444 struct afs_addr_list *alist; 453 struct afs_addr_list *alist;
454 int error = fc->ac.error;
445 455
446 _enter(""); 456 _enter("");
447 457
448 switch (fc->ac.error) { 458 switch (error) {
449 case SHRT_MAX: 459 case SHRT_MAX:
450 if (!cbi) { 460 if (!cbi) {
451 fc->ac.error = -ESTALE; 461 fc->error = -ESTALE;
452 fc->flags |= AFS_FS_CURSOR_STOP; 462 fc->flags |= AFS_FS_CURSOR_STOP;
453 return false; 463 return false;
454 } 464 }
@@ -461,7 +471,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
461 afs_get_addrlist(alist); 471 afs_get_addrlist(alist);
462 read_unlock(&cbi->server->fs_lock); 472 read_unlock(&cbi->server->fs_lock);
463 if (!alist) { 473 if (!alist) {
464 fc->ac.error = -ESTALE; 474 fc->error = -ESTALE;
465 fc->flags |= AFS_FS_CURSOR_STOP; 475 fc->flags |= AFS_FS_CURSOR_STOP;
466 return false; 476 return false;
467 } 477 }
@@ -475,11 +485,13 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
475 case 0: 485 case 0:
476 default: 486 default:
477 /* Success or local failure. Stop. */ 487 /* Success or local failure. Stop. */
488 fc->error = error;
478 fc->flags |= AFS_FS_CURSOR_STOP; 489 fc->flags |= AFS_FS_CURSOR_STOP;
479 _leave(" = f [okay/local %d]", fc->ac.error); 490 _leave(" = f [okay/local %d]", error);
480 return false; 491 return false;
481 492
482 case -ECONNABORTED: 493 case -ECONNABORTED:
494 fc->error = afs_abort_to_error(fc->ac.abort_code);
483 fc->flags |= AFS_FS_CURSOR_STOP; 495 fc->flags |= AFS_FS_CURSOR_STOP;
484 _leave(" = f [abort]"); 496 _leave(" = f [abort]");
485 return false; 497 return false;
@@ -490,6 +502,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
490 case -ETIMEDOUT: 502 case -ETIMEDOUT:
491 case -ETIME: 503 case -ETIME:
492 _debug("no conn"); 504 _debug("no conn");
505 fc->error = error;
493 goto iterate_address; 506 goto iterate_address;
494 } 507 }
495 508
@@ -512,7 +525,6 @@ iterate_address:
512int afs_end_vnode_operation(struct afs_fs_cursor *fc) 525int afs_end_vnode_operation(struct afs_fs_cursor *fc)
513{ 526{
514 struct afs_net *net = afs_v2net(fc->vnode); 527 struct afs_net *net = afs_v2net(fc->vnode);
515 int ret;
516 528
517 mutex_unlock(&fc->vnode->io_lock); 529 mutex_unlock(&fc->vnode->io_lock);
518 530
@@ -520,9 +532,8 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc)
520 afs_put_cb_interest(net, fc->cbi); 532 afs_put_cb_interest(net, fc->cbi);
521 afs_put_serverlist(net, fc->server_list); 533 afs_put_serverlist(net, fc->server_list);
522 534
523 ret = fc->ac.error; 535 if (fc->error == -ECONNABORTED)
524 if (ret == -ECONNABORTED) 536 fc->error = afs_abort_to_error(fc->ac.abort_code);
525 afs_abort_to_error(fc->ac.abort_code);
526 537
527 return fc->ac.error; 538 return fc->error;
528} 539}