s3:smb2_server: only allocate the required buffer in the smb2 recvfile() code path
authorStefan Metzmacher <metze@samba.org>
Fri, 15 Nov 2013 08:12:40 +0000 (09:12 +0100)
committerJeremy Allison <jra@samba.org>
Fri, 11 Apr 2014 19:41:08 +0000 (21:41 +0200)
This way the buffer will likely be allocated within the existing talloc_pool,
which avoids one malloc() per request.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/globals.h
source3/smbd/smb2_server.c

index 3baa048c0de57f88ca63a79e2394727fffb0c6f8..cd99fe72ca154423aa53f330ab46a58ef9eeb1a9 100644 (file)
@@ -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;
index 0e42b7fdf713cbdddc1f8057ef8b38815a258788..4f6967968c4f28996fd0aea52bbddb8d3ef216fa 100644 (file)
@@ -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);