ceph: fix short synchronous reads
authorYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 4 Feb 2010 21:41:41 +0000 (13:41 -0800)
committerSage Weil <sage@newdream.net>
Thu, 11 Feb 2010 19:48:49 +0000 (11:48 -0800)
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>
fs/ceph/file.c

index 2d88c805a56c430412bfd8b8b44f01284926fdf2..43bd2f2e51a572279bbd2d82bffd8ea5ae735da5 100644 (file)
@@ -395,23 +395,22 @@ static void zero_page_vector_range(int off, int len, struct page **pages)
 {
        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 @@ static int striped_read(struct inode *inode,
        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 @@ more:
                        dout("zero tail\n");
                        zero_page_vector_range(page_off + read, len - read,
                                               pages);
+                       read = len;
                        goto out;
                }