Commit 3d9c2472 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

CIFS: Move buffer allocation to a separate function

Reviewed-and-Tested-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarPavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent c4a5534a
...@@ -319,15 +319,53 @@ cifs_echo_request(struct work_struct *work) ...@@ -319,15 +319,53 @@ cifs_echo_request(struct work_struct *work)
queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL); queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
} }
static bool
allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
bool is_large_buf)
{
char *bbuf = *bigbuf, *sbuf = *smallbuf;
if (bbuf == NULL) {
bbuf = (char *)cifs_buf_get();
if (!bbuf) {
cERROR(1, "No memory for large SMB response");
msleep(3000);
/* retry will check if exiting */
return false;
}
} else if (is_large_buf) {
/* we are reusing a dirty large buf, clear its start */
memset(bbuf, 0, size);
}
if (sbuf == NULL) {
sbuf = (char *)cifs_small_buf_get();
if (!sbuf) {
cERROR(1, "No memory for SMB response");
msleep(1000);
/* retry will check if exiting */
return false;
}
/* beginning of smb buffer is cleared in our buf_get */
} else {
/* if existing small buf clear beginning */
memset(sbuf, 0, size);
}
*bigbuf = bbuf;
*smallbuf = sbuf;
return true;
}
static int static int
cifs_demultiplex_thread(void *p) cifs_demultiplex_thread(void *p)
{ {
int length; int length;
struct TCP_Server_Info *server = p; struct TCP_Server_Info *server = p;
unsigned int pdu_length, total_read; unsigned int pdu_length, total_read;
char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL;
struct smb_hdr *smb_buffer = NULL; struct smb_hdr *smb_buffer = NULL;
struct smb_hdr *bigbuf = NULL;
struct smb_hdr *smallbuf = NULL;
struct msghdr smb_msg; struct msghdr smb_msg;
struct kvec iov; struct kvec iov;
struct socket *csocket = server->ssocket; struct socket *csocket = server->ssocket;
...@@ -351,35 +389,16 @@ cifs_demultiplex_thread(void *p) ...@@ -351,35 +389,16 @@ cifs_demultiplex_thread(void *p)
while (server->tcpStatus != CifsExiting) { while (server->tcpStatus != CifsExiting) {
if (try_to_freeze()) if (try_to_freeze())
continue; continue;
if (bigbuf == NULL) {
bigbuf = cifs_buf_get();
if (!bigbuf) {
cERROR(1, "No memory for large SMB response");
msleep(3000);
/* retry will check if exiting */
continue;
}
} else if (isLargeBuf) {
/* we are reusing a dirty large buf, clear its start */
memset(bigbuf, 0, sizeof(struct smb_hdr));
}
if (smallbuf == NULL) { if (!allocate_buffers(&bigbuf, &smallbuf,
smallbuf = cifs_small_buf_get(); sizeof(struct smb_hdr), isLargeBuf))
if (!smallbuf) { continue;
cERROR(1, "No memory for SMB response");
msleep(1000);
/* retry will check if exiting */
continue;
}
/* beginning of smb buffer is cleared in our buf_get */
} else /* if existing small buf clear beginning */
memset(smallbuf, 0, sizeof(struct smb_hdr));
isLargeBuf = false; isLargeBuf = false;
isMultiRsp = false; isMultiRsp = false;
smb_buffer = smallbuf; smb_buffer = (struct smb_hdr *)smallbuf;
iov.iov_base = smb_buffer; buf = smallbuf;
iov.iov_base = buf;
iov.iov_len = 4; iov.iov_len = 4;
smb_msg.msg_control = NULL; smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0; smb_msg.msg_controllen = 0;
...@@ -417,8 +436,7 @@ cifs_demultiplex_thread(void *p) ...@@ -417,8 +436,7 @@ cifs_demultiplex_thread(void *p)
allowing socket to clear and app threads to set allowing socket to clear and app threads to set
tcpStatus CifsNeedReconnect if server hung */ tcpStatus CifsNeedReconnect if server hung */
if (pdu_length < 4) { if (pdu_length < 4) {
iov.iov_base = (4 - pdu_length) + iov.iov_base = (4 - pdu_length) + buf;
(char *)smb_buffer;
iov.iov_len = pdu_length; iov.iov_len = pdu_length;
smb_msg.msg_control = NULL; smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0; smb_msg.msg_controllen = 0;
...@@ -446,7 +464,7 @@ cifs_demultiplex_thread(void *p) ...@@ -446,7 +464,7 @@ cifs_demultiplex_thread(void *p)
/* the first byte big endian of the length field, /* the first byte big endian of the length field,
is actually not part of the length but the type is actually not part of the length but the type
with the most common, zero, as regular data */ with the most common, zero, as regular data */
temp = *((char *) smb_buffer); temp = *buf;
/* Note that FC 1001 length is big endian on the wire, /* Note that FC 1001 length is big endian on the wire,
but we convert it here so it is always manipulated but we convert it here so it is always manipulated
...@@ -480,8 +498,7 @@ cifs_demultiplex_thread(void *p) ...@@ -480,8 +498,7 @@ cifs_demultiplex_thread(void *p)
continue; continue;
} else if (temp != (char) 0) { } else if (temp != (char) 0) {
cERROR(1, "Unknown RFC 1002 frame"); cERROR(1, "Unknown RFC 1002 frame");
cifs_dump_mem(" Received Data: ", (char *)smb_buffer, cifs_dump_mem(" Received Data: ", buf, length);
length);
cifs_reconnect(server); cifs_reconnect(server);
csocket = server->ssocket; csocket = server->ssocket;
continue; continue;
...@@ -504,10 +521,11 @@ cifs_demultiplex_thread(void *p) ...@@ -504,10 +521,11 @@ cifs_demultiplex_thread(void *p)
if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
isLargeBuf = true; isLargeBuf = true;
memcpy(bigbuf, smallbuf, 4); memcpy(bigbuf, smallbuf, 4);
smb_buffer = bigbuf; smb_buffer = (struct smb_hdr *)bigbuf;
buf = bigbuf;
} }
length = 0; length = 0;
iov.iov_base = 4 + (char *)smb_buffer; iov.iov_base = 4 + buf;
iov.iov_len = pdu_length; iov.iov_len = pdu_length;
for (total_read = 0; total_read < pdu_length; for (total_read = 0; total_read < pdu_length;
total_read += length) { total_read += length) {
...@@ -562,8 +580,8 @@ cifs_demultiplex_thread(void *p) ...@@ -562,8 +580,8 @@ cifs_demultiplex_thread(void *p)
*/ */
length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); length = checkSMB(smb_buffer, smb_buffer->Mid, total_read);
if (length != 0) if (length != 0)
cifs_dump_mem("Bad SMB: ", smb_buffer, cifs_dump_mem("Bad SMB: ", buf,
min_t(unsigned int, total_read, 48)); min_t(unsigned int, total_read, 48));
mid_entry = NULL; mid_entry = NULL;
server->lstrp = jiffies; server->lstrp = jiffies;
...@@ -648,7 +666,7 @@ cifs_demultiplex_thread(void *p) ...@@ -648,7 +666,7 @@ cifs_demultiplex_thread(void *p)
!isMultiRsp) { !isMultiRsp) {
cERROR(1, "No task to wake, unknown frame received! " cERROR(1, "No task to wake, unknown frame received! "
"NumMids %d", atomic_read(&midCount)); "NumMids %d", atomic_read(&midCount));
cifs_dump_mem("Received Data is: ", (char *)smb_buffer, cifs_dump_mem("Received Data is: ", buf,
sizeof(struct smb_hdr)); sizeof(struct smb_hdr));
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
cifs_dump_detail(smb_buffer); cifs_dump_detail(smb_buffer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment