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)
committerStefan Metzmacher <metze@samba.org>
Wed, 12 Mar 2014 23:04:40 +0000 (00:04 +0100)
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>
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 d6598127ca8f8f5659746bb0ba5571a000449ce2..f67fd44da2224c71a9faf70f67ba9331e85cf739 100644 (file)
@@ -2883,8 +2883,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;
 }
@@ -3222,10 +3221,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;
                }
 
@@ -3239,24 +3249,17 @@ again:
        /*
         * Now we analyze the NBT header
         */
-       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'
@@ -3265,12 +3268,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:
@@ -3309,8 +3320,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);