#include "lafs.h"
#include <linux/bit_spinlock.h>
#include <linux/writeback.h>
+#include <linux/version.h>
struct readpage_data {
struct bio *bio;
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.
* 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)
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);
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);
}
if (err < 0)
goto fail;
+ *fsdata = fb;
return 0;
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
}
__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
.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,