From 535103e7a38e175fec082a658c2b70dbdd9af33e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 15 Nov 2013 09:12:40 +0100 Subject: [PATCH] s3:smb2_server: only allocate the required buffer in the smb2 recvfile() code path This way the buffer will likely be allocated within the existing talloc_pool, which avoids one malloc() per request. Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison --- source3/smbd/globals.h | 1 + source3/smbd/smb2_server.c | 48 ++++++++++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 3baa048c0de..cd99fe72ca1 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -768,6 +768,7 @@ struct smbd_server_connection { struct iovec vector; bool doing_receivefile; size_t min_recv_size; + size_t pktfull; size_t pktlen; uint8_t *pktbuf; } request_read_state; diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 0e42b7fdf71..4f6967968c4 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -2924,8 +2924,7 @@ static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state) } DEBUG(10,("Doing recvfile write len = %u\n", - (unsigned int)(state->pktlen - - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN))); + (unsigned int)(state->pktfull - state->pktlen))); return true; } @@ -3263,10 +3262,21 @@ again: * Read the rest of the data. */ state->doing_receivefile = false; + + state->pktbuf = talloc_realloc(state->req, + state->pktbuf, + uint8_t, + state->pktfull); + if (state->pktbuf == NULL) { + return NT_STATUS_NO_MEMORY; + } + state->vector.iov_base = (void *)(state->pktbuf + - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN); - state->vector.iov_len = (state->pktlen - - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN); + state->pktlen); + state->vector.iov_len = (state->pktfull - + state->pktlen); + + state->pktlen = state->pktfull; goto again; } @@ -3283,24 +3293,17 @@ again: if (state->hdr.nbt[0] != 0x00) { state->min_recv_size = 0; } - state->pktlen = smb2_len(state->hdr.nbt); - if (state->pktlen == 0) { + state->pktfull = smb2_len(state->hdr.nbt); + if (state->pktfull == 0) { goto got_full; } - state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen); - if (state->pktbuf == NULL) { - return NT_STATUS_NO_MEMORY; - } - - state->vector.iov_base = (void *)state->pktbuf; - if (state->min_recv_size != 0) { min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN; min_recvfile_size += state->min_recv_size; } - if (state->pktlen > min_recvfile_size) { + if (state->pktfull > min_recvfile_size) { /* * Might be a receivefile write. Read the SMB2 HEADER + * SMB2_WRITE header first. Set 'doing_receivefile' @@ -3309,12 +3312,20 @@ again: * not suitable then we'll just read the rest of the data * the next time this function is called. */ - state->vector.iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN; + state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN; state->doing_receivefile = true; } else { - state->vector.iov_len = state->pktlen; + state->pktlen = state->pktfull; } + state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen); + if (state->pktbuf == NULL) { + return NT_STATUS_NO_MEMORY; + } + + state->vector.iov_base = (void *)state->pktbuf; + state->vector.iov_len = state->pktlen; + goto again; got_full: @@ -3353,8 +3364,7 @@ got_full: if (req->smb1req == NULL) { return NT_STATUS_NO_MEMORY; } - req->smb1req->unread_bytes = - state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN; + req->smb1req->unread_bytes = state->pktfull - state->pktlen; } ZERO_STRUCTP(state); -- 2.11.4.GIT