s3:smb2_read: avoid 2 talloc* calls when using sendfile()
authorStefan Metzmacher <metze@samba.org>
Wed, 4 Dec 2013 11:32:36 +0000 (12:32 +0100)
committerJeremy Allison <jra@samba.org>
Wed, 5 Mar 2014 21:59:20 +0000 (13:59 -0800)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/smb2_read.c
source3/smbd/smb2_server.c

index 6478326ac068dfe10ff0dbdca77dd6c85d6b5ea8..474eaeae8aa2202d85e1c9f28d0018df0e57ff6c 100644 (file)
@@ -167,10 +167,16 @@ struct smbd_smb2_read_state {
        uint64_t in_offset;
        uint32_t in_minimum;
        DATA_BLOB out_headers;
+       uint8_t _out_hdr_buf[NBT_HDR_SIZE + SMB2_HDR_BODY + 0x10];
        DATA_BLOB out_data;
        uint32_t out_remaining;
 };
 
+static int smb2_smb2_read_state_deny_destructor(struct smbd_smb2_read_state *state)
+{
+       return -1;
+}
+
 /* struct smbd_smb2_read_state destructor. Send the SMB2_READ data. */
 static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state)
 {
@@ -258,7 +264,6 @@ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state)
 static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req,
                                        struct smbd_smb2_read_state *state)
 {
-       struct smbd_smb2_read_state *state_copy = NULL;
        files_struct *fsp = state->fsp;
 
        /*
@@ -293,16 +298,8 @@ static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req,
        state->out_data.length = state->in_length;
        state->out_remaining = 0;
 
-       /* Make a copy of state attached to the smb2req. Attach
-          the destructor here as this will trigger the sendfile
-          call when the request is destroyed. */
-       state_copy = talloc(smb2req, struct smbd_smb2_read_state);
-       if (!state_copy) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       *state_copy = *state;
-       talloc_set_destructor(state_copy, smb2_sendfile_send_data);
-       state->smb2req->queue_entry.sendfile_header = &state_copy->out_headers;
+       state->out_headers = data_blob_const(state->_out_hdr_buf,
+                                            sizeof(state->_out_hdr_buf));
        return NT_STATUS_OK;
 }
 
@@ -582,6 +579,15 @@ static NTSTATUS smbd_smb2_read_recv(struct tevent_req *req,
        talloc_steal(mem_ctx, out_data->data);
        *out_remaining = state->out_remaining;
 
-       tevent_req_received(req);
+       if (state->out_headers.length > 0) {
+               talloc_steal(mem_ctx, state);
+               talloc_set_destructor(state, smb2_smb2_read_state_deny_destructor);
+               tevent_req_received(req);
+               state->smb2req->queue_entry.sendfile_header = &state->out_headers;
+               talloc_set_destructor(state, smb2_sendfile_send_data);
+       } else {
+               tevent_req_received(req);
+       }
+
        return NT_STATUS_OK;
 }
index dea3915d96633091012e520219974ba33c56eb14..b805c1a3906c088261e61108e53fbffa0263d833 100644 (file)
@@ -3035,9 +3035,13 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
                                size += e->vector[i].iov_len;
                        }
 
-                       buf = talloc_array(e->mem_ctx, uint8_t, size);
-                       if (buf == NULL) {
-                               return NT_STATUS_NO_MEMORY;
+                       if (size <= e->sendfile_header->length) {
+                               buf = e->sendfile_header->data;
+                       } else {
+                               buf = talloc_array(e->mem_ctx, uint8_t, size);
+                               if (buf == NULL) {
+                                       return NT_STATUS_NO_MEMORY;
+                               }
                        }
 
                        size = 0;
@@ -3054,6 +3058,10 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn)
 
                        sconn->smb2.send_queue_len--;
                        DLIST_REMOVE(sconn->smb2.send_queue, e);
+                       /*
+                        * This triggers the sendfile path via
+                        * the destructor.
+                        */
                        talloc_free(e->mem_ctx);
                        continue;
                }