Browse Source

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  cifs: make sure we allocate enough storage for socket address
  [CIFS] Make socket retry timeouts consistent between blocking and nonblocking cases
  [CIFS] some cleanup to dir.c prior to addition of posix_open
  [CIFS] revalidate parent inode when rmdir done within that directory
  [CIFS] Rename md5 functions to avoid collision with new rt modules
  cifs: turn smb_send into a wrapper around smb_sendv
Linus Torvalds 16 years ago
parent
commit
f2257b70b0
9 changed files with 121 additions and 161 deletions
  1. 3 1
      fs/cifs/CHANGES
  2. 9 9
      fs/cifs/cifsencrypt.c
  3. 2 2
      fs/cifs/cifsproto.h
  4. 11 13
      fs/cifs/connect.c
  5. 31 25
      fs/cifs/dir.c
  6. 5 0
      fs/cifs/inode.c
  7. 19 19
      fs/cifs/md5.c
  8. 3 3
      fs/cifs/md5.h
  9. 38 89
      fs/cifs/transport.c

+ 3 - 1
fs/cifs/CHANGES

@@ -5,7 +5,9 @@ rather than posix (advisory) byte range locks, even though server would
 support posix byte range locks.  Fix query of root inode when prefixpath
 support posix byte range locks.  Fix query of root inode when prefixpath
 specified and user does not have access to query information about the
 specified and user does not have access to query information about the
 top of the share.  Fix problem in 2.6.28 resolving DFS paths to
 top of the share.  Fix problem in 2.6.28 resolving DFS paths to
-Samba servers (worked to Windows).
+Samba servers (worked to Windows).  Fix rmdir so that pending search
+(readdir) requests do not get invalid results which include the now
+removed directory.
 
 
 Version 1.55
 Version 1.55
 ------------
 ------------

+ 9 - 9
fs/cifs/cifsencrypt.c

@@ -48,11 +48,11 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
 	if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
 	if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	MD5Init(&context);
-	MD5Update(&context, (char *)&key->data, key->len);
-	MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
+	cifs_MD5_init(&context);
+	cifs_MD5_update(&context, (char *)&key->data, key->len);
+	cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
 
 
-	MD5Final(signature, &context);
+	cifs_MD5_final(signature, &context);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -96,8 +96,8 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
 	if ((iov == NULL) || (signature == NULL) || (key == NULL))
 	if ((iov == NULL) || (signature == NULL) || (key == NULL))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	MD5Init(&context);
-	MD5Update(&context, (char *)&key->data, key->len);
+	cifs_MD5_init(&context);
+	cifs_MD5_update(&context, (char *)&key->data, key->len);
 	for (i = 0; i < n_vec; i++) {
 	for (i = 0; i < n_vec; i++) {
 		if (iov[i].iov_len == 0)
 		if (iov[i].iov_len == 0)
 			continue;
 			continue;
@@ -110,13 +110,13 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
 		if (i == 0) {
 		if (i == 0) {
 			if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
 			if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
 				break; /* nothing to sign or corrupt header */
 				break; /* nothing to sign or corrupt header */
-			MD5Update(&context, iov[0].iov_base+4,
+			cifs_MD5_update(&context, iov[0].iov_base+4,
 				  iov[0].iov_len-4);
 				  iov[0].iov_len-4);
 		} else
 		} else
-			MD5Update(&context, iov[i].iov_base, iov[i].iov_len);
+			cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len);
 	}
 	}
 
 
-	MD5Final(signature, &context);
+	cifs_MD5_final(signature, &context);
 
 
 	return 0;
 	return 0;
 }
 }

+ 2 - 2
fs/cifs/cifsproto.h

@@ -35,8 +35,8 @@ extern struct smb_hdr *cifs_buf_get(void);
 extern void cifs_buf_release(void *);
 extern void cifs_buf_release(void *);
 extern struct smb_hdr *cifs_small_buf_get(void);
 extern struct smb_hdr *cifs_small_buf_get(void);
 extern void cifs_small_buf_release(void *);
 extern void cifs_small_buf_release(void *);
-extern int smb_send(struct socket *, struct smb_hdr *,
-			unsigned int /* length */ , struct sockaddr *, bool);
+extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
+			unsigned int /* length */);
 extern unsigned int _GetXid(void);
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
 extern void _FreeXid(unsigned int);
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));

+ 11 - 13
fs/cifs/connect.c

@@ -1354,7 +1354,7 @@ cifs_parse_mount_options(char *options, const char *devname,
 }
 }
 
 
 static struct TCP_Server_Info *
 static struct TCP_Server_Info *
-cifs_find_tcp_session(struct sockaddr *addr)
+cifs_find_tcp_session(struct sockaddr_storage *addr)
 {
 {
 	struct list_head *tmp;
 	struct list_head *tmp;
 	struct TCP_Server_Info *server;
 	struct TCP_Server_Info *server;
@@ -1374,11 +1374,11 @@ cifs_find_tcp_session(struct sockaddr *addr)
 		if (server->tcpStatus == CifsNew)
 		if (server->tcpStatus == CifsNew)
 			continue;
 			continue;
 
 
-		if (addr->sa_family == AF_INET &&
+		if (addr->ss_family == AF_INET &&
 		    (addr4->sin_addr.s_addr !=
 		    (addr4->sin_addr.s_addr !=
 		     server->addr.sockAddr.sin_addr.s_addr))
 		     server->addr.sockAddr.sin_addr.s_addr))
 			continue;
 			continue;
-		else if (addr->sa_family == AF_INET6 &&
+		else if (addr->ss_family == AF_INET6 &&
 			 memcmp(&server->addr.sockAddr6.sin6_addr,
 			 memcmp(&server->addr.sockAddr6.sin6_addr,
 				&addr6->sin6_addr, sizeof(addr6->sin6_addr)))
 				&addr6->sin6_addr, sizeof(addr6->sin6_addr)))
 			continue;
 			continue;
@@ -1419,12 +1419,12 @@ static struct TCP_Server_Info *
 cifs_get_tcp_session(struct smb_vol *volume_info)
 cifs_get_tcp_session(struct smb_vol *volume_info)
 {
 {
 	struct TCP_Server_Info *tcp_ses = NULL;
 	struct TCP_Server_Info *tcp_ses = NULL;
-	struct sockaddr addr;
+	struct sockaddr_storage addr;
 	struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
 	struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
 	struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
 	struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
 	int rc;
 	int rc;
 
 
-	memset(&addr, 0, sizeof(struct sockaddr));
+	memset(&addr, 0, sizeof(struct sockaddr_storage));
 
 
 	if (volume_info->UNCip && volume_info->UNC) {
 	if (volume_info->UNCip && volume_info->UNC) {
 		rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
 		rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
@@ -1435,9 +1435,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 			rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
 			rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
 					    &sin_server6->sin6_addr.in6_u);
 					    &sin_server6->sin6_addr.in6_u);
 			if (rc > 0)
 			if (rc > 0)
-				addr.sa_family = AF_INET6;
+				addr.ss_family = AF_INET6;
 		} else {
 		} else {
-			addr.sa_family = AF_INET;
+			addr.ss_family = AF_INET;
 		}
 		}
 
 
 		if (rc <= 0) {
 		if (rc <= 0) {
@@ -1502,7 +1502,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 	tcp_ses->tcpStatus = CifsNew;
 	tcp_ses->tcpStatus = CifsNew;
 	++tcp_ses->srv_count;
 	++tcp_ses->srv_count;
 
 
-	if (addr.sa_family == AF_INET6) {
+	if (addr.ss_family == AF_INET6) {
 		cFYI(1, ("attempting ipv6 connect"));
 		cFYI(1, ("attempting ipv6 connect"));
 		/* BB should we allow ipv6 on port 139? */
 		/* BB should we allow ipv6 on port 139? */
 		/* other OS never observed in Wild doing 139 with v6 */
 		/* other OS never observed in Wild doing 139 with v6 */
@@ -1802,7 +1802,7 @@ ipv4_connect(struct TCP_Server_Info *server)
 	 *  user space buffer
 	 *  user space buffer
 	 */
 	 */
 	socket->sk->sk_rcvtimeo = 7 * HZ;
 	socket->sk->sk_rcvtimeo = 7 * HZ;
-	socket->sk->sk_sndtimeo = 3 * HZ;
+	socket->sk->sk_sndtimeo = 5 * HZ;
 
 
 	/* make the bufsizes depend on wsize/rsize and max requests */
 	/* make the bufsizes depend on wsize/rsize and max requests */
 	if (server->noautotune) {
 	if (server->noautotune) {
@@ -1860,9 +1860,7 @@ ipv4_connect(struct TCP_Server_Info *server)
 			smb_buf = (struct smb_hdr *)ses_init_buf;
 			smb_buf = (struct smb_hdr *)ses_init_buf;
 			/* sizeof RFC1002_SESSION_REQUEST with no scope */
 			/* sizeof RFC1002_SESSION_REQUEST with no scope */
 			smb_buf->smb_buf_length = 0x81000044;
 			smb_buf->smb_buf_length = 0x81000044;
-			rc = smb_send(socket, smb_buf, 0x44,
-				(struct sockaddr *) &server->addr.sockAddr,
-				server->noblocksnd);
+			rc = smb_send(server, smb_buf, 0x44);
 			kfree(ses_init_buf);
 			kfree(ses_init_buf);
 			msleep(1); /* RFC1001 layer in at least one server
 			msleep(1); /* RFC1001 layer in at least one server
 				      requires very short break before negprot
 				      requires very short break before negprot
@@ -1955,7 +1953,7 @@ ipv6_connect(struct TCP_Server_Info *server)
 	 * user space buffer
 	 * user space buffer
 	 */
 	 */
 	socket->sk->sk_rcvtimeo = 7 * HZ;
 	socket->sk->sk_rcvtimeo = 7 * HZ;
-	socket->sk->sk_sndtimeo = 3 * HZ;
+	socket->sk->sk_sndtimeo = 5 * HZ;
 	server->ssocket = socket;
 	server->ssocket = socket;
 
 
 	return rc;
 	return rc;

+ 31 - 25
fs/cifs/dir.c

@@ -129,6 +129,17 @@ cifs_bp_rename_retry:
 	return full_path;
 	return full_path;
 }
 }
 
 
+static void setup_cifs_dentry(struct cifsTconInfo *tcon,
+			      struct dentry *direntry,
+			      struct inode *newinode)
+{
+	if (tcon->nocase)
+		direntry->d_op = &cifs_ci_dentry_ops;
+	else
+		direntry->d_op = &cifs_dentry_ops;
+	d_instantiate(direntry, newinode);
+}
+
 /* Inode operations in similar order to how they appear in Linux file fs.h */
 /* Inode operations in similar order to how they appear in Linux file fs.h */
 
 
 int
 int
@@ -139,14 +150,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 	int xid;
 	int xid;
 	int create_options = CREATE_NOT_DIR;
 	int create_options = CREATE_NOT_DIR;
 	int oplock = 0;
 	int oplock = 0;
+	/* BB below access is too much for the mknod to request */
 	int desiredAccess = GENERIC_READ | GENERIC_WRITE;
 	int desiredAccess = GENERIC_READ | GENERIC_WRITE;
 	__u16 fileHandle;
 	__u16 fileHandle;
 	struct cifs_sb_info *cifs_sb;
 	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
+	struct cifsTconInfo *tcon;
 	char *full_path = NULL;
 	char *full_path = NULL;
 	FILE_ALL_INFO *buf = NULL;
 	FILE_ALL_INFO *buf = NULL;
 	struct inode *newinode = NULL;
 	struct inode *newinode = NULL;
-	struct cifsFileInfo *pCifsFile = NULL;
 	struct cifsInodeInfo *pCifsInode;
 	struct cifsInodeInfo *pCifsInode;
 	int disposition = FILE_OVERWRITE_IF;
 	int disposition = FILE_OVERWRITE_IF;
 	bool write_only = false;
 	bool write_only = false;
@@ -154,7 +165,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 	xid = GetXid();
 	xid = GetXid();
 
 
 	cifs_sb = CIFS_SB(inode->i_sb);
 	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tcon = cifs_sb->tcon;
 
 
 	full_path = build_path_from_dentry(direntry);
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 	if (full_path == NULL) {
@@ -162,6 +173,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
+	mode &= ~current->fs->umask;
+
 	if (nd && (nd->flags & LOOKUP_OPEN)) {
 	if (nd && (nd->flags & LOOKUP_OPEN)) {
 		int oflags = nd->intent.open.flags;
 		int oflags = nd->intent.open.flags;
 
 
@@ -196,17 +209,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	mode &= ~current->fs->umask;
-
 	/*
 	/*
 	 * if we're not using unix extensions, see if we need to set
 	 * if we're not using unix extensions, see if we need to set
 	 * ATTR_READONLY on the create call
 	 * ATTR_READONLY on the create call
 	 */
 	 */
-	if (!pTcon->unix_ext && (mode & S_IWUGO) == 0)
+	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
 		create_options |= CREATE_OPTION_READONLY;
 		create_options |= CREATE_OPTION_READONLY;
 
 
 	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
 	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
-		rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
+		rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
 			 desiredAccess, create_options,
 			 desiredAccess, create_options,
 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -215,7 +226,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 
 
 	if (rc == -EIO) {
 	if (rc == -EIO) {
 		/* old server, retry the open legacy style */
 		/* old server, retry the open legacy style */
-		rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
+		rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
 			desiredAccess, create_options,
 			desiredAccess, create_options,
 			&fileHandle, &oplock, buf, cifs_sb->local_nls,
 			&fileHandle, &oplock, buf, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -225,7 +236,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 	} else {
 	} else {
 		/* If Open reported that we actually created a file
 		/* If Open reported that we actually created a file
 		then we now have to set the mode if possible */
 		then we now have to set the mode if possible */
-		if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
+		if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
 			struct cifs_unix_set_info_args args = {
 			struct cifs_unix_set_info_args args = {
 				.mode	= mode,
 				.mode	= mode,
 				.ctime	= NO_CHANGE_64,
 				.ctime	= NO_CHANGE_64,
@@ -244,20 +255,20 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 				args.uid = NO_CHANGE_64;
 				args.uid = NO_CHANGE_64;
 				args.gid = NO_CHANGE_64;
 				args.gid = NO_CHANGE_64;
 			}
 			}
-			CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args,
+			CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
 				cifs_sb->local_nls,
 				cifs_sb->local_nls,
 				cifs_sb->mnt_cifs_flags &
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		} else {
 		} else {
 			/* BB implement mode setting via Windows security
 			/* BB implement mode setting via Windows security
 			   descriptors e.g. */
 			   descriptors e.g. */
-			/* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/
+			/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
 
 
 			/* Could set r/o dos attribute if mode & 0222 == 0 */
 			/* Could set r/o dos attribute if mode & 0222 == 0 */
 		}
 		}
 
 
 		/* server might mask mode so we have to query for it */
 		/* server might mask mode so we have to query for it */
-		if (pTcon->unix_ext)
+		if (tcon->unix_ext)
 			rc = cifs_get_inode_info_unix(&newinode, full_path,
 			rc = cifs_get_inode_info_unix(&newinode, full_path,
 						 inode->i_sb, xid);
 						 inode->i_sb, xid);
 		else {
 		else {
@@ -283,22 +294,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 		}
 		}
 
 
 		if (rc != 0) {
 		if (rc != 0) {
-			cFYI(1,
-			     ("Create worked but get_inode_info failed rc = %d",
-			      rc));
-		} else {
-			if (pTcon->nocase)
-				direntry->d_op = &cifs_ci_dentry_ops;
-			else
-				direntry->d_op = &cifs_dentry_ops;
-			d_instantiate(direntry, newinode);
-		}
+			cFYI(1, ("Create worked, get_inode_info failed rc = %d",
+				 rc));
+		} else
+			setup_cifs_dentry(tcon, direntry, newinode);
+
 		if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
 		if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
 			(!(nd->flags & LOOKUP_OPEN))) {
 			(!(nd->flags & LOOKUP_OPEN))) {
 			/* mknod case - do not leave file open */
 			/* mknod case - do not leave file open */
-			CIFSSMBClose(xid, pTcon, fileHandle);
+			CIFSSMBClose(xid, tcon, fileHandle);
 		} else if (newinode) {
 		} else if (newinode) {
-			pCifsFile =
+			struct cifsFileInfo *pCifsFile =
 			   kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
 			   kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
 
 
 			if (pCifsFile == NULL)
 			if (pCifsFile == NULL)
@@ -316,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 			/* set the following in open now
 			/* set the following in open now
 				pCifsFile->pfile = file; */
 				pCifsFile->pfile = file; */
 			write_lock(&GlobalSMBSeslock);
 			write_lock(&GlobalSMBSeslock);
-			list_add(&pCifsFile->tlist, &pTcon->openFileList);
+			list_add(&pCifsFile->tlist, &tcon->openFileList);
 			pCifsInode = CIFS_I(newinode);
 			pCifsInode = CIFS_I(newinode);
 			if (pCifsInode) {
 			if (pCifsInode) {
 				/* if readable file instance put first in list*/
 				/* if readable file instance put first in list*/

+ 5 - 0
fs/cifs/inode.c

@@ -1285,6 +1285,11 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
 	cifsInode = CIFS_I(direntry->d_inode);
 	cifsInode = CIFS_I(direntry->d_inode);
 	cifsInode->time = 0;	/* force revalidate to go get info when
 	cifsInode->time = 0;	/* force revalidate to go get info when
 				   needed */
 				   needed */
+
+	cifsInode = CIFS_I(inode);
+	cifsInode->time = 0;	/* force revalidate to get parent dir info
+				   since cached search results now invalid */
+
 	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
 	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
 		current_fs_time(inode->i_sb);
 		current_fs_time(inode->i_sb);
 
 

+ 19 - 19
fs/cifs/md5.c

@@ -10,8 +10,8 @@
  * with every copy.
  * with every copy.
  *
  *
  * To compute the message digest of a chunk of bytes, declare an
  * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
+ * MD5Context structure, pass it to cifs_MD5_init, call cifs_MD5_update as
+ * needed on buffers full of bytes, and then call cifs_MD5_final, which
  * will fill a supplied 16-byte array with the digest.
  * will fill a supplied 16-byte array with the digest.
  */
  */
 
 
@@ -45,7 +45,7 @@ byteReverse(unsigned char *buf, unsigned longs)
  * initialization constants.
  * initialization constants.
  */
  */
 void
 void
-MD5Init(struct MD5Context *ctx)
+cifs_MD5_init(struct MD5Context *ctx)
 {
 {
 	ctx->buf[0] = 0x67452301;
 	ctx->buf[0] = 0x67452301;
 	ctx->buf[1] = 0xefcdab89;
 	ctx->buf[1] = 0xefcdab89;
@@ -61,7 +61,7 @@ MD5Init(struct MD5Context *ctx)
  * of bytes.
  * of bytes.
  */
  */
 void
 void
-MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+cifs_MD5_update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
 {
 {
 	register __u32 t;
 	register __u32 t;
 
 
@@ -110,7 +110,7 @@ MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
  * 1 0* (64-bit count of bits processed, MSB-first)
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
  */
 void
 void
-MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+cifs_MD5_final(unsigned char digest[16], struct MD5Context *ctx)
 {
 {
 	unsigned int count;
 	unsigned int count;
 	unsigned char *p;
 	unsigned char *p;
@@ -165,7 +165,7 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx)
 
 
 /*
 /*
  * The core of the MD5 algorithm, this alters an existing MD5 hash to
  * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * reflect the addition of 16 longwords of new data.  cifs_MD5_update blocks
  * the data and converts bytes into longwords for this routine.
  * the data and converts bytes into longwords for this routine.
  */
  */
 static void
 static void
@@ -267,9 +267,9 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
 		unsigned char tk[16];
 		unsigned char tk[16];
 		struct MD5Context tctx;
 		struct MD5Context tctx;
 
 
-		MD5Init(&tctx);
-		MD5Update(&tctx, key, key_len);
-		MD5Final(tk, &tctx);
+		cifs_MD5_init(&tctx);
+		cifs_MD5_update(&tctx, key, key_len);
+		cifs_MD5_final(tk, &tctx);
 
 
 		key = tk;
 		key = tk;
 		key_len = 16;
 		key_len = 16;
@@ -287,8 +287,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
 		ctx->k_opad[i] ^= 0x5c;
 		ctx->k_opad[i] ^= 0x5c;
 	}
 	}
 
 
-	MD5Init(&ctx->ctx);
-	MD5Update(&ctx->ctx, ctx->k_ipad, 64);
+	cifs_MD5_init(&ctx->ctx);
+	cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64);
 }
 }
 #endif
 #endif
 
 
@@ -317,8 +317,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
 		ctx->k_opad[i] ^= 0x5c;
 		ctx->k_opad[i] ^= 0x5c;
 	}
 	}
 
 
-	MD5Init(&ctx->ctx);
-	MD5Update(&ctx->ctx, ctx->k_ipad, 64);
+	cifs_MD5_init(&ctx->ctx);
+	cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64);
 }
 }
 
 
 /***********************************************************************
 /***********************************************************************
@@ -328,7 +328,7 @@ void
 hmac_md5_update(const unsigned char *text, int text_len,
 hmac_md5_update(const unsigned char *text, int text_len,
 		struct HMACMD5Context *ctx)
 		struct HMACMD5Context *ctx)
 {
 {
-	MD5Update(&ctx->ctx, text, text_len);	/* then text of datagram */
+	cifs_MD5_update(&ctx->ctx, text, text_len);	/* then text of datagram */
 }
 }
 
 
 /***********************************************************************
 /***********************************************************************
@@ -339,12 +339,12 @@ hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
 {
 {
 	struct MD5Context ctx_o;
 	struct MD5Context ctx_o;
 
 
-	MD5Final(digest, &ctx->ctx);
+	cifs_MD5_final(digest, &ctx->ctx);
 
 
-	MD5Init(&ctx_o);
-	MD5Update(&ctx_o, ctx->k_opad, 64);
-	MD5Update(&ctx_o, digest, 16);
-	MD5Final(digest, &ctx_o);
+	cifs_MD5_init(&ctx_o);
+	cifs_MD5_update(&ctx_o, ctx->k_opad, 64);
+	cifs_MD5_update(&ctx_o, digest, 16);
+	cifs_MD5_final(digest, &ctx_o);
 }
 }
 
 
 /***********************************************************
 /***********************************************************

+ 3 - 3
fs/cifs/md5.h

@@ -20,10 +20,10 @@ struct HMACMD5Context {
 };
 };
 #endif				/* _HMAC_MD5_H */
 #endif				/* _HMAC_MD5_H */
 
 
-void MD5Init(struct MD5Context *context);
-void MD5Update(struct MD5Context *context, unsigned char const *buf,
+void cifs_MD5_init(struct MD5Context *context);
+void cifs_MD5_update(struct MD5Context *context, unsigned char const *buf,
 			unsigned len);
 			unsigned len);
-void MD5Final(unsigned char digest[16], struct MD5Context *context);
+void cifs_MD5_final(unsigned char digest[16], struct MD5Context *context);
 
 
 /* The following definitions come from lib/hmacmd5.c  */
 /* The following definitions come from lib/hmacmd5.c  */
 
 

+ 38 - 89
fs/cifs/transport.c

@@ -154,81 +154,8 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
 	spin_unlock(&GlobalMid_Lock);
 	spin_unlock(&GlobalMid_Lock);
 }
 }
 
 
-int
-smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
-	 unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd)
-{
-	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;
-	if (noblocksnd)
-		smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
-	else
-		smb_msg.msg_flags = MSG_NOSIGNAL;
-
-	/* 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++;
-		/* smaller timeout here than send2 since smaller size */
-		/* Although it may not be required, this also is smaller
-		   oplock break time */
-			if (i > 12) {
-				cERROR(1,
-				   ("sends on sock %p stuck for 7 seconds",
-				    ssocket));
-				rc = -EAGAIN;
-				break;
-			}
-			msleep(1 << i);
-			continue;
-		}
-		if (rc < 0)
-			break;
-		else
-			i = 0; /* reset i after each successful send */
-		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;
-	}
-
-	/* Don't want to modify the buffer as a
-	   side effect of this call. */
-	smb_buffer->smb_buf_length = smb_buf_length;
-
-	return rc;
-}
-
 static int
 static int
-smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
-	  struct sockaddr *sin, bool noblocksnd)
+smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	int i = 0;
 	int i = 0;
@@ -243,11 +170,11 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
 	if (ssocket == NULL)
 	if (ssocket == NULL)
 		return -ENOTSOCK; /* BB eventually add reconnect code here */
 		return -ENOTSOCK; /* BB eventually add reconnect code here */
 
 
-	smb_msg.msg_name = sin;
+	smb_msg.msg_name = (struct sockaddr *) &server->addr.sockAddr;
 	smb_msg.msg_namelen = sizeof(struct sockaddr);
 	smb_msg.msg_namelen = sizeof(struct sockaddr);
 	smb_msg.msg_control = NULL;
 	smb_msg.msg_control = NULL;
 	smb_msg.msg_controllen = 0;
 	smb_msg.msg_controllen = 0;
-	if (noblocksnd)
+	if (server->noblocksnd)
 		smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
 		smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
 	else
 	else
 		smb_msg.msg_flags = MSG_NOSIGNAL;
 		smb_msg.msg_flags = MSG_NOSIGNAL;
@@ -272,7 +199,25 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
 				    n_vec - first_vec, total_len);
 				    n_vec - first_vec, total_len);
 		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 			i++;
 			i++;
-			if (i >= 14) {
+			/* if blocking send we try 3 times, since each can block
+			   for 5 seconds. For nonblocking  we have to try more
+			   but wait increasing amounts of time allowing time for
+			   socket to clear.  The overall time we wait in either
+			   case to send on the socket is about 15 seconds.
+			   Similarly we wait for 15 seconds for
+			   a response from the server in SendReceive[2]
+			   for the server to send a response back for
+			   most types of requests (except SMB Write
+			   past end of file which can be slow, and
+			   blocking lock operations). NFS waits slightly longer
+			   than CIFS, but this can make it take longer for
+			   nonresponsive servers to be detected and 15 seconds
+			   is more than enough time for modern networks to
+			   send a packet.  In most cases if we fail to send
+			   after the retries we will kill the socket and
+			   reconnect which may clear the network problem.
+			*/
+			if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
 				cERROR(1,
 				cERROR(1,
 				   ("sends on sock %p stuck for 15 seconds",
 				   ("sends on sock %p stuck for 15 seconds",
 				    ssocket));
 				    ssocket));
@@ -339,6 +284,18 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
 	return rc;
 	return rc;
 }
 }
 
 
+int
+smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
+	 unsigned int smb_buf_length)
+{
+	struct kvec iov;
+
+	iov.iov_base = smb_buffer;
+	iov.iov_len = smb_buf_length + 4;
+
+	return smb_sendv(server, &iov, 1);
+}
+
 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
 {
 {
 	if (long_op == CIFS_ASYNC_OP) {
 	if (long_op == CIFS_ASYNC_OP) {
@@ -540,9 +497,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 #ifdef CONFIG_CIFS_STATS2
 #ifdef CONFIG_CIFS_STATS2
 	atomic_inc(&ses->server->inSend);
 	atomic_inc(&ses->server->inSend);
 #endif
 #endif
-	rc = smb_send2(ses->server, iov, n_vec,
-		      (struct sockaddr *) &(ses->server->addr.sockAddr),
-		       ses->server->noblocksnd);
+	rc = smb_sendv(ses->server, iov, n_vec);
 #ifdef CONFIG_CIFS_STATS2
 #ifdef CONFIG_CIFS_STATS2
 	atomic_dec(&ses->server->inSend);
 	atomic_dec(&ses->server->inSend);
 	midQ->when_sent = jiffies;
 	midQ->when_sent = jiffies;
@@ -736,9 +691,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 #ifdef CONFIG_CIFS_STATS2
 #ifdef CONFIG_CIFS_STATS2
 	atomic_inc(&ses->server->inSend);
 	atomic_inc(&ses->server->inSend);
 #endif
 #endif
-	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
-		      (struct sockaddr *) &(ses->server->addr.sockAddr),
-		      ses->server->noblocksnd);
+	rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
 #ifdef CONFIG_CIFS_STATS2
 #ifdef CONFIG_CIFS_STATS2
 	atomic_dec(&ses->server->inSend);
 	atomic_dec(&ses->server->inSend);
 	midQ->when_sent = jiffies;
 	midQ->when_sent = jiffies;
@@ -879,9 +832,7 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
 		mutex_unlock(&ses->server->srv_mutex);
 		mutex_unlock(&ses->server->srv_mutex);
 		return rc;
 		return rc;
 	}
 	}
-	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
-	      (struct sockaddr *) &(ses->server->addr.sockAddr),
-	      ses->server->noblocksnd);
+	rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
 	mutex_unlock(&ses->server->srv_mutex);
 	mutex_unlock(&ses->server->srv_mutex);
 	return rc;
 	return rc;
 }
 }
@@ -973,9 +924,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
 #ifdef CONFIG_CIFS_STATS2
 #ifdef CONFIG_CIFS_STATS2
 	atomic_inc(&ses->server->inSend);
 	atomic_inc(&ses->server->inSend);
 #endif
 #endif
-	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
-		      (struct sockaddr *) &(ses->server->addr.sockAddr),
-		      ses->server->noblocksnd);
+	rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
 #ifdef CONFIG_CIFS_STATS2
 #ifdef CONFIG_CIFS_STATS2
 	atomic_dec(&ses->server->inSend);
 	atomic_dec(&ses->server->inSend);
 	midQ->when_sent = jiffies;
 	midQ->when_sent = jiffies;