Skip to content

Commit

Permalink
[PATCH] cifs: Ease memory pressure, do not use large buffers in byte …
Browse files Browse the repository at this point in the history
…range lock requests.

Signed-off-by: Steve French (sfrench@us.ibm.com)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Steve French authored and Linus Torvalds committed Apr 29, 2005
1 parent 79944bf commit 46810cb
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 149 deletions.
8 changes: 5 additions & 3 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
295 changes: 149 additions & 146 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 46810cb

Please sign in to comment.