mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
Merge branch 'work.write_end' into for-linus
This commit is contained in:
commit
4da00fd1b9
6 changed files with 52 additions and 65 deletions
|
@ -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);
|
||||
|
||||
if (unlikely(copied < len)) {
|
||||
/*
|
||||
* zero out the rest of the area
|
||||
*/
|
||||
unsigned from = pos & (PAGE_SIZE - 1);
|
||||
|
||||
zero_user(page, from + copied, len - copied);
|
||||
flush_dcache_page(page);
|
||||
if (unlikely(copied < len && !PageUptodate(page))) {
|
||||
copied = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!PageUptodate(page))
|
||||
SetPageUptodate(page);
|
||||
/*
|
||||
* No need to use i_size_read() here, the i_size
|
||||
* 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);
|
||||
}
|
||||
set_page_dirty(page);
|
||||
out:
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
|
|
|
@ -1276,25 +1276,27 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
|
|||
struct page *page, void *fsdata)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
unsigned from = pos & (PAGE_SIZE - 1);
|
||||
int check_cap = 0;
|
||||
|
||||
dout("write_end file %p inode %p page %p %d~%d (%d)\n", file,
|
||||
inode, page, (int)pos, (int)copied, (int)len);
|
||||
|
||||
/* zero the stale part of the page if we did a short copy */
|
||||
if (copied < len)
|
||||
zero_user_segment(page, from+copied, len);
|
||||
if (!PageUptodate(page)) {
|
||||
if (copied < len) {
|
||||
copied = 0;
|
||||
goto out;
|
||||
}
|
||||
SetPageUptodate(page);
|
||||
}
|
||||
|
||||
/* did file size increase? */
|
||||
if (pos+copied > i_size_read(inode))
|
||||
check_cap = ceph_inode_set_size(inode, pos+copied);
|
||||
|
||||
if (!PageUptodate(page))
|
||||
SetPageUptodate(page);
|
||||
|
||||
set_page_dirty(page);
|
||||
|
||||
out:
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)));
|
||||
kaddr = kmap_atomic(page);
|
||||
memcpy(buf + pos, kaddr + pos, copied);
|
||||
memset(kaddr + pos + copied, 0, len - copied);
|
||||
flush_dcache_page(page);
|
||||
kunmap_atomic(kaddr);
|
||||
|
||||
if (!PageUptodate(page))
|
||||
SetPageUptodate(page);
|
||||
WARN_ON(!PageUptodate(page));
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
|
|
14
fs/libfs.c
14
fs/libfs.c
|
@ -465,6 +465,8 @@ EXPORT_SYMBOL(simple_write_begin);
|
|||
* 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
|
||||
* case that i_size has changed.
|
||||
*
|
||||
* Use *ONLY* with simple_readpage()
|
||||
*/
|
||||
int simple_write_end(struct file *file, struct address_space *mapping,
|
||||
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;
|
||||
|
||||
/* zero the stale part of the page if we did a short copy */
|
||||
if (copied < len) {
|
||||
unsigned from = pos & (PAGE_SIZE - 1);
|
||||
if (!PageUptodate(page)) {
|
||||
if (copied < len) {
|
||||
unsigned from = pos & (PAGE_SIZE - 1);
|
||||
|
||||
zero_user(page, from + copied, len - copied);
|
||||
}
|
||||
|
||||
if (!PageUptodate(page))
|
||||
zero_user(page, from + copied, len - copied);
|
||||
}
|
||||
SetPageUptodate(page);
|
||||
}
|
||||
/*
|
||||
* No need to use i_size_read() here, the i_size
|
||||
* cannot change under us because we hold the i_mutex.
|
||||
|
|
|
@ -374,7 +374,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
|
|||
*/
|
||||
if (!PageUptodate(page)) {
|
||||
unsigned pglen = nfs_page_length(page);
|
||||
unsigned end = offset + len;
|
||||
unsigned end = offset + copied;
|
||||
|
||||
if (pglen == 0) {
|
||||
zero_user_segments(page, 0, offset,
|
||||
|
|
Loading…
Reference in a new issue