* only snap context we are allowed to write back.
  */
 static struct ceph_snap_context *get_oldest_context(struct inode *inode,
-                                                   u64 *snap_size)
+                                                   loff_t *snap_size)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_snap_context *snapc = NULL;
        struct ceph_osd_client *osdc;
        struct ceph_snap_context *snapc, *oldest;
        loff_t page_off = page_offset(page);
+       loff_t snap_size = -1;
        long writeback_stat;
-       u64 truncate_size, snap_size = 0;
+       u64 truncate_size;
        u32 truncate_seq;
        int err = 0, len = PAGE_CACHE_SIZE;
 
        spin_lock(&ci->i_ceph_lock);
        truncate_seq = ci->i_truncate_seq;
        truncate_size = ci->i_truncate_size;
-       if (!snap_size)
+       if (snap_size == -1)
                snap_size = i_size_read(inode);
        spin_unlock(&ci->i_ceph_lock);
 
        unsigned wsize = 1 << inode->i_blkbits;
        struct ceph_osd_request *req = NULL;
        int do_sync = 0;
-       u64 truncate_size, snap_size;
+       loff_t snap_size, i_size;
+       u64 truncate_size;
        u32 truncate_seq;
 
        /*
 retry:
        /* find oldest snap context with dirty data */
        ceph_put_snap_context(snapc);
-       snap_size = 0;
+       snap_size = -1;
        snapc = get_oldest_context(inode, &snap_size);
        if (!snapc) {
                /* hmm, why does writepages get called when there
                dout(" no snap context with dirty data?\n");
                goto out;
        }
-       if (snap_size == 0)
-               snap_size = i_size_read(inode);
        dout(" oldest snapc is %p seq %lld (%d snaps)\n",
             snapc, snapc->seq, snapc->num_snaps);
 
        spin_lock(&ci->i_ceph_lock);
        truncate_seq = ci->i_truncate_seq;
        truncate_size = ci->i_truncate_size;
-       if (!snap_size)
-               snap_size = i_size_read(inode);
+       i_size = i_size_read(inode);
        spin_unlock(&ci->i_ceph_lock);
 
        if (last_snapc && snapc != last_snapc) {
                                dout("waiting on writeback %p\n", page);
                                wait_on_page_writeback(page);
                        }
-                       if (page_offset(page) >= snap_size) {
-                               dout("%p page eof %llu\n", page, snap_size);
+                       if (page_offset(page) >=
+                           (snap_size == -1 ? i_size : snap_size)) {
+                               dout("%p page eof %llu\n", page,
+                                    (snap_size == -1 ? i_size : snap_size));
                                done = 1;
                                unlock_page(page);
                                break;
                }
 
                /* Format the osd request message and submit the write */
-
                offset = page_offset(pages[0]);
-               len = min(snap_size - offset,
-                         (u64)locked_pages << PAGE_CACHE_SHIFT);
+               len = (u64)locked_pages << PAGE_CACHE_SHIFT;
+               if (snap_size == -1) {
+                       len = min(len, (u64)i_size_read(inode) - offset);
+                        /* writepages_finish() clears writeback pages
+                         * according to the data length, so make sure
+                         * data length covers all locked pages */
+                       len = max(len, 1 +
+                               ((u64)(locked_pages - 1) << PAGE_CACHE_SHIFT));
+               } else {
+                       len = min(len, snap_size - offset);
+               }
                dout("writepages got %d pages at %llu~%llu\n",
                     locked_pages, offset, len);