ceph: fix short synchronous reads

Zeroing of holes was not done correctly: page_off was miscalculated and
zeroing the tail didn't not adjust the 'read' value to include the zeroed
portion.

Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: Sage Weil <sage@newdream.net>
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 2d88c80..43bd2f2 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -395,23 +395,22 @@
 {
 	int i = off >> PAGE_CACHE_SHIFT;
 
+	off &= ~PAGE_CACHE_MASK;
+
 	dout("zero_page_vector_page %u~%u\n", off, len);
-	BUG_ON(len < PAGE_CACHE_SIZE);
 
 	/* leading partial page? */
-	if (off & ~PAGE_CACHE_MASK) {
+	if (off) {
+		int end = min((int)PAGE_CACHE_SIZE, off + len);
 		dout("zeroing %d %p head from %d\n", i, pages[i],
-		     (int)(off & ~PAGE_CACHE_MASK));
-		zero_user_segment(pages[i], off & ~PAGE_CACHE_MASK,
-				  PAGE_CACHE_SIZE);
-		off += PAGE_CACHE_SIZE;
-		off &= PAGE_CACHE_MASK;
+		     (int)off);
+		zero_user_segment(pages[i], off, end);
+		len -= (end - off);
 		i++;
 	}
 	while (len >= PAGE_CACHE_SIZE) {
 		dout("zeroing %d %p\n", i, pages[i]);
 		zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
-		off += PAGE_CACHE_SIZE;
 		len -= PAGE_CACHE_SIZE;
 		i++;
 	}
@@ -437,7 +436,7 @@
 	struct ceph_client *client = ceph_inode_to_client(inode);
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	u64 pos, this_len;
-	int page_off = off & ~PAGE_CACHE_SIZE; /* first byte's offset in page */
+	int page_off = off & ~PAGE_CACHE_MASK; /* first byte's offset in page */
 	int left, pages_left;
 	int read;
 	struct page **page_pos;
@@ -493,6 +492,7 @@
 			dout("zero tail\n");
 			zero_page_vector_range(page_off + read, len - read,
 					       pages);
+			read = len;
 			goto out;
 		}