|
@@ -870,46 +870,31 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
|
|
|
|
|
|
page = *pagep;
|
|
|
if (page == NULL) {
|
|
|
- ret = simple_write_begin(file, mapping, pos, len, flags, pagep,
|
|
|
- fsdata);
|
|
|
- if (ret) {
|
|
|
- EXOFS_DBGMSG("simple_write_begin failed\n");
|
|
|
- goto out;
|
|
|
+ page = grab_cache_page_write_begin(mapping, pos >> PAGE_SHIFT,
|
|
|
+ flags);
|
|
|
+ if (!page) {
|
|
|
+ EXOFS_DBGMSG("grab_cache_page_write_begin failed\n");
|
|
|
+ return -ENOMEM;
|
|
|
}
|
|
|
-
|
|
|
- page = *pagep;
|
|
|
+ *pagep = page;
|
|
|
}
|
|
|
|
|
|
/* read modify write */
|
|
|
if (!PageUptodate(page) && (len != PAGE_SIZE)) {
|
|
|
loff_t i_size = i_size_read(mapping->host);
|
|
|
pgoff_t end_index = i_size >> PAGE_SHIFT;
|
|
|
- size_t rlen;
|
|
|
|
|
|
- if (page->index < end_index)
|
|
|
- rlen = PAGE_SIZE;
|
|
|
- else if (page->index == end_index)
|
|
|
- rlen = i_size & ~PAGE_MASK;
|
|
|
- else
|
|
|
- rlen = 0;
|
|
|
-
|
|
|
- if (!rlen) {
|
|
|
+ if (page->index > end_index) {
|
|
|
clear_highpage(page);
|
|
|
SetPageUptodate(page);
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- ret = _readpage(page, true);
|
|
|
- if (ret) {
|
|
|
- /*SetPageError was done by _readpage. Is it ok?*/
|
|
|
- unlock_page(page);
|
|
|
- EXOFS_DBGMSG("__readpage failed\n");
|
|
|
+ } else {
|
|
|
+ ret = _readpage(page, true);
|
|
|
+ if (ret) {
|
|
|
+ unlock_page(page);
|
|
|
+ EXOFS_DBGMSG("__readpage failed\n");
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
-out:
|
|
|
- if (unlikely(ret))
|
|
|
- _write_failed(mapping->host, pos + len);
|
|
|
-
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -929,18 +914,25 @@ static int exofs_write_end(struct file *file, struct address_space *mapping,
|
|
|
struct page *page, void *fsdata)
|
|
|
{
|
|
|
struct inode *inode = mapping->host;
|
|
|
- /* According to comment in simple_write_end i_mutex is held */
|
|
|
- loff_t i_size = inode->i_size;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata);
|
|
|
- if (unlikely(ret))
|
|
|
- _write_failed(inode, pos + len);
|
|
|
+ loff_t last_pos = pos + copied;
|
|
|
|
|
|
- /* TODO: once simple_write_end marks inode dirty remove */
|
|
|
- if (i_size != inode->i_size)
|
|
|
+ if (!PageUptodate(page)) {
|
|
|
+ if (copied < len) {
|
|
|
+ _write_failed(inode, pos + len);
|
|
|
+ copied = 0;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ SetPageUptodate(page);
|
|
|
+ }
|
|
|
+ if (last_pos > inode->i_size) {
|
|
|
+ i_size_write(inode, last_pos);
|
|
|
mark_inode_dirty(inode);
|
|
|
- return ret;
|
|
|
+ }
|
|
|
+ set_page_dirty(page);
|
|
|
+out:
|
|
|
+ unlock_page(page);
|
|
|
+ put_page(page);
|
|
|
+ return copied;
|
|
|
}
|
|
|
|
|
|
static int exofs_releasepage(struct page *page, gfp_t gfp)
|