diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-09-03 12:00:49 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-09-08 17:22:33 -0400 |
commit | 7332f2a6217ee6925f83ef0e725013067ed316ba (patch) | |
tree | 481c0774aa1620f9e3f20e2809307d9047dd7324 /fs | |
parent | 522bbe65a2415fabce618186fc7777eb4c502989 (diff) |
cifs: eliminate some more premature cifsd exits
If the tcpStatus is still CifsNew, the main cifs_demultiplex_loop can
break out prematurely in some cases. This is wrong as we will almost
always have other structures with pointers to the TCP_Server_Info. If
the main loop breaks under any other condition other than tcpStatus ==
CifsExiting, then it'll face a use-after-free situation.
I don't see any reason to treat a CifsNew tcpStatus differently than
CifsGood. I believe we'll still want to attempt to reconnect in either
case. What should happen in those situations is that the MIDs get marked
as MID_RETRY_NEEDED. This will make CIFSSMBNegotiate return -EAGAIN, and
then the caller can retry the whole thing on a newly reconnected socket.
If that fails again in the same way, the caller of cifs_get_smb_ses
should tear down the TCP_Server_Info struct.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/connect.c | 41 |
1 files changed, 12 insertions, 29 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5f68b968faa7..5fde83f0c75e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -416,14 +416,6 @@ incomplete_rcv: | |||
416 | } else | 416 | } else |
417 | continue; | 417 | continue; |
418 | } else if (length <= 0) { | 418 | } else if (length <= 0) { |
419 | if (server->tcpStatus == CifsNew) { | ||
420 | cFYI(1, "tcp session abend after SMBnegprot"); | ||
421 | /* some servers kill the TCP session rather than | ||
422 | returning an SMB negprot error, in which | ||
423 | case reconnecting here is not going to help, | ||
424 | and so simply return error to mount */ | ||
425 | break; | ||
426 | } | ||
427 | cFYI(1, "Reconnect after unexpected peek error %d", | 419 | cFYI(1, "Reconnect after unexpected peek error %d", |
428 | length); | 420 | length); |
429 | cifs_reconnect(server); | 421 | cifs_reconnect(server); |
@@ -464,27 +456,18 @@ incomplete_rcv: | |||
464 | an error on SMB negprot response */ | 456 | an error on SMB negprot response */ |
465 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", | 457 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", |
466 | pdu_length); | 458 | pdu_length); |
467 | if (server->tcpStatus == CifsNew) { | 459 | /* give server a second to clean up */ |
468 | /* if nack on negprot (rather than | 460 | msleep(1000); |
469 | ret of smb negprot error) reconnecting | 461 | /* always try 445 first on reconnect since we get NACK |
470 | not going to help, ret error to mount */ | 462 | * on some if we ever connected to port 139 (the NACK |
471 | break; | 463 | * is since we do not begin with RFC1001 session |
472 | } else { | 464 | * initialize frame) |
473 | /* give server a second to | 465 | */ |
474 | clean up before reconnect attempt */ | 466 | server->addr.sockAddr.sin_port = htons(CIFS_PORT); |
475 | msleep(1000); | 467 | cifs_reconnect(server); |
476 | /* always try 445 first on reconnect | 468 | csocket = server->ssocket; |
477 | since we get NACK on some if we ever | 469 | wake_up(&server->response_q); |
478 | connected to port 139 (the NACK is | 470 | continue; |
479 | since we do not begin with RFC1001 | ||
480 | session initialize frame) */ | ||
481 | server->addr.sockAddr.sin_port = | ||
482 | htons(CIFS_PORT); | ||
483 | cifs_reconnect(server); | ||
484 | csocket = server->ssocket; | ||
485 | wake_up(&server->response_q); | ||
486 | continue; | ||
487 | } | ||
488 | } else if (temp != (char) 0) { | 471 | } else if (temp != (char) 0) { |
489 | cERROR(1, "Unknown RFC 1002 frame"); | 472 | cERROR(1, "Unknown RFC 1002 frame"); |
490 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, | 473 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, |