[rds-commits] zab commits r77 - trunk/linux/net/rds

svn-commits@oss.oracle.com svn-commits at oss.oracle.com
Thu May 25 18:38:47 CDT 2006


Author: zab
Date: 2006-05-25 18:38:46 -0500 (Thu, 25 May 2006)
New Revision: 77

Modified:
   trunk/linux/net/rds/message.c
   trunk/linux/net/rds/rds.h
Log:
Fix three bad bugs when copying to and from pages and user iovecs.

1) copy into the page at the offset in the current page.

2) 'ret' was being stomped on as a temporary return from copy_to_user, add
   an explitic 'copied'.

3) size doesn't need to be dropped now that we're comparing it with copied


Modified: trunk/linux/net/rds/message.c
===================================================================
--- trunk/linux/net/rds/message.c	2006-05-25 22:44:12 UTC (rev 76)
+++ trunk/linux/net/rds/message.c	2006-05-25 23:38:46 UTC (rev 77)
@@ -203,13 +203,16 @@
 		}
 
 		to_copy = min(iov->iov_len - iov_off, PAGE_SIZE - vec->v_len);
+		to_copy = min_t(size_t, to_copy, total_len);
 
-		pr_debug("iov %p iov_off %lu vec len %u total_len %zu\n",
-			 iov, iov_off, vec->v_len, total_len);
+		pr_debug("copying %lu bytes from user %p (base %p len %zu "
+			 "off %lu) to vec %p page %p off %u\n", to_copy,
+			 iov->iov_base + iov_off, iov->iov_base, iov->iov_len,
+			 iov_off, vec, page, vec->v_len);
 
 		/* XXX could look more like filemap_copy_from_user() */
-		ret = copy_from_user(kmap(page), iov->iov_base + iov_off,
-				     to_copy);
+		ret = copy_from_user(kmap(page) + vec->v_len,
+				     iov->iov_base + iov_off, to_copy);
 		kunmap(page);
 		if (ret) {
 			ret = -EFAULT;
@@ -245,43 +248,47 @@
 	unsigned long to_copy;
 	unsigned long iov_off = 0;
 	unsigned long vec_off = 0;
-	int ret = 0;
+	int ret, copied = 0;
 
 	rm = container_of(inc, struct rds_message, m_inc);
 
-	while (ret < size && ret < rm->m_len) {
+	while (copied < size && copied < rm->m_len) {
 		while (iov_off == iov->iov_len) {
 			iov_off = 0;
 			iov++;
 		}
 
 		to_copy = min(iov->iov_len - iov_off, vec->v_len - vec_off);
-		to_copy = min_t(size_t, to_copy, size - ret);
-		to_copy = min_t(unsigned long, to_copy, rm->m_len - ret);
+		to_copy = min_t(size_t, to_copy, size - copied);
+		to_copy = min_t(unsigned long, to_copy, rm->m_len - copied);
 
+		pr_debug("copying %lu bytes to user %p (base %p len %zu "
+			 "off %lu) from vec %p page %p voff %u off %lu\n",
+			 to_copy, iov->iov_base + iov_off, iov->iov_base,
+			 iov->iov_len, iov_off, vec, vec->v_page, vec->v_off,
+			 vec_off);
+
 		/* XXX could look more like filemap_copy_from_user() */
 		ret = copy_to_user(iov->iov_base + iov_off,
 				   kmap(vec->v_page) + vec->v_off + vec_off, 
 				   to_copy);
 		kunmap(vec->v_page);
 		if (ret) {
-			ret = -EFAULT;
+			copied = -EFAULT;
 			break;
 		}
 
 		iov_off += to_copy;
 		vec_off += to_copy;
-		ret += to_copy;
-		size -= to_copy;
-		if (size == 0)
-			break;
+		copied += to_copy;
+
 		if (vec_off == vec->v_len) {
 			vec_off = 0;
 			vec++;
 		}
 	}
 
-	return ret;
+	return copied;
 }
 
 /*

Modified: trunk/linux/net/rds/rds.h
===================================================================
--- trunk/linux/net/rds/rds.h	2006-05-25 22:44:12 UTC (rev 76)
+++ trunk/linux/net/rds/rds.h	2006-05-25 23:38:46 UTC (rev 77)
@@ -26,7 +26,6 @@
 	unsigned int		v_len;
 };
 
-
 struct rds_connection {
 	struct hlist_node	c_hash_node;
 	__be32			c_laddr;




More information about the Rds-commits mailing list