[linux-cifs-client] cifs vfs performance patch

Steve French smfltc at us.ibm.com
Wed Nov 17 22:59:26 GMT 2004


I have been doing some experiments with cutting out some of the big 5
page (cifs request/response buffer) memory allocations in the response
processing path of the cifs vfs.   With connectathon basic timing tests
as a benchmark it yielded an 8% improvement locally (cifs mount to
Samaba 3.0.8 smbd on the same box) and even a bit better than that
running dbench with 12 processes (about 10%).  I need to clean it up to
handle smb signing but it does prove that this approach is helpful.  The
hard part is going to be staging this code in sensibly because the
buffer allocation strategy for the request buffers needs to be changed. 
The smb write path needs to use iovecs so we can do cifs_writepages
without buffer alloc and memcopy - And then there is JazzyJames's async
read ideas.  But this was a promising start.  For those interested here
is the quick and dirty test patch.


-------------- next part --------------
diff -Nau /home/stevef/cifs_back_mid_test/cifsglob.h /home/stevef/cifs_new_mid_test/cifsglob.h
--- /home/stevef/cifs_back_mid_test/cifsglob.h	2004-11-17 14:06:42.634251416 -0600
+++ /home/stevef/cifs_new_mid_test/cifsglob.h	2004-11-17 15:57:59.753175048 -0600
@@ -305,6 +305,7 @@
 	struct task_struct *tsk;	/* task waiting for response */
 	struct smb_hdr *resp_buf;	/* response buffer */
 	int midState;	/* wish this were enum but can not pass to wait_event */
+	unsigned trivialResponse:1;   /* response has wct/bcc zero or uninteresting */
 };
 
 struct oplock_q_entry {
diff -Nau /home/stevef/cifs_back_mid_test/connect.c /home/stevef/cifs_new_mid_test/connect.c
--- /home/stevef/cifs_back_mid_test/connect.c	2004-11-17 14:06:45.528811376 -0600
+++ /home/stevef/cifs_new_mid_test/connect.c	2004-11-17 15:57:56.873612808 -0600
@@ -385,15 +385,31 @@
 						cFYI(1,
 						     (" Mid 0x%x matched - waking up ",mid_entry->mid));
 						task_to_wake = mid_entry->tsk;
-						mid_entry->resp_buf =
-						    smb_buffer;
+						if(mid_entry->trivialResponse) {
+							if(smb_buffer->Status.CifsError != 0) {
+						/* if error, easier to return SMB */
+						/* buf freed by users thread after he is done */
+								mid_entry->resp_buf =
+									smb_buffer;
+								mid_entry->trivialResponse = 0;
+								smb_buffer = NULL;
+							} else {
+						/* no error, nothing in response to parse 
+						no need to return buf */
+								mid_entry->resp_buf = NULL;
+							}
+						} else {
+						/* buf freed by users thread after he is done */
+							smb_buffer = NULL;
+							mid_entry->resp_buf =
+								smb_buffer;
+						}
 						mid_entry->midState =
 						    MID_RESPONSE_RECEIVED;
 					}
 				}
 				spin_unlock(&GlobalMid_Lock);
 				if (task_to_wake) {
-					smb_buffer = NULL;	/* will be freed by users thread after he is done */
 					wake_up_process(task_to_wake);
 				} else if (is_valid_oplock_break(smb_buffer) == FALSE) {                          
 					cERROR(1, ("No task to wake, unknown frame rcvd!"));
diff -Nau /home/stevef/cifs_back_mid_test/transport.c /home/stevef/cifs_new_mid_test/transport.c
--- /home/stevef/cifs_back_mid_test/transport.c	2004-11-17 14:06:45.531810920 -0600
+++ /home/stevef/cifs_new_mid_test/transport.c	2004-11-17 15:57:56.876612352 -0600
@@ -67,6 +67,24 @@
 	atomic_inc(&midCount);
 	temp->midState = MID_REQUEST_ALLOCATED;
 	spin_unlock(&GlobalMid_Lock);
+
+	/* BB fixme BB */
+	switch(temp->command) {
+	case SMB_COM_CLOSE:
+	case SMB_COM_DELETE:
+	case SMB_COM_RENAME:
+	case SMB_COM_CREATE_DIRECTORY:
+	case SMB_COM_DELETE_DIRECTORY:
+	case SMB_COM_LOCKING_ANDX:
+	case SMB_COM_COPY:
+	case SMB_COM_FIND_CLOSE2:
+	case SMB_COM_TREE_DISCONNECT:
+	case SMB_COM_LOGOFF_ANDX:
+	case SMB_COM_NT_RENAME:
+		temp->trivialResponse = 1;
+	}
+	/* BB fixme end BB */
+
 	return temp;
 }
 
@@ -326,6 +344,14 @@
 	}
 
 	spin_lock(&GlobalMid_Lock);
+	if((midQ->trivialResponse)&&(midQ->midState == MID_RESPONSE_RECEIVED)){
+		spin_unlock(&GlobalMid_Lock);
+		*pbytes_returned = 0;
+		/* BB can not verify signature with this approach */
+		rc = 0;
+		goto cifs_no_response_exit;
+	}
+
 	if (midQ->resp_buf) {
 		spin_unlock(&GlobalMid_Lock);
 		receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
@@ -364,7 +390,6 @@
 			receive_len, xid));
 		rc = -EIO;
 	} else {		/* rcvd frame is ok */
-
 		if (midQ->resp_buf && out_buf
 		    && (midQ->midState == MID_RESPONSE_RECEIVED)) {
 			out_buf->smb_buf_length = receive_len;


More information about the linux-cifs-client mailing list