From: NeilBrown Date: Thu, 15 Jul 2010 18:44:45 +0000 (+0200) Subject: Use write_begin/write_end in place of prepare/commit X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=68aa040d0df4a4d7ca5cde4228e172f19bffaa94;p=LaFS.git Use write_begin/write_end in place of prepare/commit As this is the 'new way' and need for upgrading the base kernel. Signed-off-by: NeilBrown --- diff --git a/file.c b/file.c index 4c4b36d..d88bcfe 100644 --- a/file.c +++ b/file.c @@ -11,6 +11,7 @@ #include "lafs.h" #include #include +#include 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,