Merge branch 'work.write_end' into for-linus

This commit is contained in:
Al Viro 2016-12-16 16:19:49 -05:00
commit 4da00fd1b9
6 changed files with 52 additions and 65 deletions

View File

@ -309,18 +309,10 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping);
if (unlikely(copied < len)) { if (unlikely(copied < len && !PageUptodate(page))) {
/* copied = 0;
* zero out the rest of the area goto out;
*/
unsigned from = pos & (PAGE_SIZE - 1);
zero_user(page, from + copied, len - copied);
flush_dcache_page(page);
} }
if (!PageUptodate(page))
SetPageUptodate(page);
/* /*
* No need to use i_size_read() here, the i_size * No need to use i_size_read() here, the i_size
* cannot change under us because we hold the i_mutex. * cannot change under us because we hold the i_mutex.
@ -330,6 +322,7 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
i_size_write(inode, last_pos); i_size_write(inode, last_pos);
} }
set_page_dirty(page); set_page_dirty(page);
out:
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);

View File

@ -1276,25 +1276,27 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
struct page *page, void *fsdata) struct page *page, void *fsdata)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
unsigned from = pos & (PAGE_SIZE - 1);
int check_cap = 0; int check_cap = 0;
dout("write_end file %p inode %p page %p %d~%d (%d)\n", file, dout("write_end file %p inode %p page %p %d~%d (%d)\n", file,
inode, page, (int)pos, (int)copied, (int)len); inode, page, (int)pos, (int)copied, (int)len);
/* zero the stale part of the page if we did a short copy */ /* zero the stale part of the page if we did a short copy */
if (copied < len) if (!PageUptodate(page)) {
zero_user_segment(page, from+copied, len); if (copied < len) {
copied = 0;
goto out;
}
SetPageUptodate(page);
}
/* did file size increase? */ /* did file size increase? */
if (pos+copied > i_size_read(inode)) if (pos+copied > i_size_read(inode))
check_cap = ceph_inode_set_size(inode, pos+copied); check_cap = ceph_inode_set_size(inode, pos+copied);
if (!PageUptodate(page))
SetPageUptodate(page);
set_page_dirty(page); set_page_dirty(page);
out:
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);

View File

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

View File

@ -839,12 +839,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs2_dinode))); BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs2_dinode)));
kaddr = kmap_atomic(page); kaddr = kmap_atomic(page);
memcpy(buf + pos, kaddr + pos, copied); memcpy(buf + pos, kaddr + pos, copied);
memset(kaddr + pos + copied, 0, len - copied);
flush_dcache_page(page); flush_dcache_page(page);
kunmap_atomic(kaddr); kunmap_atomic(kaddr);
if (!PageUptodate(page)) WARN_ON(!PageUptodate(page));
SetPageUptodate(page);
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);

View File

@ -465,6 +465,8 @@ EXPORT_SYMBOL(simple_write_begin);
* is not called, so a filesystem that actually does store data in .write_inode * is not called, so a filesystem that actually does store data in .write_inode
* should extend on what's done here with a call to mark_inode_dirty() in the * should extend on what's done here with a call to mark_inode_dirty() in the
* case that i_size has changed. * case that i_size has changed.
*
* Use *ONLY* with simple_readpage()
*/ */
int simple_write_end(struct file *file, struct address_space *mapping, int simple_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied, loff_t pos, unsigned len, unsigned copied,
@ -474,14 +476,14 @@ int simple_write_end(struct file *file, struct address_space *mapping,
loff_t last_pos = pos + copied; loff_t last_pos = pos + copied;
/* zero the stale part of the page if we did a short copy */ /* zero the stale part of the page if we did a short copy */
if (!PageUptodate(page)) {
if (copied < len) { if (copied < len) {
unsigned from = pos & (PAGE_SIZE - 1); unsigned from = pos & (PAGE_SIZE - 1);
zero_user(page, from + copied, len - copied); zero_user(page, from + copied, len - copied);
} }
if (!PageUptodate(page))
SetPageUptodate(page); SetPageUptodate(page);
}
/* /*
* No need to use i_size_read() here, the i_size * No need to use i_size_read() here, the i_size
* cannot change under us because we hold the i_mutex. * cannot change under us because we hold the i_mutex.

View File

@ -374,7 +374,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
*/ */
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
unsigned pglen = nfs_page_length(page); unsigned pglen = nfs_page_length(page);
unsigned end = offset + len; unsigned end = offset + copied;
if (pglen == 0) { if (pglen == 0) {
zero_user_segments(page, 0, offset, zero_user_segments(page, 0, offset,