diff options
author | Steve French <sfrench@us.ibm.com> | 2008-11-03 15:46:21 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-11-03 15:46:21 -0500 |
commit | c527c8a7ffa18400c2c1488f7ab5aff5e83f3c8e (patch) | |
tree | 4f051c90690aa89099d169baa7fdbce2a01cdea1 | |
parent | a75952b72a0fff3031124003e62118111aed42c1 (diff) |
[CIFS] Can't rely on iov length and base when kernel_recvmsg returns error
When retrying kernel_recvmsg, reset iov_base and iov_len.
Note comment from Sridhar: "In the normal path, iov.iov_len is clearly set to 4. But i think you are
running into a case where kernel_recvmsg() is called via 'goto incomplete_rcv'
It happens if the previous call fails with EAGAIN.
If you want to call recvmsg() after EAGAIN failure, you need to reset iov."
Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/connect.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e9f9248cb3fe..c682be8f2984 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -417,9 +417,14 @@ incomplete_rcv: | |||
417 | msleep(1); /* minimum sleep to prevent looping | 417 | msleep(1); /* minimum sleep to prevent looping |
418 | allowing socket to clear and app threads to set | 418 | allowing socket to clear and app threads to set |
419 | tcpStatus CifsNeedReconnect if server hung */ | 419 | tcpStatus CifsNeedReconnect if server hung */ |
420 | if (pdu_length < 4) | 420 | if (pdu_length < 4) { |
421 | iov.iov_base = (4 - pdu_length) + | ||
422 | (char *)smb_buffer; | ||
423 | iov.iov_len = pdu_length; | ||
424 | smb_msg.msg_control = NULL; | ||
425 | smb_msg.msg_controllen = 0; | ||
421 | goto incomplete_rcv; | 426 | goto incomplete_rcv; |
422 | else | 427 | } else |
423 | continue; | 428 | continue; |
424 | } else if (length <= 0) { | 429 | } else if (length <= 0) { |
425 | if (server->tcpStatus == CifsNew) { | 430 | if (server->tcpStatus == CifsNew) { |