diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 4 | ||||
-rw-r--r-- | fs/cifs/connect.c | 101 |
2 files changed, 50 insertions, 55 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 51ed2de2307..a73dd1d5e7e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -291,9 +291,13 @@ struct TCP_Server_Info { bool sec_kerberosu2u; /* supports U2U Kerberos */ bool sec_kerberos; /* supports plain Kerberos */ bool sec_mskerberos; /* supports legacy MS Kerberos */ + bool large_buf; /* is current buffer large? */ struct delayed_work echo; /* echo ping workqueue job */ struct kvec *iov; /* reusable kvec array for receives */ unsigned int nr_iov; /* number of kvecs in array */ + char *smallbuf; /* pointer to current "small" buffer */ + char *bigbuf; /* pointer to current "big" buffer */ + unsigned int total_read; /* total amount of data read in this pass */ #ifdef CONFIG_CIFS_FSCACHE struct fscache_cookie *fscache; /* client index cache cookie */ #endif diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8d5a6156190..8918f935bf0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -320,27 +320,24 @@ requeue_echo: } static bool -allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size, - bool is_large_buf) +allocate_buffers(struct TCP_Server_Info *server) { - char *bbuf = *bigbuf, *sbuf = *smallbuf; - - if (bbuf == NULL) { - bbuf = (char *)cifs_buf_get(); - if (!bbuf) { + if (!server->bigbuf) { + server->bigbuf = (char *)cifs_buf_get(); + if (!server->bigbuf) { cERROR(1, "No memory for large SMB response"); msleep(3000); /* retry will check if exiting */ return false; } - } else if (is_large_buf) { + } else if (server->large_buf) { /* we are reusing a dirty large buf, clear its start */ - memset(bbuf, 0, size); + memset(server->bigbuf, 0, sizeof(struct smb_hdr)); } - if (sbuf == NULL) { - sbuf = (char *)cifs_small_buf_get(); - if (!sbuf) { + if (!server->smallbuf) { + server->smallbuf = (char *)cifs_small_buf_get(); + if (!server->smallbuf) { cERROR(1, "No memory for SMB response"); msleep(1000); /* retry will check if exiting */ @@ -349,12 +346,9 @@ allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size, /* beginning of smb buffer is cleared in our buf_get */ } else { /* if existing small buf clear beginning */ - memset(sbuf, 0, size); + memset(server->smallbuf, 0, sizeof(struct smb_hdr)); } - *bigbuf = bbuf; - *smallbuf = sbuf; - return true; } @@ -576,7 +570,7 @@ dequeue_mid(struct mid_q_entry *mid, int malformed) static struct mid_q_entry * find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf, - int malformed, bool is_large_buf, char **bigbuf) + int malformed) { struct mid_q_entry *mid = NULL; @@ -596,19 +590,27 @@ find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf, mid->multiEnd = true; goto multi_t2_fnd; } - if (!is_large_buf) { + if (!server->large_buf) { /*FIXME: switch to already allocated largebuf?*/ cERROR(1, "1st trans2 resp needs bigbuf"); } else { /* Have first buffer */ mid->resp_buf = buf; mid->largeBuf = true; - *bigbuf = NULL; + server->bigbuf = NULL; } return mid; } mid->resp_buf = buf; - mid->largeBuf = is_large_buf; + mid->largeBuf = server->large_buf; + /* Was previous buf put in mpx struct for multi-rsp? */ + if (!mid->multiRsp) { + /* smb buffer will be freed by user thread */ + if (server->large_buf) + server->bigbuf = NULL; + else + server->smallbuf = NULL; + } multi_t2_fnd: dequeue_mid(mid, malformed); return mid; @@ -715,12 +717,11 @@ cifs_demultiplex_thread(void *p) { int length; struct TCP_Server_Info *server = p; - unsigned int pdu_length, total_read; - char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL; + unsigned int pdu_length; + char *buf = NULL; struct smb_hdr *smb_buffer = NULL; struct task_struct *task_to_wake = NULL; struct mid_q_entry *mid_entry; - bool isLargeBuf = false; current->flags |= PF_MEMALLOC; cFYI(1, "Demultiplex PID: %d", task_pid_nr(current)); @@ -735,19 +736,18 @@ cifs_demultiplex_thread(void *p) if (try_to_freeze()) continue; - if (!allocate_buffers(&bigbuf, &smallbuf, - sizeof(struct smb_hdr), isLargeBuf)) + if (!allocate_buffers(server)) continue; - isLargeBuf = false; - smb_buffer = (struct smb_hdr *)smallbuf; - buf = smallbuf; + server->large_buf = false; + smb_buffer = (struct smb_hdr *)server->smallbuf; + buf = server->smallbuf; pdu_length = 4; /* enough to get RFC1001 header */ length = read_from_socket(server, buf, pdu_length); if (length < 0) continue; - total_read = length; + server->total_read = length; /* * The right amount was read from socket - 4 bytes, @@ -773,7 +773,7 @@ cifs_demultiplex_thread(void *p) sizeof(struct smb_hdr) - 1 - 4); if (length < 0) continue; - total_read += length; + server->total_read += length; if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { cERROR(1, "SMB response too long (%u bytes)", @@ -785,10 +785,11 @@ cifs_demultiplex_thread(void *p) /* else length ok */ if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { - isLargeBuf = true; - memcpy(bigbuf, smallbuf, total_read); - smb_buffer = (struct smb_hdr *)bigbuf; - buf = bigbuf; + server->large_buf = true; + memcpy(server->bigbuf, server->smallbuf, + server->total_read); + smb_buffer = (struct smb_hdr *)server->bigbuf; + buf = server->bigbuf; } /* now read the rest */ @@ -797,9 +798,9 @@ cifs_demultiplex_thread(void *p) pdu_length - sizeof(struct smb_hdr) + 1 + 4); if (length < 0) continue; - total_read += length; + server->total_read += length; - dump_smb(smb_buffer, total_read); + dump_smb(smb_buffer, server->total_read); /* * We know that we received enough to get to the MID as we @@ -810,28 +811,18 @@ cifs_demultiplex_thread(void *p) * 48 bytes is enough to display the header and a little bit * into the payload for debugging purposes. */ - length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); + length = checkSMB(smb_buffer, smb_buffer->Mid, + server->total_read); if (length != 0) cifs_dump_mem("Bad SMB: ", buf, - min_t(unsigned int, total_read, 48)); + min_t(unsigned int, server->total_read, 48)); server->lstrp = jiffies; - mid_entry = find_cifs_mid(server, smb_buffer, length, - isLargeBuf, &bigbuf); + mid_entry = find_cifs_mid(server, smb_buffer, length); if (mid_entry != NULL) { - if (mid_entry->multiRsp && !mid_entry->multiEnd) - continue; - - /* Was previous buf put in mpx struct for multi-rsp? */ - if (!mid_entry->multiRsp) { - /* smb buffer will be freed by user thread */ - if (isLargeBuf) - bigbuf = NULL; - else - smallbuf = NULL; - } - mid_entry->callback(mid_entry); + if (!mid_entry->multiRsp || mid_entry->multiEnd) + mid_entry->callback(mid_entry); } else if (length != 0) { /* response sanity checks failed */ continue; @@ -849,9 +840,9 @@ cifs_demultiplex_thread(void *p) } /* end while !EXITING */ /* buffer usually freed in free_mid - need to free it here on exit */ - cifs_buf_release(bigbuf); - if (smallbuf) /* no sense logging a debug message if NULL */ - cifs_small_buf_release(smallbuf); + cifs_buf_release(server->bigbuf); + if (server->smallbuf) /* no sense logging a debug message if NULL */ + cifs_small_buf_release(server->smallbuf); task_to_wake = xchg(&server->tsk, NULL); clean_demultiplex_info(server); |