History

CIFS: Fix an issue with re-sending rdata when transport returning -EAGAIN

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

Long Li committed 7 years ago

Commit 0b0dfd51 parent d53e2921 file · +41 −30Browse files

Unified · Split

fs/cifs/file.c+41−30
@@ -3361,44 +3361,55 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, · 3360 unmodified lines
33613361 struct TCP_Server_Info *server =
33623362 tlink_tcon(rdata->cfile->tlink)->ses->server;
33633363
3364− /*
3365− * Wait for credits to resend this rdata.
3366− * Note: we are attempting to resend the whole rdata not in segments
3367− */
33683364 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,
33703380 &rsize, &credits);
33713381
3372− if (rc)
3373− goto out;
3382+ if (rc)
3383+ goto fail;
33743384
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;
33803391
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+ }
33903399
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+ }
33963406
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);
34013410
3411+fail:
3412+ kref_put(&rdata->refcount, cifs_uncached_readdata_release);
34023413 return rc;
34033414 }
34043415