diff -Naur cifs-1.34-RHEL4/fs/cifs/cifsfs.c cifs-1.34-SLES9-SP2/fs/cifs/cifsfs.c
--- cifs-1.34-RHEL4/fs/cifs/cifsfs.c	2005-04-22 07:19:19.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/cifsfs.c	2005-04-22 07:22:49.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/seq_file.h>
 #include <linux/vfs.h>
 #include <linux/mempool.h>
+#include <linux/moduleparam.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -538,9 +539,9 @@
 };
 
 struct inode_operations cifs_symlink_inode_ops = {
-	.readlink = generic_readlink, 
+	.readlink = cifs_readlink, 
 	.follow_link = cifs_follow_link,
-	.put_link = cifs_put_link,
+/*	.put_link = cifs_put_link,*/
 	.permission = cifs_permission,
 	/* BB add the following two eventually */
 	/* revalidate: cifs_revalidate,
@@ -563,16 +564,11 @@
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
 	.sendfile = generic_file_sendfile,
-#ifdef CONFIG_CIFS_POSIX
-	.ioctl	= cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
-
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 	.readv = generic_file_readv,
 	.writev = generic_file_writev,
 	.aio_read = generic_file_aio_read,
 	.aio_write = generic_file_aio_write,
-	.dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
 
@@ -586,14 +582,7 @@
 	.lock = cifs_lock,
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
-	.sendfile = generic_file_sendfile, /* BB removeme BB */
-#ifdef CONFIG_CIFS_POSIX
-	.ioctl  = cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
-
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-	.dir_notify = cifs_dir_notify,
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
+	.sendfile = generic_file_sendfile,
 };
 
 struct file_operations cifs_dir_ops = {
diff -Naur cifs-1.34-RHEL4/fs/cifs/cifspdu.h cifs-1.34-SLES9-SP2/fs/cifs/cifspdu.h
--- cifs-1.34-RHEL4/fs/cifs/cifspdu.h	2005-04-22 07:18:13.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/cifspdu.h	2005-04-22 07:22:49.000000000 -0500
@@ -83,6 +83,14 @@
  * All constants go here
  *****************************************************************
  */
+#ifndef __le16
+#define __le16 __u16
+#define __le32 __u32
+#define __le64 __u64
+#define __be16 __u16
+#define __be32 __u32
+#define __be64 __u64
+#endif
 
 /*
  * Starting value for maximum SMB size negotiation
diff -Naur cifs-1.34-RHEL4/fs/cifs/connect.c cifs-1.34-SLES9-SP2/fs/cifs/connect.c
--- cifs-1.34-RHEL4/fs/cifs/connect.c	2005-04-22 07:19:19.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/connect.c	2005-04-22 07:22:49.000000000 -0500
@@ -318,7 +318,8 @@
 	struct smb_hdr *bigbuf = NULL;
 	struct smb_hdr *smallbuf = NULL;
 	struct msghdr smb_msg;
-	struct kvec iov;
+	mm_segment_t temp_fs;
+	struct iovec iov;
 	struct socket *csocket = server->ssocket;
 	struct list_head *tmp;
 	struct cifsSesInfo *ses;
@@ -334,6 +335,9 @@
 	current->flags |= PF_MEMALLOC;
 	server->tsk = current;	/* save process info to wake at shutdown */
 	cFYI(1, ("Demultiplex PID: %d", current->pid));
+	temp_fs = get_fs();     /* we must turn off socket api parm checking */
+	set_fs(get_ds());
+
 	write_lock(&GlobalSMBSeslock); 
 	atomic_inc(&tcpSesAllocCount);
 	length = tcpSesAllocCount.counter;
@@ -375,11 +379,13 @@
 		smb_buffer = smallbuf;
 		iov.iov_base = smb_buffer;
 		iov.iov_len = 4;
+		smb_msg.msg_iov = &iov;
+		smb_msg.msg_iovlen = 1;
 		smb_msg.msg_control = NULL;
 		smb_msg.msg_controllen = 0;
 		length =
-		    kernel_recvmsg(csocket, &smb_msg,
-				 &iov, 1, 4, 0 /* BB see socket.h flags */);
+		    sock_recvmsg(csocket, &smb_msg,
+				 4, 0 /* BB see socket.h flags */);
 
 		if(server->tcpStatus == CifsExiting) {
 			break;
@@ -492,8 +498,8 @@
 		iov.iov_len = pdu_length;
 		for (total_read = 0; total_read < pdu_length; 
 		     total_read += length) {
-			length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
-						pdu_length - total_read, 0);
+			length = sock_recvmsg(csocket, &smb_msg, 
+					      pdu_length - total_read, 0);
 			if((server->tcpStatus == CifsExiting) ||
 			    (length == -EINTR)) {
 				/* then will exit */
@@ -1250,7 +1256,7 @@
 	__be16 orig_port = 0;
 
 	if(*csocket == NULL) {
-		rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
+		rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
 		if (rc < 0) {
 			cERROR(1, ("Error %d creating socket",rc));
 			*csocket = NULL;
@@ -1358,7 +1364,7 @@
 	__be16 orig_port = 0;
 
 	if(*csocket == NULL) {
-		rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
+		rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
 		if (rc < 0) {
 			cERROR(1, ("Error %d creating ipv6 socket",rc));
 			*csocket = NULL;
diff -Naur cifs-1.34-RHEL4/fs/cifs/connect.c.orig cifs-1.34-SLES9-SP2/fs/cifs/connect.c.orig
--- cifs-1.34-RHEL4/fs/cifs/connect.c.orig	2005-04-22 07:18:13.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/connect.c.orig	2005-04-22 07:20:44.000000000 -0500
@@ -1734,8 +1734,6 @@
 			sb->s_maxbytes = (u64) 1 << 31;	/* 2 GB */
 	}
 
-	sb->s_time_gran = 100;
-
 /* on error free sesinfo and tcon struct if needed */
 	if (rc) {
 		/* if session setup failed, use count is zero but
diff -Naur cifs-1.34-RHEL4/fs/cifs/dir.c cifs-1.34-SLES9-SP2/fs/cifs/dir.c
--- cifs-1.34-RHEL4/fs/cifs/dir.c	2005-04-22 07:18:13.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/dir.c	2005-04-22 07:22:49.000000000 -0500
@@ -146,23 +146,23 @@
 	}
 
 	if(nd) {
-		if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
+		if ((nd->intent.it_flags & O_ACCMODE) == O_RDONLY)
 			desiredAccess = GENERIC_READ;
-		else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) {
+		else if ((nd->intent.it_flags & O_ACCMODE) == O_WRONLY) {
 			desiredAccess = GENERIC_WRITE;
 			write_only = TRUE;
-		} else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) {
+		} else if ((nd->intent.it_flags & O_ACCMODE) == O_RDWR) {
 			/* GENERIC_ALL is too much permission to request */
 			/* can cause unnecessary access denied on create */
 			/* desiredAccess = GENERIC_ALL; */
 			desiredAccess = GENERIC_READ | GENERIC_WRITE;
 		}
 
-		if((nd->intent.open.flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+		if((nd->intent.it_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
 			disposition = FILE_CREATE;
-		else if((nd->intent.open.flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+		else if((nd->intent.it_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
 			disposition = FILE_OVERWRITE_IF;
-		else if((nd->intent.open.flags & O_CREAT) == O_CREAT)
+		else if((nd->intent.it_flags & O_CREAT) == O_CREAT)
 			disposition = FILE_OPEN_IF;
 		else {
 			cFYI(1,("Create flag not set in create function"));
diff -Naur cifs-1.34-RHEL4/fs/cifs/link.c cifs-1.34-SLES9-SP2/fs/cifs/link.c
--- cifs-1.34-RHEL4/fs/cifs/link.c	2005-04-22 07:18:13.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/link.c	2005-04-22 07:22:49.000000000 -0500
@@ -138,6 +138,7 @@
 /* BB Add special case check for Samba DFS symlinks */
 
 		target_path[PATH_MAX-1] = 0;
+		rc = vfs_follow_link(nd, target_path);       
 	} else {
 		kfree(target_path);
 		target_path = ERR_PTR(rc);
@@ -147,7 +148,7 @@
 	kfree(full_path);
 out_no_free:
 	FreeXid(xid);
-	nd_set_link(nd, target_path);
+	/*nd_set_link(nd, target_path);*/
 	return 0;
 }
 
@@ -329,10 +330,3 @@
 	FreeXid(xid);
 	return rc;
 }
-
-void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
-{
-	char *p = nd_get_link(nd);
-	if (!IS_ERR(p))
-		kfree(p);
-}
diff -Naur cifs-1.34-RHEL4/fs/cifs/Makefile cifs-1.34-SLES9-SP2/fs/cifs/Makefile
--- cifs-1.34-RHEL4/fs/cifs/Makefile	2005-04-22 07:18:13.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/Makefile	2005-04-22 07:22:49.000000000 -0500
@@ -3,4 +3,4 @@
 #
 obj-$(CONFIG_CIFS) += cifs.o
 
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o
+cifs-objs := cifssmb.o cifs_debug.o file.o inode.o misc.o netmisc.o smbdes.o smbencrypt.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o readdir.o dir.o connect.o link.o transport.o cifsfs.o ioctl.o 
diff -Naur cifs-1.34-RHEL4/fs/cifs/transport.c cifs-1.34-SLES9-SP2/fs/cifs/transport.c
--- cifs-1.34-RHEL4/fs/cifs/transport.c	2005-04-22 07:18:13.000000000 -0500
+++ cifs-1.34-SLES9-SP2/fs/cifs/transport.c	2005-04-22 07:23:26.000000000 -0500
@@ -126,7 +126,8 @@
 	int rc = 0;
 	int i = 0;
 	struct msghdr smb_msg;
-	struct kvec iov;
+	struct iovec iov;
+	mm_segment_t temp_fs;
 	unsigned len = smb_buf_length + 4;
 
 	if(ssocket == NULL)
@@ -136,6 +137,8 @@
 
 	smb_msg.msg_name = sin;
 	smb_msg.msg_namelen = sizeof (struct sockaddr);
+	smb_msg.msg_iov = &iov;
+	smb_msg.msg_iovlen = 1;
 	smb_msg.msg_control = NULL;
 	smb_msg.msg_controllen = 0;
 	smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
@@ -149,8 +152,10 @@
 	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
 	dump_smb(smb_buffer, len);
 
+	temp_fs = get_fs();     /* we must turn off socket api parm checking */
+	set_fs(get_ds());
 	while (len > 0) {
-		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
+		rc = sock_sendmsg(ssocket, &smb_msg, len);
 		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 			i++;
 			if(i > 60) {
@@ -169,6 +174,7 @@
 		iov.iov_len -= rc;
 		len -= rc;
 	}
+	set_fs(temp_fs);
 
 	if (rc < 0) {
 		cERROR(1,("Error %d sending data on socket to server.", rc));
@@ -179,211 +185,6 @@
 	return rc;
 }
 
-#ifdef CIFS_EXPERIMENTAL
-/* BB finish off this function, adding support for writing set of pages as iovec */
-/* and also adding support for operations that need to parse the response smb    */
-
-int
-smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
-	 unsigned int smb_buf_length, struct kvec * write_vector 
-	  /* page list */, struct sockaddr *sin)
-{
-	int rc = 0;
-	int i = 0;
-	struct msghdr smb_msg;
-	number_of_pages += 1; /* account for SMB header */
-	struct kvec * piov  = kmalloc(number_of_pages * sizeof(struct kvec));
-	unsigned len = smb_buf_length + 4;
-
-	if(ssocket == NULL)
-		return -ENOTSOCK; /* BB eventually add reconnect code here */
-	iov.iov_base = smb_buffer;
-	iov.iov_len = len;
-
-	smb_msg.msg_name = sin;
-	smb_msg.msg_namelen = sizeof (struct sockaddr);
-	smb_msg.msg_control = NULL;
-	smb_msg.msg_controllen = 0;
-	smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
-
-	/* smb header is converted in header_assemble. bcc and rest of SMB word
-	   area, and byte area if necessary, is converted to littleendian in 
-	   cifssmb.c and RFC1001 len is converted to bigendian in smb_send 
-	   Flags2 is converted in SendReceive */
-
-	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
-	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
-	dump_smb(smb_buffer, len);
-
-	while (len > 0) {
-		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, 
-				    len);
-		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
-			i++;
-			if(i > 60) {
-				cERROR(1,
-				   ("sends on sock %p stuck for 30 seconds",
-				    ssocket));
-				rc = -EAGAIN;
-				break;
-			}
-			msleep(500);
-			continue;
-		}
-		if (rc < 0) 
-			break;
-		iov.iov_base += rc;
-		iov.iov_len -= rc;
-		len -= rc;
-	}
-
-	if (rc < 0) {
-		cERROR(1,("Error %d sending data on socket to server.", rc));
-	} else {
-		rc = 0;
-	}
-
-	return rc;
-}
-
-
-int
-CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
-	    struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op)
-{
-	int rc = 0;
-	unsigned long timeout = 15 * HZ;
-	struct mid_q_entry *midQ = NULL;
-
-	if (ses == NULL) {
-		cERROR(1,("Null smb session"));
-		return -EIO;
-	}
-	if(ses->server == NULL) {
-		cERROR(1,("Null tcp session"));
-		return -EIO;
-	}
-	if(pbytes_returned == NULL)
-		return -EIO;
-	else
-		*pbytes_returned = 0;
-
-  
-
-	if(ses->server->tcpStatus == CIFS_EXITING)
-		return -ENOENT;
-
-	/* Ensure that we do not send more than 50 overlapping requests 
-	   to the same server. We may make this configurable later or
-	   use ses->maxReq */
-	if(long_op == -1) {
-		/* oplock breaks must not be held up */
-		atomic_inc(&ses->server->inFlight);
-	} else {
-		spin_lock(&GlobalMid_Lock); 
-		while(1) {        
-			if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
-				spin_unlock(&GlobalMid_Lock);
-				wait_event(ses->server->request_q,
-					atomic_read(&ses->server->inFlight)
-					 < cifs_max_pending);
-				spin_lock(&GlobalMid_Lock);
-			} else {
-				if(ses->server->tcpStatus == CifsExiting) {
-					spin_unlock(&GlobalMid_Lock);
-					return -ENOENT;
-				}
-
-			/* can not count locking commands against total since
-			   they are allowed to block on server */
-					
-				if(long_op < 3) {
-				/* update # of requests on the wire to server */
-					atomic_inc(&ses->server->inFlight);
-				}
-				spin_unlock(&GlobalMid_Lock);
-				break;
-			}
-		}
-	}
-	/* make sure that we sign in the same order that we send on this socket 
-	   and avoid races inside tcp sendmsg code that could cause corruption
-	   of smb data */
-
-	down(&ses->server->tcpSem); 
-
-	if (ses->server->tcpStatus == CifsExiting) {
-		rc = -ENOENT;
-		goto cifs_out_label;
-	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
-		cFYI(1,("tcp session dead - return to caller to retry"));
-		rc = -EAGAIN;
-		goto cifs_out_label;
-	} else if (ses->status != CifsGood) {
-		/* check if SMB session is bad because we are setting it up */
-		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
-			(in_buf->Command != SMB_COM_NEGOTIATE)) {
-			rc = -EAGAIN;
-			goto cifs_out_label;
-		} /* else ok - we are setting up session */
-	}
-	midQ = AllocMidQEntry(in_buf, ses);
-	if (midQ == NULL) {
-		up(&ses->server->tcpSem);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
-		return -ENOMEM;
-	}
-
-	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
-		up(&ses->server->tcpSem);
-		cERROR(1,
-		       ("Illegal length, greater than maximum frame, %d ",
-			in_buf->smb_buf_length));
-		DeleteMidQEntry(midQ);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
-		return -EIO;
-	}
-
-	/* BB can we sign efficiently in this path? */
-	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
-
-	midQ->midState = MID_REQUEST_SUBMITTED;
-/*	rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
-		       piovec, 
-		       (struct sockaddr *) &(ses->server->addr.sockAddr));*/
-	if(rc < 0) {
-		DeleteMidQEntry(midQ);
-		up(&ses->server->tcpSem);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
-		return rc;
-	} else
-		up(&ses->server->tcpSem);
-cifs_out_label:
-	if(midQ)
-	        DeleteMidQEntry(midQ);
-                                                                                                                           
-	if(long_op < 3) {
-		atomic_dec(&ses->server->inFlight);
-		wake_up(&ses->server->request_q);
-	}
-
-	return rc;
-}
-
-
-#endif /* CIFS_EXPERIMENTAL */
 
 int
 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
diff -Naur cifs-1.34-RHEL4/fs/cifs/transport.c.orig cifs-1.34-SLES9-SP2/fs/cifs/transport.c.orig
--- cifs-1.34-RHEL4/fs/cifs/transport.c.orig	1969-12-31 18:00:00.000000000 -0600
+++ cifs-1.34-SLES9-SP2/fs/cifs/transport.c.orig	2005-04-22 07:20:44.000000000 -0500
@@ -0,0 +1,635 @@
+/*
+ *   fs/cifs/transport.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/net.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <linux/mempool.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+  
+extern mempool_t *cifs_mid_poolp;
+extern kmem_cache_t *cifs_oplock_cachep;
+
+static struct mid_q_entry *
+AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
+{
+	struct mid_q_entry *temp;
+
+	if (ses == NULL) {
+		cERROR(1, ("Null session passed in to AllocMidQEntry"));
+		return NULL;
+	}
+	if (ses->server == NULL) {
+		cERROR(1, ("Null TCP session in AllocMidQEntry"));
+		return NULL;
+	}
+	
+	temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS);
+	if (temp == NULL)
+		return temp;
+	else {
+		memset(temp, 0, sizeof (struct mid_q_entry));
+		temp->mid = smb_buffer->Mid;	/* always LE */
+		temp->pid = current->pid;
+		temp->command = smb_buffer->Command;
+		cFYI(1, ("For smb_command %d", temp->command));
+		do_gettimeofday(&temp->when_sent);
+		temp->ses = ses;
+		temp->tsk = current;
+	}
+
+	spin_lock(&GlobalMid_Lock);
+	list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
+	atomic_inc(&midCount);
+	temp->midState = MID_REQUEST_ALLOCATED;
+	spin_unlock(&GlobalMid_Lock);
+	return temp;
+}
+
+static void
+DeleteMidQEntry(struct mid_q_entry *midEntry)
+{
+	spin_lock(&GlobalMid_Lock);
+	midEntry->midState = MID_FREE;
+	list_del(&midEntry->qhead);
+	atomic_dec(&midCount);
+	spin_unlock(&GlobalMid_Lock);
+	if(midEntry->largeBuf)
+		cifs_buf_release(midEntry->resp_buf);
+	else
+		cifs_small_buf_release(midEntry->resp_buf);
+	mempool_free(midEntry, cifs_mid_poolp);
+}
+
+struct oplock_q_entry *
+AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
+{
+	struct oplock_q_entry *temp;
+	if ((pinode== NULL) || (tcon == NULL)) {
+		cERROR(1, ("Null parms passed to AllocOplockQEntry"));
+		return NULL;
+	}
+	temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
+						       SLAB_KERNEL);
+	if (temp == NULL)
+		return temp;
+	else {
+		temp->pinode = pinode;
+		temp->tcon = tcon;
+		temp->netfid = fid;
+		spin_lock(&GlobalMid_Lock);
+		list_add_tail(&temp->qhead, &GlobalOplock_Q);
+		spin_unlock(&GlobalMid_Lock);
+	}
+	return temp;
+
+}
+
+void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
+{
+	spin_lock(&GlobalMid_Lock); 
+    /* should we check if list empty first? */
+	list_del(&oplockEntry->qhead);
+	spin_unlock(&GlobalMid_Lock);
+	kmem_cache_free(cifs_oplock_cachep, oplockEntry);
+}
+
+int
+smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
+	 unsigned int smb_buf_length, struct sockaddr *sin)
+{
+	int rc = 0;
+	int i = 0;
+	struct msghdr smb_msg;
+	struct kvec iov;
+	unsigned len = smb_buf_length + 4;
+
+	if(ssocket == NULL)
+		return -ENOTSOCK; /* BB eventually add reconnect code here */
+	iov.iov_base = smb_buffer;
+	iov.iov_len = len;
+
+	smb_msg.msg_name = sin;
+	smb_msg.msg_namelen = sizeof (struct sockaddr);
+	smb_msg.msg_control = NULL;
+	smb_msg.msg_controllen = 0;
+	smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+
+	/* smb header is converted in header_assemble. bcc and rest of SMB word
+	   area, and byte area if necessary, is converted to littleendian in 
+	   cifssmb.c and RFC1001 len is converted to bigendian in smb_send 
+	   Flags2 is converted in SendReceive */
+
+	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
+	dump_smb(smb_buffer, len);
+
+	while (len > 0) {
+		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
+		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+			i++;
+			if(i > 60) {
+				cERROR(1,
+				   ("sends on sock %p stuck for 30 seconds",
+				    ssocket));
+				rc = -EAGAIN;
+				break;
+			}
+			msleep(500);
+			continue;
+		}
+		if (rc < 0) 
+			break;
+		iov.iov_base += rc;
+		iov.iov_len -= rc;
+		len -= rc;
+	}
+
+	if (rc < 0) {
+		cERROR(1,("Error %d sending data on socket to server.", rc));
+	} else {
+		rc = 0;
+	}
+
+	return rc;
+}
+
+#ifdef CIFS_EXPERIMENTAL
+/* BB finish off this function, adding support for writing set of pages as iovec */
+/* and also adding support for operations that need to parse the response smb    */
+
+int
+smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
+	 unsigned int smb_buf_length, struct kvec * write_vector 
+	  /* page list */, struct sockaddr *sin)
+{
+	int rc = 0;
+	int i = 0;
+	struct msghdr smb_msg;
+	number_of_pages += 1; /* account for SMB header */
+	struct kvec * piov  = kmalloc(number_of_pages * sizeof(struct kvec));
+	unsigned len = smb_buf_length + 4;
+
+	if(ssocket == NULL)
+		return -ENOTSOCK; /* BB eventually add reconnect code here */
+	iov.iov_base = smb_buffer;
+	iov.iov_len = len;
+
+	smb_msg.msg_name = sin;
+	smb_msg.msg_namelen = sizeof (struct sockaddr);
+	smb_msg.msg_control = NULL;
+	smb_msg.msg_controllen = 0;
+	smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+
+	/* smb header is converted in header_assemble. bcc and rest of SMB word
+	   area, and byte area if necessary, is converted to littleendian in 
+	   cifssmb.c and RFC1001 len is converted to bigendian in smb_send 
+	   Flags2 is converted in SendReceive */
+
+	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
+	dump_smb(smb_buffer, len);
+
+	while (len > 0) {
+		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, 
+				    len);
+		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+			i++;
+			if(i > 60) {
+				cERROR(1,
+				   ("sends on sock %p stuck for 30 seconds",
+				    ssocket));
+				rc = -EAGAIN;
+				break;
+			}
+			msleep(500);
+			continue;
+		}
+		if (rc < 0) 
+			break;
+		iov.iov_base += rc;
+		iov.iov_len -= rc;
+		len -= rc;
+	}
+
+	if (rc < 0) {
+		cERROR(1,("Error %d sending data on socket to server.", rc));
+	} else {
+		rc = 0;
+	}
+
+	return rc;
+}
+
+
+int
+CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
+	    struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op)
+{
+	int rc = 0;
+	unsigned long timeout = 15 * HZ;
+	struct mid_q_entry *midQ = NULL;
+
+	if (ses == NULL) {
+		cERROR(1,("Null smb session"));
+		return -EIO;
+	}
+	if(ses->server == NULL) {
+		cERROR(1,("Null tcp session"));
+		return -EIO;
+	}
+	if(pbytes_returned == NULL)
+		return -EIO;
+	else
+		*pbytes_returned = 0;
+
+  
+
+	if(ses->server->tcpStatus == CIFS_EXITING)
+		return -ENOENT;
+
+	/* Ensure that we do not send more than 50 overlapping requests 
+	   to the same server. We may make this configurable later or
+	   use ses->maxReq */
+	if(long_op == -1) {
+		/* oplock breaks must not be held up */
+		atomic_inc(&ses->server->inFlight);
+	} else {
+		spin_lock(&GlobalMid_Lock); 
+		while(1) {        
+			if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
+				spin_unlock(&GlobalMid_Lock);
+				wait_event(ses->server->request_q,
+					atomic_read(&ses->server->inFlight)
+					 < cifs_max_pending);
+				spin_lock(&GlobalMid_Lock);
+			} else {
+				if(ses->server->tcpStatus == CifsExiting) {
+					spin_unlock(&GlobalMid_Lock);
+					return -ENOENT;
+				}
+
+			/* can not count locking commands against total since
+			   they are allowed to block on server */
+					
+				if(long_op < 3) {
+				/* update # of requests on the wire to server */
+					atomic_inc(&ses->server->inFlight);
+				}
+				spin_unlock(&GlobalMid_Lock);
+				break;
+			}
+		}
+	}
+	/* make sure that we sign in the same order that we send on this socket 
+	   and avoid races inside tcp sendmsg code that could cause corruption
+	   of smb data */
+
+	down(&ses->server->tcpSem); 
+
+	if (ses->server->tcpStatus == CifsExiting) {
+		rc = -ENOENT;
+		goto cifs_out_label;
+	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
+		cFYI(1,("tcp session dead - return to caller to retry"));
+		rc = -EAGAIN;
+		goto cifs_out_label;
+	} else if (ses->status != CifsGood) {
+		/* check if SMB session is bad because we are setting it up */
+		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
+			(in_buf->Command != SMB_COM_NEGOTIATE)) {
+			rc = -EAGAIN;
+			goto cifs_out_label;
+		} /* else ok - we are setting up session */
+	}
+	midQ = AllocMidQEntry(in_buf, ses);
+	if (midQ == NULL) {
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -ENOMEM;
+	}
+
+	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		up(&ses->server->tcpSem);
+		cERROR(1,
+		       ("Illegal length, greater than maximum frame, %d ",
+			in_buf->smb_buf_length));
+		DeleteMidQEntry(midQ);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -EIO;
+	}
+
+	/* BB can we sign efficiently in this path? */
+	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+
+	midQ->midState = MID_REQUEST_SUBMITTED;
+/*	rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+		       piovec, 
+		       (struct sockaddr *) &(ses->server->addr.sockAddr));*/
+	if(rc < 0) {
+		DeleteMidQEntry(midQ);
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return rc;
+	} else
+		up(&ses->server->tcpSem);
+cifs_out_label:
+	if(midQ)
+	        DeleteMidQEntry(midQ);
+                                                                                                                           
+	if(long_op < 3) {
+		atomic_dec(&ses->server->inFlight);
+		wake_up(&ses->server->request_q);
+	}
+
+	return rc;
+}
+
+
+#endif /* CIFS_EXPERIMENTAL */
+
+int
+SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
+	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
+	    int *pbytes_returned, const int long_op)
+{
+	int rc = 0;
+	unsigned int receive_len;
+	unsigned long timeout;
+	struct mid_q_entry *midQ;
+
+	if (ses == NULL) {
+		cERROR(1,("Null smb session"));
+		return -EIO;
+	}
+	if(ses->server == NULL) {
+		cERROR(1,("Null tcp session"));
+		return -EIO;
+	}
+
+	if(ses->server->tcpStatus == CifsExiting)
+		return -ENOENT;
+
+	/* Ensure that we do not send more than 50 overlapping requests 
+	   to the same server. We may make this configurable later or
+	   use ses->maxReq */
+	if(long_op == -1) {
+		/* oplock breaks must not be held up */
+		atomic_inc(&ses->server->inFlight);
+	} else {
+		spin_lock(&GlobalMid_Lock); 
+		while(1) {        
+			if(atomic_read(&ses->server->inFlight) >= 
+					cifs_max_pending){
+				spin_unlock(&GlobalMid_Lock);
+				wait_event(ses->server->request_q,
+					atomic_read(&ses->server->inFlight)
+					 < cifs_max_pending);
+				spin_lock(&GlobalMid_Lock);
+			} else {
+				if(ses->server->tcpStatus == CifsExiting) {
+					spin_unlock(&GlobalMid_Lock);
+					return -ENOENT;
+				}
+
+			/* can not count locking commands against total since
+			   they are allowed to block on server */
+					
+				if(long_op < 3) {
+				/* update # of requests on the wire to server */
+					atomic_inc(&ses->server->inFlight);
+				}
+				spin_unlock(&GlobalMid_Lock);
+				break;
+			}
+		}
+	}
+	/* make sure that we sign in the same order that we send on this socket 
+	   and avoid races inside tcp sendmsg code that could cause corruption
+	   of smb data */
+
+	down(&ses->server->tcpSem); 
+
+	if (ses->server->tcpStatus == CifsExiting) {
+		rc = -ENOENT;
+		goto out_unlock;
+	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
+		cFYI(1,("tcp session dead - return to caller to retry"));
+		rc = -EAGAIN;
+		goto out_unlock;
+	} else if (ses->status != CifsGood) {
+		/* check if SMB session is bad because we are setting it up */
+		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
+			(in_buf->Command != SMB_COM_NEGOTIATE)) {
+			rc = -EAGAIN;
+			goto out_unlock;
+		} /* else ok - we are setting up session */
+	}
+	midQ = AllocMidQEntry(in_buf, ses);
+	if (midQ == NULL) {
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -ENOMEM;
+	}
+
+	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		up(&ses->server->tcpSem);
+		cERROR(1,
+		       ("Illegal length, greater than maximum frame, %d ",
+			in_buf->smb_buf_length));
+		DeleteMidQEntry(midQ);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -EIO;
+	}
+
+	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+
+	midQ->midState = MID_REQUEST_SUBMITTED;
+	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+		      (struct sockaddr *) &(ses->server->addr.sockAddr));
+	if(rc < 0) {
+		DeleteMidQEntry(midQ);
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return rc;
+	} else
+		up(&ses->server->tcpSem);
+	if (long_op == -1)
+		goto cifs_no_response_exit;
+	else if (long_op == 2) /* writes past end of file can take loong time */
+		timeout = 300 * HZ;
+	else if (long_op == 1)
+		timeout = 45 * HZ; /* should be greater than 
+			servers oplock break timeout (about 43 seconds) */
+	else if (long_op > 2) {
+		timeout = MAX_SCHEDULE_TIMEOUT;
+	} else
+		timeout = 15 * HZ;
+	/* wait for 15 seconds or until woken up due to response arriving or 
+	   due to last connection to this server being unmounted */
+	if (signal_pending(current)) {
+		/* if signal pending do not hold up user for full smb timeout
+		but we still give response a change to complete */
+		timeout = 2 * HZ;
+	}   
+
+	/* No user interrupts in wait - wreaks havoc with performance */
+	if(timeout != MAX_SCHEDULE_TIMEOUT) {
+		timeout += jiffies;
+		wait_event(ses->server->response_q,
+			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
+			time_after(jiffies, timeout) || 
+			((ses->server->tcpStatus != CifsGood) &&
+			 (ses->server->tcpStatus != CifsNew)));
+	} else {
+		wait_event(ses->server->response_q,
+			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
+			((ses->server->tcpStatus != CifsGood) &&
+			 (ses->server->tcpStatus != CifsNew)));
+	}
+
+	spin_lock(&GlobalMid_Lock);
+	if (midQ->resp_buf) {
+		spin_unlock(&GlobalMid_Lock);
+		receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
+	} else {
+		cERROR(1,("No response buffer"));
+		if(midQ->midState == MID_REQUEST_SUBMITTED) {
+			if(ses->server->tcpStatus == CifsExiting)
+				rc = -EHOSTDOWN;
+			else {
+				ses->server->tcpStatus = CifsNeedReconnect;
+				midQ->midState = MID_RETRY_NEEDED;
+			}
+		}
+
+		if (rc != -EHOSTDOWN) {
+			if(midQ->midState == MID_RETRY_NEEDED) {
+				rc = -EAGAIN;
+				cFYI(1,("marking request for retry"));
+			} else {
+				rc = -EIO;
+			}
+		}
+		spin_unlock(&GlobalMid_Lock);
+		DeleteMidQEntry(midQ);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return rc;
+	}
+  
+	if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
+		cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
+			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;
+			memcpy((char *)out_buf + 4,
+			       (char *)midQ->resp_buf + 4,
+			       receive_len);
+
+			dump_smb(out_buf, 92);
+			/* convert the length into a more usable form */
+			if((receive_len > 24) &&
+			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
+					SECMODE_SIGN_ENABLED))) {
+				rc = cifs_verify_signature(out_buf,
+						ses->server->mac_signing_key,
+						midQ->sequence_number+1);
+				if(rc) {
+					cERROR(1,("Unexpected SMB signature"));
+					/* BB FIXME add code to kill session */
+				}
+			}
+
+			*pbytes_returned = out_buf->smb_buf_length;
+
+			/* BB special case reconnect tid and uid here? */
+			rc = map_smb_to_linux_error(out_buf);
+
+			/* convert ByteCount if necessary */
+			if (receive_len >=
+			    sizeof (struct smb_hdr) -
+			    4 /* do not count RFC1001 header */  +
+			    (2 * out_buf->WordCount) + 2 /* bcc */ )
+				BCC(out_buf) = le16_to_cpu(BCC(out_buf));
+		} else {
+			rc = -EIO;
+			cFYI(1,("Bad MID state? "));
+		}
+	}
+cifs_no_response_exit:
+	DeleteMidQEntry(midQ);
+
+	if(long_op < 3) {
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
+	}
+
+	return rc;
+
+out_unlock:
+	up(&ses->server->tcpSem);
+	/* If not lock req, update # of requests on wire to server */
+	if(long_op < 3) {
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
+	}
+
+	return rc;
+}
