summaryrefslogtreecommitdiffstats
path: root/fs/exofs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-08-30 04:04:51 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2016-12-10 20:25:19 +0100
commit92e50d2d42d7cb9fcd816b47b580622032d38293 (patch)
treeec748429d1fce11dc3d079e2d26c2b9ab27a41e0 /fs/exofs
parent9p: saner ->write_end() on failing copy into non-uptodate page (diff)
downloadlinux-92e50d2d42d7cb9fcd816b47b580622032d38293.tar.xz
linux-92e50d2d42d7cb9fcd816b47b580622032d38293.zip
exofs: don't mess with simple_write_{begin,end}
... and don't zero anything on short copy; just unlock and return 0 if that has happened on non-uptodate page. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/exofs')
-rw-r--r--fs/exofs/inode.c68
1 files changed, 30 insertions, 38 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index d8072bc074a4..0ac62811b341 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -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)