svn commit: samba r8024 - in branches/SAMBA_4_0/source/ntvfs/ipc: .

metze at samba.org metze at samba.org
Thu Jun 30 19:25:56 GMT 2005


Author: metze
Date: 2005-06-30 19:25:55 +0000 (Thu, 30 Jun 2005)
New Revision: 8024

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=8024

Log:
avoid one memcpy in the ipc_trans dcesrv_output() callback
we now can reference the DATA_BLOB that is used inside the dcesrv subsystem

metze
Modified:
   branches/SAMBA_4_0/source/ntvfs/ipc/vfs_ipc.c


Changeset:
Modified: branches/SAMBA_4_0/source/ntvfs/ipc/vfs_ipc.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/ipc/vfs_ipc.c	2005-06-30 19:24:29 UTC (rev 8023)
+++ branches/SAMBA_4_0/source/ntvfs/ipc/vfs_ipc.c	2005-06-30 19:25:55 UTC (rev 8024)
@@ -350,14 +350,14 @@
 	return NT_STATUS_ACCESS_DENIED;
 }
 
-static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *output, size_t *nwritten)
 {
 	DATA_BLOB *blob = private_data;
 
-	if (out->length < blob->length) {
-		blob->length = out->length;
+	if (output->length < blob->length) {
+		blob->length = output->length;
 	}
-	memcpy(blob->data, out->data, blob->length);
+	memcpy(blob->data, output->data, blob->length);
 	*nwritten = blob->length;
 	return NT_STATUS_OK;
 }
@@ -616,20 +616,33 @@
 	return NT_STATUS_ACCESS_DENIED;
 }
 
-static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+struct ipctp_dcesrv_output {
+	struct smbsrv_request *req;
+	struct smb_trans2 *trans;
+};
+static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *_output, size_t *nwritten)
 {
 	NTSTATUS status = NT_STATUS_OK;
-	DATA_BLOB *blob = private_data;
+	DATA_BLOB *output;
+	struct ipctp_dcesrv_output *ipctp = private_data;
 
-	if (out->length > blob->length) {
+	/*
+	 * do it the fast way without doing an extra memcpy()
+	 *
+	 * we need to reference the the DATA_BLOB itself,
+	 * because out->data isn't always a valid talloc pointer
+	 */
+	output = talloc_reference(ipctp->req, _output);
+	NT_STATUS_HAVE_NO_MEMORY(output);
+
+	if (output->length > ipctp->trans->in.max_data) {
 		status = STATUS_BUFFER_OVERFLOW;
 	}
 
-	if (out->length < blob->length) {
-		blob->length = out->length;
-	}
-	memcpy(blob->data, out->data, blob->length);
-	*nwritten = blob->length;
+	ipctp->trans->out.data.data	= output->data;
+	ipctp->trans->out.data.length	= MIN(ipctp->trans->in.max_data, output->length);
+
+	*nwritten = ipctp->trans->out.data.length;
 	return status;
 }
 
@@ -638,38 +651,36 @@
 			       struct smbsrv_request *req, struct smb_trans2 *trans)
 {
 	struct pipe_state *p;
-	struct ipc_private *private = ntvfs->private_data;
+	struct ipc_private *ipcp = ntvfs->private_data;
+	struct ipctp_dcesrv_output ipctp;
 	NTSTATUS status;
 
 	/* the fnum is in setup[1] */
-	p = pipe_state_find(private, trans->in.setup[1]);
-	if (!p) {
-		return NT_STATUS_INVALID_HANDLE;
-	}
+	p = pipe_state_find(ipcp, trans->in.setup[1]);
+	if (!p) return NT_STATUS_INVALID_HANDLE;
 
-	trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
-	if (!trans->out.data.data) {
-		return NT_STATUS_NO_MEMORY;
-	}
+	/*
+	 * just to be sure we doesn't have something uninitialized
+	 * the real work is done in the dcesrv_output() callback
+	 */
+	trans->out.data = data_blob(NULL, 0);
 
 	/* pass the data to the dcerpc server. Note that we don't
 	   expect this to fail, and things like NDR faults are not
 	   reported at this stage. Those sorts of errors happen in the
 	   dcesrv_output stage */
 	status = dcesrv_input(p->dce_conn, &trans->in.data);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
+	NT_STATUS_NOT_OK_RETURN(status);
 
 	/*
 	  now ask the dcerpc system for some output. This doesn't yet handle
-	  async calls. Again, we only expect NT_STATUS_OK. If the call fails then
-	  the error is encoded at the dcerpc level
+	  async calls. Again, we only expect NT_STATUS_OK or STATUS_BUFFER_OVERFLOW.
+	  If the call fails then the error is encoded at the dcerpc level
 	*/
-	status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
-	if (NT_STATUS_IS_ERR(status)) {
-		return status;
-	}
+	ipctp.req	= req;
+	ipctp.trans	= trans;
+	status = dcesrv_output(p->dce_conn, &ipctp, ipc_trans_dcesrv_output);
+	NT_STATUS_IS_ERR_RETURN(status);
 
 	trans->out.setup_count = 0;
 	trans->out.setup = NULL;



More information about the samba-cvs mailing list