diff options
Diffstat (limited to 'fs/cifs')
| -rw-r--r-- | fs/cifs/cifssmb.c | 8 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 295 |
2 files changed, 154 insertions, 149 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 834297f7b5e1..a6e66974b286 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1023,11 +1023,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
| 1023 | __u16 count; | 1023 | __u16 count; |
| 1024 | 1024 | ||
| 1025 | cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock)); | 1025 | cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock)); |
| 1026 | rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB, | 1026 | rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); |
| 1027 | (void **) &pSMBr); | 1027 | |
| 1028 | if (rc) | 1028 | if (rc) |
| 1029 | return rc; | 1029 | return rc; |
| 1030 | 1030 | ||
| 1031 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | ||
| 1032 | |||
| 1031 | if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1033 | if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
| 1032 | timeout = -1; /* no response expected */ | 1034 | timeout = -1; /* no response expected */ |
| 1033 | pSMB->Timeout = 0; | 1035 | pSMB->Timeout = 0; |
| @@ -1065,7 +1067,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
| 1065 | if (rc) { | 1067 | if (rc) { |
| 1066 | cFYI(1, ("Send error in Lock = %d", rc)); | 1068 | cFYI(1, ("Send error in Lock = %d", rc)); |
| 1067 | } | 1069 | } |
| 1068 | cifs_buf_release(pSMB); | 1070 | cifs_small_buf_release(pSMB); |
| 1069 | 1071 | ||
| 1070 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1072 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
| 1071 | since file handle passed in no longer valid */ | 1073 | since file handle passed in no longer valid */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8c5d310514ea..419f145c80b5 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -294,165 +294,168 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 294 | csocket = server->ssocket; | 294 | csocket = server->ssocket; |
| 295 | wake_up(&server->response_q); | 295 | wake_up(&server->response_q); |
| 296 | continue; | 296 | continue; |
| 297 | } else if (length > 3) { | 297 | } else if (length < 4) { |
| 298 | pdu_length = ntohl(smb_buffer->smb_buf_length); | 298 | cFYI(1, |
| 299 | /* Only read pdu_length after below checks for too short (due | 299 | ("Frame less than four bytes received %d bytes long.", |
| 300 | to e.g. int overflow) and too long ie beyond end of buf */ | 300 | length)); |
| 301 | cFYI(1,("rfc1002 length(big endian)0x%x)", | 301 | cifs_reconnect(server); |
| 302 | pdu_length+4)); | 302 | csocket = server->ssocket; |
| 303 | 303 | wake_up(&server->response_q); | |
| 304 | temp = (char *) smb_buffer; | 304 | continue; |
| 305 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { | 305 | } |
| 306 | cFYI(0,("Received 4 byte keep alive packet")); | 306 | |
| 307 | } else if (temp[0] == | 307 | /* the right amount was read from socket - 4 bytes */ |
| 308 | (char) RFC1002_POSITIVE_SESSION_RESPONSE) { | 308 | |
| 309 | cFYI(1,("Good RFC 1002 session rsp")); | 309 | pdu_length = ntohl(smb_buffer->smb_buf_length); |
| 310 | } else if (temp[0] == | 310 | cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); |
| 311 | (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | 311 | |
| 312 | /* we get this from Windows 98 instead of | 312 | temp = (char *) smb_buffer; |
| 313 | an error on SMB negprot response */ | 313 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { |
| 314 | cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); | 314 | cFYI(0,("Received 4 byte keep alive packet")); |
| 315 | if(server->tcpStatus == CifsNew) { | 315 | } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { |
| 316 | /* if nack on negprot (rather than | 316 | cFYI(1,("Good RFC 1002 session rsp")); |
| 317 | ret of smb negprot error) reconnecting | 317 | } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { |
| 318 | not going to help, ret error to mount */ | 318 | /* we get this from Windows 98 instead of |
| 319 | break; | 319 | an error on SMB negprot response */ |
| 320 | } else { | 320 | cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); |
| 321 | /* give server a second to | 321 | if(server->tcpStatus == CifsNew) { |
| 322 | clean up before reconnect attempt */ | 322 | /* if nack on negprot (rather than |
| 323 | msleep(1000); | 323 | ret of smb negprot error) reconnecting |
| 324 | /* always try 445 first on reconnect | 324 | not going to help, ret error to mount */ |
| 325 | since we get NACK on some if we ever | 325 | break; |
| 326 | connected to port 139 (the NACK is | 326 | } else { |
| 327 | since we do not begin with RFC1001 | 327 | /* give server a second to |
| 328 | session initialize frame) */ | 328 | clean up before reconnect attempt */ |
| 329 | server->addr.sockAddr.sin_port = | 329 | msleep(1000); |
| 330 | htons(CIFS_PORT); | 330 | /* always try 445 first on reconnect |
| 331 | cifs_reconnect(server); | 331 | since we get NACK on some if we ever |
| 332 | csocket = server->ssocket; | 332 | connected to port 139 (the NACK is |
| 333 | wake_up(&server->response_q); | 333 | since we do not begin with RFC1001 |
| 334 | continue; | 334 | session initialize frame) */ |
| 335 | } | 335 | server->addr.sockAddr.sin_port = |
| 336 | } else if (temp[0] != (char) 0) { | 336 | htons(CIFS_PORT); |
| 337 | cERROR(1,("Unknown RFC 1002 frame")); | ||
| 338 | cifs_dump_mem(" Received Data: ", temp, length); | ||
| 339 | cifs_reconnect(server); | 337 | cifs_reconnect(server); |
| 340 | csocket = server->ssocket; | 338 | csocket = server->ssocket; |
| 339 | wake_up(&server->response_q); | ||
| 341 | continue; | 340 | continue; |
| 342 | } else { | 341 | } |
| 343 | if((pdu_length > CIFSMaxBufSize + | 342 | } else if (temp[0] != (char) 0) { |
| 344 | MAX_CIFS_HDR_SIZE - 4) || | 343 | cERROR(1,("Unknown RFC 1002 frame")); |
| 345 | (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { | 344 | cifs_dump_mem(" Received Data: ", temp, length); |
| 346 | cERROR(1, | 345 | cifs_reconnect(server); |
| 347 | ("Invalid size SMB length %d and pdu_length %d", | 346 | csocket = server->ssocket; |
| 348 | length, pdu_length+4)); | 347 | continue; |
| 349 | cifs_reconnect(server); | 348 | } else { /* we have an SMB response */ |
| 350 | csocket = server->ssocket; | 349 | if((pdu_length > CIFSMaxBufSize + |
| 351 | wake_up(&server->response_q); | 350 | MAX_CIFS_HDR_SIZE - 4) || |
| 352 | continue; | 351 | (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { |
| 353 | } else { /* length ok */ | 352 | cERROR(1, |
| 354 | if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { | 353 | ("Invalid size SMB length %d and pdu_length %d", |
| 355 | isLargeBuf = TRUE; | 354 | length, pdu_length+4)); |
| 356 | memcpy(bigbuf, smallbuf, 4); | 355 | cifs_reconnect(server); |
| 357 | smb_buffer = bigbuf; | 356 | csocket = server->ssocket; |
| 358 | } | 357 | wake_up(&server->response_q); |
| 359 | length = 0; | 358 | continue; |
| 360 | iov.iov_base = 4 + (char *)smb_buffer; | 359 | } else { /* length ok */ |
| 361 | iov.iov_len = pdu_length; | 360 | int reconnect = 0; |
| 362 | for (total_read = 0; | 361 | |
| 363 | total_read < pdu_length; | 362 | if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { |
| 364 | total_read += length) { | 363 | isLargeBuf = TRUE; |
| 365 | length = kernel_recvmsg(csocket, &smb_msg, | 364 | memcpy(bigbuf, smallbuf, 4); |
| 366 | &iov, 1, | 365 | smb_buffer = bigbuf; |
| 367 | pdu_length - total_read, 0); | 366 | } |
| 368 | if((server->tcpStatus == CifsExiting) || | 367 | length = 0; |
| 369 | (length == -EINTR)) { | 368 | iov.iov_base = 4 + (char *)smb_buffer; |
| 370 | /* then will exit */ | 369 | iov.iov_len = pdu_length; |
| 371 | goto dmx_loop_end; | 370 | for (total_read = 0; |
| 372 | } else if (server->tcpStatus == | 371 | total_read < pdu_length; |
| 373 | CifsNeedReconnect) { | 372 | total_read += length) { |
| 374 | cifs_reconnect(server); | 373 | length = kernel_recvmsg(csocket, &smb_msg, |
| 375 | csocket = server->ssocket; | 374 | &iov, 1, |
| 376 | /* Reconnect wakes up rspns q */ | 375 | pdu_length - total_read, 0); |
| 376 | if((server->tcpStatus == CifsExiting) || | ||
| 377 | (length == -EINTR)) { | ||
| 378 | /* then will exit */ | ||
| 379 | reconnect = 2; | ||
| 380 | break; | ||
| 381 | } else if (server->tcpStatus == | ||
| 382 | CifsNeedReconnect) { | ||
| 383 | cifs_reconnect(server); | ||
| 384 | csocket = server->ssocket; | ||
| 385 | /* Reconnect wakes up rspns q */ | ||
| 377 | /* Now we will reread sock */ | 386 | /* Now we will reread sock */ |
| 378 | goto dmx_loop_end; | 387 | reconnect = 1; |
| 379 | } else if ((length == -ERESTARTSYS) || | 388 | break; |
| 380 | (length == -EAGAIN)) { | 389 | } else if ((length == -ERESTARTSYS) || |
| 381 | msleep(1); /* minimum sleep to prevent looping | 390 | (length == -EAGAIN)) { |
| 382 | allowing socket to clear and app threads to set | 391 | msleep(1); /* minimum sleep to prevent looping |
| 383 | tcpStatus CifsNeedReconnect if server hung */ | 392 | allowing socket to clear and app threads to set |
| 384 | continue; | 393 | tcpStatus CifsNeedReconnect if server hung */ |
| 385 | } else if (length <= 0) { | 394 | continue; |
| 386 | cERROR(1, | 395 | } else if (length <= 0) { |
| 387 | ("Received no data, expecting %d", | 396 | cERROR(1,("Received no data, expecting %d", |
| 388 | pdu_length - total_read)); | 397 | pdu_length - total_read)); |
| 389 | cifs_reconnect(server); | 398 | cifs_reconnect(server); |
| 390 | csocket = server->ssocket; | 399 | csocket = server->ssocket; |
| 391 | goto dmx_loop_end; | 400 | reconnect = 1; |
| 392 | } | 401 | break; |
| 393 | } | 402 | } |
| 394 | length += 4; /* account for rfc1002 hdr */ | ||
| 395 | } | 403 | } |
| 404 | if(reconnect == 2) | ||
| 405 | break; | ||
| 406 | else if(reconnect == 1) | ||
| 407 | continue; | ||
| 396 | 408 | ||
| 397 | dump_smb(smb_buffer, length); | 409 | length += 4; /* account for rfc1002 hdr */ |
| 398 | if (checkSMB | 410 | } |
| 399 | (smb_buffer, smb_buffer->Mid, total_read+4)) { | ||
| 400 | cERROR(1, ("Bad SMB Received ")); | ||
| 401 | continue; | ||
| 402 | } | ||
| 403 | 411 | ||
| 404 | /* BB FIXME - add checkTrans2SMBSecondary() */ | 412 | dump_smb(smb_buffer, length); |
| 405 | 413 | if (checkSMB | |
| 406 | task_to_wake = NULL; | 414 | (smb_buffer, smb_buffer->Mid, total_read+4)) { |
| 407 | spin_lock(&GlobalMid_Lock); | 415 | cERROR(1, ("Bad SMB Received ")); |
| 408 | list_for_each(tmp, &server->pending_mid_q) { | 416 | continue; |
| 409 | mid_entry = list_entry(tmp, struct | 417 | } |
| 410 | mid_q_entry, | 418 | |
| 411 | qhead); | 419 | |
| 412 | 420 | task_to_wake = NULL; | |
| 413 | if ((mid_entry->mid == smb_buffer->Mid) | 421 | spin_lock(&GlobalMid_Lock); |
| 414 | && (mid_entry->midState == | 422 | list_for_each(tmp, &server->pending_mid_q) { |
| 415 | MID_REQUEST_SUBMITTED) | 423 | mid_entry = list_entry(tmp, struct mid_q_entry, |
| 416 | && (mid_entry->command == | 424 | qhead); |
| 417 | smb_buffer->Command)) { | 425 | |
| 418 | cFYI(1,("Found Mid 0x%x wake up" | 426 | if ((mid_entry->mid == smb_buffer->Mid) |
| 419 | ,mid_entry->mid)); | 427 | && (mid_entry->midState == |
| 420 | task_to_wake = mid_entry->tsk; | 428 | MID_REQUEST_SUBMITTED) |
| 421 | mid_entry->resp_buf = | 429 | && (mid_entry->command == |
| 422 | smb_buffer; | 430 | smb_buffer->Command)) { |
| 423 | mid_entry->midState = | 431 | cFYI(1,("Found Mid 0x%x wake up" |
| 424 | MID_RESPONSE_RECEIVED; | 432 | ,mid_entry->mid)); |
| 425 | if(isLargeBuf) | 433 | /* BB FIXME - missing code here BB */ |
| 426 | mid_entry->largeBuf = 1; | 434 | /* check_2nd_t2(smb_buffer); */ |
| 427 | else | 435 | task_to_wake = mid_entry->tsk; |
| 428 | mid_entry->largeBuf = 0; | 436 | mid_entry->resp_buf = |
| 429 | } | 437 | smb_buffer; |
| 430 | } | 438 | mid_entry->midState = |
| 431 | spin_unlock(&GlobalMid_Lock); | 439 | MID_RESPONSE_RECEIVED; |
| 432 | if (task_to_wake) { | ||
| 433 | if(isLargeBuf) | 440 | if(isLargeBuf) |
| 434 | bigbuf = NULL; | 441 | mid_entry->largeBuf = 1; |
| 435 | else | 442 | else |
| 436 | smallbuf = NULL; | 443 | mid_entry->largeBuf = 0; |
| 437 | smb_buffer = NULL; /* will be freed by users thread after he is done */ | ||
| 438 | wake_up_process(task_to_wake); | ||
| 439 | } else if (is_valid_oplock_break(smb_buffer) == FALSE) { | ||
| 440 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | ||
| 441 | cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); | ||
| 442 | } | 444 | } |
| 443 | } | 445 | } |
| 444 | } else { | 446 | spin_unlock(&GlobalMid_Lock); |
| 445 | cFYI(1, | 447 | if (task_to_wake) { |
| 446 | ("Frame less than four bytes received %d bytes long.", | 448 | if(isLargeBuf) |
| 447 | length)); | 449 | bigbuf = NULL; |
| 448 | cifs_reconnect(server); | 450 | else |
| 449 | csocket = server->ssocket; | 451 | smallbuf = NULL; |
| 450 | wake_up(&server->response_q); | 452 | smb_buffer = NULL; /* will be freed by users thread after he is done */ |
| 451 | continue; | 453 | wake_up_process(task_to_wake); |
| 454 | } else if (is_valid_oplock_break(smb_buffer) == FALSE) { | ||
| 455 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | ||
| 456 | cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); | ||
| 457 | } | ||
| 452 | } | 458 | } |
| 453 | dmx_loop_end: | ||
| 454 | cFYI(1,("Exiting cifsd loop")); | ||
| 455 | |||
| 456 | } | 459 | } |
| 457 | spin_lock(&GlobalMid_Lock); | 460 | spin_lock(&GlobalMid_Lock); |
| 458 | server->tcpStatus = CifsExiting; | 461 | server->tcpStatus = CifsExiting; |
