]> git.neil.brown.name Git - LaFS.git/commitdiff
Use write_begin/write_end in place of prepare/commit
authorNeilBrown <neilb@suse.de>
Thu, 15 Jul 2010 18:44:45 +0000 (20:44 +0200)
committerNeilBrown <neilb@suse.de>
Sun, 25 Jul 2010 05:34:26 +0000 (15:34 +1000)
As this is the 'new way' and need for upgrading the base kernel.

Signed-off-by: NeilBrown <neilb@suse.de>
file.c

diff --git a/file.c b/file.c
index 4c4b36d495dc83c996e1ef6431cb64e47ee21692..d88bcfe62f268a375a24f2285820a0e29ccd5460 100644 (file)
--- a/file.c
+++ b/file.c
@@ -11,6 +11,7 @@
 #include       "lafs.h"
 #include       <linux/bit_spinlock.h>
 #include       <linux/writeback.h>
+#include       <linux/version.h>
 
 struct readpage_data {
        struct bio *bio;
@@ -115,8 +116,9 @@ lafs_readpages(struct file *file, struct address_space *mapping,
 
 
 static int
-lafs_prepare_write(struct file *file, struct page *page,
-                  unsigned start, unsigned end)
+lafs_write_begin(struct file *file, struct address_space *mapping,
+                loff_t pos, unsigned len, unsigned flags,
+                struct page **pagep, void **fsdata)
 {
        /* The range covers one or more blocks in this page
         * and may partially cover the first or last.
@@ -125,21 +127,37 @@ lafs_prepare_write(struct file *file, struct page *page,
         * Then we 'reserve' those datablocks to ensure that
         * a write will succeed.
         */
-       struct inode *ino = file->f_dentry->d_inode;
+       struct inode *ino = mapping->host;
        struct fs *fs = fs_from_inode(ino);
        int bits = ino->i_blkbits;
        int first, last, loading = -1;
        struct datablock *fb;
        int err = 0;
        int i;
+       pgoff_t index;
+       unsigned from, to;
+       struct page *page;
 
-       first = start >> bits;
-       last = (end-1) >> bits;
+       index = pos >> PAGE_CACHE_SHIFT;
+       from = pos & (PAGE_CACHE_SIZE - 1);
+       to = from + len;
+
+       first = from >> bits;
+       last = (to-1) >> bits;
 
        wait_event(fs->trunc_wait,
                   !test_bit(I_Trunc, &LAFSI(ino)->iflags) ||
                   LAFSI(ino)->trunc_next > last);
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+       page = __grab_cache_page(mapping, index);
+#else
+       page = grab_cache_page_write_begin(mapping, index, flags);
+#endif
+       if (!page)
+               return -ENOMEM;
+       *pagep = page;
+
        fb = lafs_get_block(ino, first, page, GFP_KERNEL, MKREF(write));
        dprintk("PREPARE %p\n", fb);
        if (!fb)
@@ -150,7 +168,7 @@ lafs_prepare_write(struct file *file, struct page *page,
        for (i = first + 1 ; i <= last ; i++)
                lafs_get_block(ino, i, page, GFP_KERNEL, MKREF(write));
 
-       if (start != (first << bits)) {
+       if (from != (first << bits)) {
                err = lafs_find_block(fb, NOADOPT);
                if (!err)
                        err = lafs_load_block(&fb->b, NULL);
@@ -159,7 +177,7 @@ lafs_prepare_write(struct file *file, struct page *page,
                loading = first;
        }
        if (last != loading &&
-           end != ((last+1) << bits)) {
+           to != ((last+1) << bits)) {
                struct datablock *lb = fb + last - first;
 
                err = lafs_find_block(lb, ADOPT);
@@ -191,6 +209,7 @@ retry:
        }
        if (err < 0)
                goto fail;
+       *fsdata = fb;
        return 0;
 
 fail:
@@ -201,22 +220,33 @@ fail:
 }
 
 static int
-lafs_commit_write(struct file *file, struct page *page,
-                 unsigned start, unsigned end)
+lafs_write_end(struct file *file,
+              struct address_space *mapping,
+              loff_t pos, unsigned len, unsigned copied,
+              struct page *page, void *fsdata)
 {
-       struct inode *ino = file->f_dentry->d_inode;
+       struct inode *ino = mapping->host;
        struct fs *fs = fs_from_inode(ino);
        int bits = ino->i_blkbits;
-       int first, last;
+       unsigned first, last;
        struct datablock *fb;
-       int i;
-       loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + end;
+       unsigned i;
+       pgoff_t index;
+       unsigned from, to;
+
+       index = pos >> PAGE_CACHE_SHIFT;
+       from = pos & (PAGE_CACHE_SIZE - 1);
+       to = from + len;
 
-       first = start >> bits;
-       last = (end-1) >> bits;
+       first = from >> bits;
+       last = (to-1) >> bits;
 
-       fb = lafs_get_block(ino, first, page, GFP_KERNEL, MKREF(commit));
-       BUG_ON(!fb);
+       fb = fsdata;
+
+       if (unlikely(copied < len)) {
+               if (!PageUptodate(page))
+                       copied = 0;
+       }
 
        /*
         * No need to use i_size_read() here, the i_size
@@ -236,13 +266,16 @@ lafs_commit_write(struct file *file, struct page *page,
        }
        __set_page_dirty_nobuffers(page);
        for (i = first ; i <= last ; i++) {
-               set_bit(B_Valid, &(fb+i-first)->b.flags);
-               lafs_dirty_dblock(fb+i-first);
+               if (copied > 0) {
+                       set_bit(B_Valid, &(fb+i-first)->b.flags);
+                       lafs_dirty_dblock(fb+i-first);
+               }
                putdref(fb+i-first, MKREF(write));
        }
-       putdref(fb, MKREF(commit));
        lafs_checkpoint_unlock(fs);
-       return 0;
+       unlock_page(page);
+       page_cache_release(page);
+       return copied;
 }
 
 static int
@@ -401,8 +434,8 @@ struct address_space_operations lafs_file_aops = {
        .readpage       = lafs_readpage,
        .readpages      = lafs_readpages,
        .writepage      = lafs_writepage,
-       .prepare_write  = lafs_prepare_write,
-       .commit_write   = lafs_commit_write,
+       .write_begin    = lafs_write_begin,
+       .write_end      = lafs_write_end,
        .invalidatepage = lafs_invalidate_page,
        .releasepage    = lafs_release_page,
        .sync_page      = lafs_sync_page,