[PATCH] cifs: Ease memory pressure, do not use large buffers in byte range lock requests.
authorSteve French <smfrench@austin.rr.com>
Fri, 29 Apr 2005 05:41:09 +0000 (22:41 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 29 Apr 2005 05:41:09 +0000 (22:41 -0700)
Signed-off-by: Steve French (sfrench@us.ibm.com)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/cifs/cifssmb.c
fs/cifs/connect.c

index 834297f7b5e197cf8bcba37e163c0ea15cef4727..a6e66974b2863135d298232cfb2973a7a9721658 100644 (file)
@@ -1023,11 +1023,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        __u16 count;
 
        cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
-       rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
+
        if (rc)
                return rc;
 
+       pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
+
        if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
                timeout = -1; /* no response expected */
                pSMB->Timeout = 0;
@@ -1065,7 +1067,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        if (rc) {
                cFYI(1, ("Send error in Lock = %d", rc));
        }
-       cifs_buf_release(pSMB);
+       cifs_small_buf_release(pSMB);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls 
        since file handle passed in no longer valid */
index 8c5d310514ea8304f719fe310fe3e236029057b7..419f145c80b53f5e84688e68fd35e840b7b4d089 100644 (file)
@@ -294,165 +294,168 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                        csocket = server->ssocket;
                        wake_up(&server->response_q);
                        continue;
-               } else if (length > 3) {
-                       pdu_length = ntohl(smb_buffer->smb_buf_length);
-               /* Only read pdu_length after below checks for too short (due
-                  to e.g. int overflow) and too long ie beyond end of buf */
-                       cFYI(1,("rfc1002 length(big endian)0x%x)",
-                               pdu_length+4));
-
-                       temp = (char *) smb_buffer;
-                       if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
-                               cFYI(0,("Received 4 byte keep alive packet"));
-                       } else if (temp[0] == 
-                               (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
-                                       cFYI(1,("Good RFC 1002 session rsp"));
-                       } else if (temp[0] == 
-                               (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
-                               /* we get this from Windows 98 instead of 
-                                  an error on SMB negprot response */
-                               cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
-                               if(server->tcpStatus == CifsNew) {
-                                       /* if nack on negprot (rather than 
-                                       ret of smb negprot error) reconnecting
-                                       not going to help, ret error to mount */
-                                       break;
-                               } else {
-                                       /* give server a second to
-                                       clean up before reconnect attempt */
-                                       msleep(1000);
-                                       /* always try 445 first on reconnect
-                                       since we get NACK on some if we ever
-                                       connected to port 139 (the NACK is 
-                                       since we do not begin with RFC1001
-                                       session initialize frame) */
-                                       server->addr.sockAddr.sin_port = 
-                                               htons(CIFS_PORT);
-                                       cifs_reconnect(server);
-                                       csocket = server->ssocket;
-                                       wake_up(&server->response_q);
-                                       continue;
-                               }
-                       } else if (temp[0] != (char) 0) {
-                               cERROR(1,("Unknown RFC 1002 frame"));
-                               cifs_dump_mem(" Received Data: ", temp, length);
+               } else if (length < 4) {
+                       cFYI(1,
+                           ("Frame less than four bytes received  %d bytes long.",
+                             length));
+                       cifs_reconnect(server);
+                       csocket = server->ssocket;
+                       wake_up(&server->response_q);
+                       continue;
+               }
+
+               /* the right amount was read from socket - 4 bytes */
+
+               pdu_length = ntohl(smb_buffer->smb_buf_length);
+               cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
+
+               temp = (char *) smb_buffer;
+               if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
+                       cFYI(0,("Received 4 byte keep alive packet"));
+               } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
+                               cFYI(1,("Good RFC 1002 session rsp"));
+               } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
+                       /* we get this from Windows 98 instead of 
+                          an error on SMB negprot response */
+                       cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
+                       if(server->tcpStatus == CifsNew) {
+                               /* if nack on negprot (rather than 
+                               ret of smb negprot error) reconnecting
+                               not going to help, ret error to mount */
+                               break;
+                       } else {
+                               /* give server a second to
+                               clean up before reconnect attempt */
+                               msleep(1000);
+                               /* always try 445 first on reconnect
+                               since we get NACK on some if we ever
+                               connected to port 139 (the NACK is 
+                               since we do not begin with RFC1001
+                               session initialize frame) */
+                               server->addr.sockAddr.sin_port = 
+                                       htons(CIFS_PORT);
                                cifs_reconnect(server);
                                csocket = server->ssocket;
+                               wake_up(&server->response_q);
                                continue;
-                       } else {
-                               if((pdu_length > CIFSMaxBufSize + 
-                                       MAX_CIFS_HDR_SIZE - 4) ||
-                                   (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
-                                       cERROR(1,
-                                           ("Invalid size SMB length %d and pdu_length %d",
-                                               length, pdu_length+4));
-                                       cifs_reconnect(server);
-                                       csocket = server->ssocket;
-                                       wake_up(&server->response_q);
-                                       continue;
-                               } else { /* length ok */
-                                       if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
-                                               isLargeBuf = TRUE;
-                                               memcpy(bigbuf, smallbuf, 4);
-                                               smb_buffer = bigbuf;
-                                       }
-                                       length = 0;
-                                       iov.iov_base = 4 + (char *)smb_buffer;
-                                       iov.iov_len = pdu_length;
-                                       for (total_read = 0;
-                                            total_read < pdu_length;
-                                            total_read += length) {
-                                               length = kernel_recvmsg(csocket, &smb_msg,
-                                                       &iov, 1,
-                                                       pdu_length - total_read, 0);
-                                               if((server->tcpStatus == CifsExiting) ||
-                                                   (length == -EINTR)) {
-                                                       /* then will exit */
-                                                       goto dmx_loop_end;
-                                               } else if (server->tcpStatus ==
-                                                           CifsNeedReconnect) {
-                                                       cifs_reconnect(server);
-                                                       csocket = server->ssocket;
-                                               /* Reconnect wakes up rspns q */
+                       }
+               } else if (temp[0] != (char) 0) {
+                       cERROR(1,("Unknown RFC 1002 frame"));
+                       cifs_dump_mem(" Received Data: ", temp, length);
+                       cifs_reconnect(server);
+                       csocket = server->ssocket;
+                       continue;
+               } else { /* we have an SMB response */
+                       if((pdu_length > CIFSMaxBufSize + 
+                               MAX_CIFS_HDR_SIZE - 4) ||
+                           (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
+                               cERROR(1,
+                                   ("Invalid size SMB length %d and pdu_length %d",
+                                       length, pdu_length+4));
+                               cifs_reconnect(server);
+                               csocket = server->ssocket;
+                               wake_up(&server->response_q);
+                               continue;
+                       } else { /* length ok */
+                               int reconnect = 0;
+
+                               if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
+                                       isLargeBuf = TRUE;
+                                       memcpy(bigbuf, smallbuf, 4);
+                                       smb_buffer = bigbuf;
+                               }
+                               length = 0;
+                               iov.iov_base = 4 + (char *)smb_buffer;
+                               iov.iov_len = pdu_length;
+                               for (total_read = 0;
+                                    total_read < pdu_length;
+                                    total_read += length) {
+                                       length = kernel_recvmsg(csocket, &smb_msg,
+                                               &iov, 1,
+                                               pdu_length - total_read, 0);
+                                       if((server->tcpStatus == CifsExiting) ||
+                                           (length == -EINTR)) {
+                                               /* then will exit */
+                                               reconnect = 2;
+                                               break;
+                                       } else if (server->tcpStatus ==
+                                                   CifsNeedReconnect) {
+                                               cifs_reconnect(server);
+                                               csocket = server->ssocket;
+                                               /* Reconnect wakes up rspns q */
                                                /* Now we will reread sock */
-                                                       goto dmx_loop_end;
-                                               } else if ((length == -ERESTARTSYS) || 
-                                                          (length == -EAGAIN)) {
-                                                       msleep(1); /* minimum sleep to prevent looping
-                                                                allowing socket to clear and app threads to set
-                                                                tcpStatus CifsNeedReconnect if server hung */
-                                                       continue;
-                                               } else if (length <= 0) {
-                                                       cERROR(1,
-                                                              ("Received no data, expecting %d",
-                                                               pdu_length - total_read));
-                                                       cifs_reconnect(server);
-                                                       csocket = server->ssocket;
-                                                       goto dmx_loop_end;
-                                               }
+                                               reconnect = 1;
+                                               break;
+                                       } else if ((length == -ERESTARTSYS) || 
+                                                  (length == -EAGAIN)) {
+                                               msleep(1); /* minimum sleep to prevent looping
+                                                              allowing socket to clear and app threads to set
+                                                              tcpStatus CifsNeedReconnect if server hung */
+                                               continue;
+                                       } else if (length <= 0) {
+                                               cERROR(1,("Received no data, expecting %d",
+                                                     pdu_length - total_read));
+                                               cifs_reconnect(server);
+                                               csocket = server->ssocket;
+                                               reconnect = 1;
+                                               break;
                                        }
-                                       length += 4; /* account for rfc1002 hdr */
                                }
+                               if(reconnect == 2)
+                                   break;
+                               else if(reconnect == 1)
+                                   continue;
 
-                               dump_smb(smb_buffer, length);
-                               if (checkSMB
-                                   (smb_buffer, smb_buffer->Mid, total_read+4)) {
-                                       cERROR(1, ("Bad SMB Received "));
-                                       continue;
-                               }
+                               length += 4; /* account for rfc1002 hdr */
+                       }
 
-                               /* BB FIXME - add checkTrans2SMBSecondary() */
-
-                               task_to_wake = NULL;
-                               spin_lock(&GlobalMid_Lock);
-                               list_for_each(tmp, &server->pending_mid_q) {
-                                       mid_entry = list_entry(tmp, struct
-                                                              mid_q_entry,
-                                                              qhead);
-
-                                       if ((mid_entry->mid == smb_buffer->Mid)
-                                               && (mid_entry->midState == 
-                                                       MID_REQUEST_SUBMITTED) 
-                                               && (mid_entry->command == 
-                                                       smb_buffer->Command)) {
-                                               cFYI(1,("Found Mid 0x%x wake up"
-                                                       ,mid_entry->mid));
-                                               task_to_wake = mid_entry->tsk;
-                                               mid_entry->resp_buf =
-                                                   smb_buffer;
-                                               mid_entry->midState =
-                                                   MID_RESPONSE_RECEIVED;
-                                               if(isLargeBuf)
-                                                       mid_entry->largeBuf = 1;
-                                               else
-                                                       mid_entry->largeBuf = 0;
-                                       }
-                               }
-                               spin_unlock(&GlobalMid_Lock);
-                               if (task_to_wake) {
+                       dump_smb(smb_buffer, length);
+                       if (checkSMB
+                           (smb_buffer, smb_buffer->Mid, total_read+4)) {
+                               cERROR(1, ("Bad SMB Received "));
+                               continue;
+                       }
+
+
+                       task_to_wake = NULL;
+                       spin_lock(&GlobalMid_Lock);
+                       list_for_each(tmp, &server->pending_mid_q) {
+                               mid_entry = list_entry(tmp, struct mid_q_entry,
+                                                       qhead);
+
+                               if ((mid_entry->mid == smb_buffer->Mid)
+                                       && (mid_entry->midState == 
+                                               MID_REQUEST_SUBMITTED) 
+                                       && (mid_entry->command == 
+                                               smb_buffer->Command)) {
+                                       cFYI(1,("Found Mid 0x%x wake up"
+                                               ,mid_entry->mid));
+                                       /* BB FIXME - missing code here BB */
+                                       /* check_2nd_t2(smb_buffer); */
+                                       task_to_wake = mid_entry->tsk;
+                                       mid_entry->resp_buf =
+                                           smb_buffer;
+                                       mid_entry->midState =
+                                           MID_RESPONSE_RECEIVED;
                                        if(isLargeBuf)
-                                               bigbuf = NULL;
+                                               mid_entry->largeBuf = 1;
                                        else
-                                               smallbuf = NULL;
-                                       smb_buffer = NULL; /* will be freed by users thread after he is done */
-                                       wake_up_process(task_to_wake);
-                               } else if (is_valid_oplock_break(smb_buffer) == FALSE) {                          
-                                       cERROR(1, ("No task to wake, unknown frame rcvd!"));
-                                       cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+                                               mid_entry->largeBuf = 0;
                                }
                        }
-               } else {
-                       cFYI(1,
-                           ("Frame less than four bytes received  %d bytes long.",
-                             length));
-                       cifs_reconnect(server);
-                       csocket = server->ssocket;
-                       wake_up(&server->response_q);
-                       continue;
+                       spin_unlock(&GlobalMid_Lock);
+                       if (task_to_wake) {
+                               if(isLargeBuf)
+                                       bigbuf = NULL;
+                               else
+                                       smallbuf = NULL;
+                               smb_buffer = NULL; /* will be freed by users thread after he is done */
+                               wake_up_process(task_to_wake);
+                       } else if (is_valid_oplock_break(smb_buffer) == FALSE) {                          
+                               cERROR(1, ("No task to wake, unknown frame rcvd!"));
+                               cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+                       }
                }
-dmx_loop_end:
-               cFYI(1,("Exiting cifsd loop"));
-
        }
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;