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>
This commit is contained in:
Al Viro 2016-08-29 22:04:51 -04:00
parent 77469c3f57
commit 92e50d2d42
1 changed files with 30 additions and 38 deletions

View File

@ -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;
loff_t last_pos = pos + copied;
ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata);
if (unlikely(ret))
_write_failed(inode, pos + len);
/* 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)