aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <smfrench@austin.rr.com>2005-04-29 01:41:09 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-29 01:41:09 -0400
commit46810cbf3d951c1ce8ce3311639996ad43ca4ed1 (patch)
tree3b8a7cf7a9528501b0e3d72ccc8cbd384fd88b3a
parent79944bf71352f33f984ac3973b159b5c2cee139d (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>
-rw-r--r--fs/cifs/cifssmb.c8
-rw-r--r--fs/cifs/connect.c295
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 }
453dmx_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;