Skip to content

Commit 0b0dfd5

Browse files
longlimsftSteve French
authored andcommitted
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 Signed-off-by: Long Li <longli@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
1 parent d53e292 commit 0b0dfd5

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

fs/cifs/file.c

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3361,44 +3361,55 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata,
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

0 commit comments

Comments
 (0)