patch-2.2.18 linux/fs/smbfs/sock.c

Next file: linux/fs/super.c
Previous file: linux/fs/smbfs/proc.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/fs/smbfs/sock.c linux/fs/smbfs/sock.c
@@ -108,23 +108,24 @@
 	unsigned char peek_buf[4];
 	int result;
 	mm_segment_t fs;
+	int count = 100;   /* this is a lot, we should have some data waiting */
+	int found = 0;
 
 	fs = get_fs();
 	set_fs(get_ds());
 
 	lock_kernel();
-	while (1)
-	{
+	while (count-- > 0) {
+		peek_buf[0] = 0;
 		result = -EIO;
-		if (job->sk->dead)
-		{
+		if (job->sk->dead) {
 			PARANOIA("sock dead!\n");
 			break;
 		}
 
 		result = _recvfrom(socket, (void *) peek_buf, 1,
 				   MSG_PEEK | MSG_DONTWAIT);
-		if (result == -EAGAIN)
+		if (result < 0)
 			break;
 		if (peek_buf[0] != 0x85)
 			break;
@@ -135,13 +136,15 @@
 
 		DEBUG1("got SESSION KEEPALIVE\n");
 
-		if (result == -EAGAIN)
+		if (result < 0)
 			break;
+		found = 1;
 	}
 	unlock_kernel();
 	set_fs(fs);
 
-	if (result != -EAGAIN)
+	DEBUG1("found=%d, count=%d, result=%d\n", found, count, result);
+	if (found)
 		found_data(job->sk);
 	kfree(ptr);
 }
@@ -470,14 +473,12 @@
 	unsigned int total_p = 0, total_d = 0, buf_len = 0;
 	int result;
 
-	while (1)
-	{
+	while (1) {
 		result = smb_receive(server);
 		if (result < 0)
 			goto out;
 		inbuf = server->packet;
-		if (server->rcls != 0)
-		{
+		if (server->rcls != 0) {
 			*parm = *data = inbuf;
 			*ldata = *lparm = 0;
 			goto out;
@@ -501,13 +502,11 @@
 		parm_len += parm_count;
 		data_len += data_count;
 
-		if (!rcv_buf)
-		{
+		if (!rcv_buf) {
 			/*
 			 * Check for fast track processing ... just this packet.
 			 */
-			if (parm_count == parm_tot && data_count == data_tot)
-			{
+			if (parm_count == parm_tot && data_count == data_tot) {
 				VERBOSE("fast track, parm=%u %u %u, data=%u %u %u\n",
 					parm_disp, parm_offset, parm_count, 
 					data_disp, data_offset, data_count);
@@ -517,12 +516,10 @@
 				goto success;
 			}
 
-			if (parm_tot > TRANS2_MAX_TRANSFER ||
-	  		    data_tot > TRANS2_MAX_TRANSFER)
-				goto out_too_long;
-
 			/*
-			 * Save the total parameter and data length.
+			 * Allocate a new buffer for receiving multiple packets
+			 * into. If we stick to the negotiated max_xmit this
+			 * shouldn't have to happen.
 			 */
 			total_d = data_tot;
 			total_p = parm_tot;
@@ -531,14 +528,15 @@
 			if (server->packet_size > buf_len)
 				buf_len = server->packet_size;
 			buf_len = smb_round_length(buf_len);
+			if (buf_len > SMB_MAX_PACKET_SIZE)
+				goto out_no_mem;
 
 			rcv_buf = smb_vmalloc(buf_len);
 			if (!rcv_buf)
 				goto out_no_mem;
 			*parm = rcv_buf;
 			*data = rcv_buf + total_p;
-		}
-		else if (data_tot > total_d || parm_tot > total_p)
+		} else if (data_tot > total_d || parm_tot > total_p)
 			goto out_data_grew;
 
 		if (parm_disp + parm_count > total_p)
@@ -565,8 +563,7 @@
 	 * old one, in which case we just copy the data.
 	 */
 	inbuf = server->packet;
-	if (buf_len >= server->packet_size)
-	{
+	if (buf_len >= server->packet_size) {
 		server->packet_size = buf_len;
 		server->packet = rcv_buf;
 		rcv_buf = inbuf;
@@ -710,6 +707,7 @@
 	struct socket *sock = server_sock(server);
 	struct scm_cookie scm;
 	int err;
+	int mparam, mdata;
 
 	/* I know the following is very ugly, but I want to build the
 	   smb packet as efficiently as possible. */
@@ -730,19 +728,30 @@
 	struct iovec iov[4];
 	struct msghdr msg;
 
-	/* N.B. This test isn't valid! packet_size may be < max_xmit */
+	/* FIXME! this test needs to include SMB overhead too, I think ... */
 	if ((bcc + oparam) > server->opt.max_xmit)
-	{
 		return -ENOMEM;
-	}
 	p = smb_setup_header(server, SMBtrans2, smb_parameters, bcc);
 
+	/*
+	 * max parameters + max data + max setup == max_xmit to make NT4 happy
+	 * and not abort the transfer or split into multiple packets.
+	 *
+	 * -100 is to make room for headers, which OS/2 seems to include in the
+	 * size calculation NT4 does not?
+	 */
+	mparam = SMB_TRANS2_MAX_PARAM;
+	mdata = server->opt.max_xmit - mparam - 100;
+	if (mdata < 1024) {
+		mdata = 1024;
+		mparam = 20;
+	}
+
 	WSET(server->packet, smb_tpscnt, lparam);
 	WSET(server->packet, smb_tdscnt, ldata);
-	/* N.B. these values should reflect out current packet size */
-	WSET(server->packet, smb_mprcnt, TRANS2_MAX_TRANSFER);
-	WSET(server->packet, smb_mdrcnt, TRANS2_MAX_TRANSFER);
-	WSET(server->packet, smb_msrcnt, 0);
+	WSET(server->packet, smb_mprcnt, mparam);
+	WSET(server->packet, smb_mdrcnt, mdata);
+	WSET(server->packet, smb_msrcnt, 0);	/* max setup always 0 ? */
 	WSET(server->packet, smb_flags, 0);
 	DSET(server->packet, smb_timeout, 0);
 	WSET(server->packet, smb_pscnt, lparam);
@@ -774,8 +783,7 @@
 	iov[3].iov_len = ldata;
 
 	err = scm_send(sock, &msg, &scm);
-        if (err >= 0)
-	{
+        if (err >= 0) {
 		err = sock->ops->sendmsg(sock, &msg, packet_length, &scm);
 		scm_destroy(&scm);
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)