diff options
author | Steve French <smfrench@austin.rr.com> | 2005-04-29 01:41:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-29 01:41:09 -0400 |
commit | 46810cbf3d951c1ce8ce3311639996ad43ca4ed1 (patch) | |
tree | 3b8a7cf7a9528501b0e3d72ccc8cbd384fd88b3a /fs/cifs/connect.c | |
parent | 79944bf71352f33f984ac3973b159b5c2cee139d (diff) |
[PATCH] cifs: Ease memory pressure, do not use large buffers in byte range lock requests.
Signed-off-by: Steve French (sfrench@us.ibm.com)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 295 |
1 files changed, 149 insertions, 146 deletions
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; |