]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: force early writeback if page belongs to a (different) snap
authorSage Weil <sage@newdream.net>
Mon, 11 Aug 2008 18:13:13 +0000 (11:13 -0700)
committerSage Weil <sage@newdream.net>
Mon, 11 Aug 2008 18:13:13 +0000 (11:13 -0700)
src/kernel/addr.c

index fcb9408c21976599c653887a20cd894dedd5c52e..1994f6b86560c2e07d871257fa4e86ad540b5347 100644 (file)
@@ -45,9 +45,11 @@ static int ceph_set_page_dirty(struct page *page)
                ci = ceph_inode(mapping->host);
                atomic_inc(&ci->i_wrbuffer_ref);
                /*
-                * set PagePrivate so that we get invalidatepage callback
-                * on truncate for proper dirty page accounting for mmap
+                * reference snap context in page->private.  also set
+                * PagePrivate so that we get invalidatepage callback
+                * on truncate for dirty page accounting for mmap.
                 */
+               ceph_put_snap_context((void *)page->private);
                page->private = (unsigned long)ceph_get_snap_context(ci->i_snaprealm->cached_context);
                SetPagePrivate(page);
                dout(20, "%p set_page_dirty %p %d -> %d (?)\n", 
@@ -182,13 +184,13 @@ static int ceph_readpages(struct file *file, struct address_space *mapping,
        return 0;
 }
 
-
 /*
  * ceph_writepage:
  *  clear dirty page, and set the writeback flag in the radix tree.
  *  to actually write data to the remote OSDs.
+ * leave pages locked.
  */
-static int ceph_writepage(struct page *page, struct writeback_control *wbc)
+static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
 {
        struct inode *inode;
        struct ceph_inode_info *ci;
@@ -227,15 +229,22 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc)
                SetPageUptodate(page);
                err = 0;  /* vfs expects us to return 0 */
        } else {
-               wbc->pages_skipped++;
+               if (wbc)
+                       wbc->pages_skipped++;
                ceph_set_page_dirty(page);
        }
        end_page_writeback(page);
-       unlock_page(page);
        page_cache_release(page);
        return err;
 }
 
+static int ceph_writepage(struct page *page, struct writeback_control *wbc)
+{
+       int err = writepage_nounlock(page, wbc);
+       unlock_page(page);
+       return err;
+}
+
 
 /*
  * lame release_pages helper.  release_pages() isn't exported to
@@ -545,8 +554,15 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
        if (!ci->i_snaprealm->cached_context) {
                r = ceph_snaprealm_build_context(ci->i_snaprealm);
                if (r < 0)
-                       return r;
-       }               
+                       goto fail;
+       }
+       if (page->private &&
+           (void *)page->private != ci->i_snaprealm->cached_context) {
+               /* force early writeback of snapped page */
+               r = writepage_nounlock(page, 0);
+               if (r < 0)
+                       goto fail;
+       }
 
        if (PageUptodate(page))
                return 0;
@@ -569,7 +585,7 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
        r = ceph_osdc_readpage(osdc, ceph_vino(inode), &ci->i_layout,
                               page_off, PAGE_SIZE, page);
        if (r < 0)
-               return r;
+               goto fail;
        if (r < pos_in_page) {
                void *kaddr = kmap_atomic(page, KM_USER1);
                dout(20, "write_begin zeroing pre %d~%d\n", r, pos_in_page-r);
@@ -587,6 +603,10 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
                kunmap_atomic(kaddr, KM_USER1);
        }
        return 0;
+
+fail:
+       unlock_page(page);
+       return r;
 }
 
 /*