When sending a rdata, transport may return -EAGAIN. In this case we should re-obtain credits because the session may have been reconnected. Change in v2: adjust_credits before re-sending
Unified · Split
| @@ -3361,44 +3361,55 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, · 3360 unmodified lines | ||
| 3361 | 3361 | struct TCP_Server_Info *server = |
| 3362 | 3362 | tlink_tcon(rdata->cfile->tlink)->ses->server; |
| 3363 | 3363 | |
| 3364 | − /* | |
| 3365 | − * Wait for credits to resend this rdata. | |
| 3366 | − * Note: we are attempting to resend the whole rdata not in segments | |
| 3367 | − */ | |
| 3368 | 3364 | do { |
| 3369 | − rc = server->ops->wait_mtu_credits(server, rdata->bytes, | |
| 3365 | + if (rdata->cfile->invalidHandle) { | |
| 3366 | + rc = cifs_reopen_file(rdata->cfile, true); | |
| 3367 | + if (rc == -EAGAIN) | |
| 3368 | + continue; | |
| 3369 | + else if (rc) | |
| 3370 | + break; | |
| 3371 | + } | |
| 3372 | + | |
| 3373 | + /* | |
| 3374 | + * Wait for credits to resend this rdata. | |
| 3375 | + * Note: we are attempting to resend the whole rdata not in | |
| 3376 | + * segments | |
| 3377 | + */ | |
| 3378 | + do { | |
| 3379 | + rc = server->ops->wait_mtu_credits(server, rdata->bytes, | |
| 3370 | 3380 | &rsize, &credits); |
| 3371 | 3381 | |
| 3372 | − if (rc) | |
| 3373 | − goto out; | |
| 3382 | + if (rc) | |
| 3383 | + goto fail; | |
| 3374 | 3384 | |
| 3375 | − if (rsize < rdata->bytes) { | |
| 3376 | − add_credits_and_wake_if(server, &credits, 0); | |
| 3377 | − msleep(1000); | |
| 3378 | − } | |
| 3379 | − } while (rsize < rdata->bytes); | |
| 3385 | + if (rsize < rdata->bytes) { | |
| 3386 | + add_credits_and_wake_if(server, &credits, 0); | |
| 3387 | + msleep(1000); | |
| 3388 | + } | |
| 3389 | + } while (rsize < rdata->bytes); | |
| 3390 | + rdata->credits = credits; | |
| 3380 | 3391 | |
| 3381 | − rdata->credits = credits; | |
| 3382 | − rc = -EAGAIN; | |
| 3383 | − while (rc == -EAGAIN) { | |
| 3384 | − rc = 0; | |
| 3385 | − if (rdata->cfile->invalidHandle) | |
| 3386 | − rc = cifs_reopen_file(rdata->cfile, true); | |
| 3387 | − if (!rc) | |
| 3388 | − rc = server->ops->async_readv(rdata); | |
| 3389 | − } | |
| 3392 | + rc = adjust_credits(server, &rdata->credits, rdata->bytes); | |
| 3393 | + if (!rc) { | |
| 3394 | + if (rdata->cfile->invalidHandle) | |
| 3395 | + rc = -EAGAIN; | |
| 3396 | + else | |
| 3397 | + rc = server->ops->async_readv(rdata); | |
| 3398 | + } | |
| 3390 | 3399 | |
| 3391 | − if (!rc) { | |
| 3392 | − /* Add to aio pending list */ | |
| 3393 | − list_add_tail(&rdata->list, rdata_list); | |
| 3394 | − return 0; | |
| 3395 | − } | |
| 3400 | + /* If the read was successfully sent, we are done */ | |
| 3401 | + if (!rc) { | |
| 3402 | + /* Add to aio pending list */ | |
| 3403 | + list_add_tail(&rdata->list, rdata_list); | |
| 3404 | + return 0; | |
| 3405 | + } | |
| 3396 | 3406 | |
| 3397 | − add_credits_and_wake_if(server, &rdata->credits, 0); | |
| 3398 | −out: | |
| 3399 | − kref_put(&rdata->refcount, | |
| 3400 | − cifs_uncached_readdata_release); | |
| 3407 | + /* Roll back credits and retry if needed */ | |
| 3408 | + add_credits_and_wake_if(server, &rdata->credits, 0); | |
| 3409 | + } while (rc == -EAGAIN); | |
| 3401 | 3410 | |
| 3411 | +fail: | |
| 3412 | + kref_put(&rdata->refcount, cifs_uncached_readdata_release); | |
| 3402 | 3413 | return rc; |
| 3403 | 3414 | } |
| 3404 | 3415 | |