[CIFS] Readpages and readir performance improvements - eliminate extra
memcpy.  Part 1

Signed-off-by: Steve French <sfrench@us.ibm.com>
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 8bef2f3..1d21375 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,6 +1,7 @@
 Version 1.40
 ------------
-Use fsuid (fsgid) more consistently instead of uid (gid).
+Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
+of readpages by eliminating one extra memcpy.
 
 Version 1.39
 ------------
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index fe2bb7c..a2c2485 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsencrypt.c
  *
- *   Copyright (C) International Business Machines  Corp., 2003
+ *   Copyright (C) International Business Machines  Corp., 2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -82,6 +82,59 @@
 	return rc;
 }
 
+static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
+				const char * key, char * signature)
+{
+        struct  MD5Context context;
+
+        if((iov == NULL) || (signature == NULL))
+                return -EINVAL;
+
+        MD5Init(&context);
+        MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+
+/*        MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
+
+        MD5Final(signature,&context);
+
+	return -EOPNOTSUPP;
+/*        return 0; */
+}
+
+
+int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
+		   __u32 * pexpected_response_sequence_number)
+{
+	int rc = 0;
+	char smb_signature[20];
+	struct smb_hdr * cifs_pdu = iov[0].iov_base;
+
+	if((cifs_pdu == NULL) || (server == NULL))
+		return -EINVAL;
+
+	if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
+		return rc;
+
+        spin_lock(&GlobalMid_Lock);
+        cifs_pdu->Signature.Sequence.SequenceNumber = 
+				cpu_to_le32(server->sequence_number);
+        cifs_pdu->Signature.Sequence.Reserved = 0;
+
+        *pexpected_response_sequence_number = server->sequence_number++;
+        server->sequence_number++;
+        spin_unlock(&GlobalMid_Lock);
+
+        rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
+				      smb_signature);
+        if(rc)
+                memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+        else
+                memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+        return rc;
+
+}
+
 int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
 	__u32 expected_sequence_number)
 {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1b73f4f..c058f8a 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -48,7 +48,7 @@
 			struct smb_hdr * /* out */ ,
 			int * /* bytes returned */ , const int long_op);
 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
-			struct kvec *, int /* nvec */,
+			struct kvec *, int /* nvec to send */, 
 			int * /* bytes returned */ , const int long_op);
 extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
 extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
@@ -237,12 +237,10 @@
 			const __u64 lseek, unsigned int *nbytes,
 			const char *buf, const char __user *ubuf, 
 			const int long_op);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, const unsigned int count,
 			const __u64 offset, unsigned int *nbytes, 
 			struct kvec *iov, const int nvec, const int long_op);
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
 extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName, __u64 * inode_number,
 			const struct nls_table *nls_codepage, 
@@ -269,6 +267,8 @@
 extern int cifs_reconnect(struct TCP_Server_Info *server);
 
 extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
+extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
+			  __u32 *);
 extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
 	__u32 expected_sequence_number);
 extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6867e55..3565d3b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1155,7 +1155,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 int
 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 	     const int netfid, const unsigned int count,
@@ -1223,7 +1222,7 @@
 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
 		*nbytes = (*nbytes) << 16;
 		*nbytes += le16_to_cpu(pSMBr->Count);
-	}
+	} 
 
 	cifs_small_buf_release(pSMB);
 
@@ -1234,8 +1233,6 @@
 }
 
 
-#endif /* CIFS_EXPERIMENTAL */
-
 int
 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 	    const __u16 smb_file_id, const __u64 len,
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 14a1c72..b67be3d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -870,7 +870,6 @@
 				if (rc != 0)
 					break;
 			}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 			/* BB FIXME We can not sign across two buffers yet */
 			if((experimEnabled) && ((pTcon->ses->server->secMode & 
 			 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
@@ -889,7 +888,6 @@
 						iov, 1, long_op);
 			} else
 			/* BB FIXME fixup indentation of line below */
-#endif			
 			rc = CIFSSMBWrite(xid, pTcon,
 				 open_file->netfid,
 				 min_t(const int, cifs_sb->wsize, 
@@ -1026,7 +1024,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 static int cifs_writepages(struct address_space *mapping,
 			   struct writeback_control *wbc)
 {
@@ -1229,7 +1226,6 @@
 
 	return rc;
 }
-#endif
 
 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
 {
@@ -1875,9 +1871,7 @@
 	.readpage = cifs_readpage,
 	.readpages = cifs_readpages,
 	.writepage = cifs_writepage,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 	.writepages = cifs_writepages,
-#endif
 	.prepare_write = cifs_prepare_write,
 	.commit_write = cifs_commit_write,
 	.set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index f887119..0abfbf4 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -206,7 +206,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 static int
 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
 	  struct sockaddr *sin)
@@ -392,8 +391,7 @@
 		return -ENOMEM;
 	}
 
-/* BB FIXME */
-/* 	rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
+ 	rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
 
 	midQ->midState = MID_REQUEST_SUBMITTED;
 #ifdef CONFIG_CIFS_STATS2
@@ -492,11 +490,17 @@
 
 		if (midQ->resp_buf && 
 			(midQ->midState == MID_RESPONSE_RECEIVED)) {
+
 			in_buf->smb_buf_length = receive_len;
-			/* BB verify that length would not overrun small buf */
-			memcpy((char *)in_buf + 4,
-			       (char *)midQ->resp_buf + 4,
-			       receive_len);
+			if(receive_len > 500) {
+				/* use multiple buffers on way out */
+			} else { 
+				memcpy((char *)in_buf + 4,
+					(char *)midQ->resp_buf + 4,
+					receive_len);
+				iov[0].iov_len = receive_len + 4;
+				iov[1].iov_len = 0;
+			}
 
 			dump_smb(in_buf, 80);
 			/* convert the length into a more usable form */
@@ -549,7 +553,6 @@
 
 	return rc;
 }
-#endif /* CIFS_EXPERIMENTAL */
 
 int
 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,