Commit e89061de authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] async write errors: fix spurious fs truncate errors

From: Oliver Xymoron <oxymoron@waste.org>

Currently, a writepage() which detects that it is writing outside i_size (due
to concurrent truncate) will abandon the write, returning -EIO.

The return value will bogusly cause an error to be recorded in the
address_space.  So convert all those writepage() instances to return zero in
this case.
parent fcad2b42
...@@ -2610,7 +2610,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block, ...@@ -2610,7 +2610,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
*/ */
block_invalidatepage(page, 0); block_invalidatepage(page, 0);
unlock_page(page); unlock_page(page);
return -EIO; return 0; /* don't care */
} }
/* /*
......
...@@ -500,12 +500,19 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to) ...@@ -500,12 +500,19 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
write_data = kmap(page); write_data = kmap(page);
write_data += from; write_data += from;
if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) { if((to > PAGE_CACHE_SIZE) || (from > to)) {
kunmap(page); kunmap(page);
FreeXid(xid); FreeXid(xid);
return -EIO; return -EIO;
} }
/* racing with truncate? */
if(offset > mapping->host->i_size) {
kunmap(page);
FreeXid(xid);
return 0; /* don't care */
}
/* check to make sure that we are not extending the file */ /* check to make sure that we are not extending the file */
if(mapping->host->i_size - offset < (loff_t)to) if(mapping->host->i_size - offset < (loff_t)to)
to = (unsigned)(mapping->host->i_size - offset); to = (unsigned)(mapping->host->i_size - offset);
......
...@@ -242,7 +242,7 @@ nfs_writepage(struct page *page, struct writeback_control *wbc) ...@@ -242,7 +242,7 @@ nfs_writepage(struct page *page, struct writeback_control *wbc)
offset = i_size & (PAGE_CACHE_SIZE-1); offset = i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */ /* OK, are we completely out? */
err = -EIO; err = 0; /* potential race with truncate - ignore */
if (page->index >= end_index+1 || !offset) if (page->index >= end_index+1 || !offset)
goto out; goto out;
do_it: do_it:
......
...@@ -811,8 +811,8 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) ...@@ -811,8 +811,8 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
if (unlikely(page->index >= (vi->i_size + PAGE_CACHE_SIZE - 1) >> if (unlikely(page->index >= (vi->i_size + PAGE_CACHE_SIZE - 1) >>
PAGE_CACHE_SHIFT)) { PAGE_CACHE_SHIFT)) {
unlock_page(page); unlock_page(page);
ntfs_debug("Write outside i_size. Returning i/o error."); ntfs_debug("Write outside i_size - truncated?");
return -EIO; return 0;
} }
ni = NTFS_I(vi); ni = NTFS_I(vi);
......
...@@ -2048,8 +2048,8 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control ...@@ -2048,8 +2048,8 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1) ; last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1) ;
/* no file contents in this page */ /* no file contents in this page */
if (page->index >= end_index + 1 || !last_offset) { if (page->index >= end_index + 1 || !last_offset) {
error = -EIO ; error = 0 ;
goto fail ; goto done ;
} }
kaddr = kmap_atomic(page, KM_USER0); kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr + last_offset, 0, PAGE_CACHE_SIZE-last_offset) ; memset(kaddr + last_offset, 0, PAGE_CACHE_SIZE-last_offset) ;
......
...@@ -193,7 +193,7 @@ smb_writepage(struct page *page, struct writeback_control *wbc) ...@@ -193,7 +193,7 @@ smb_writepage(struct page *page, struct writeback_control *wbc)
offset = inode->i_size & (PAGE_CACHE_SIZE-1); offset = inode->i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */ /* OK, are we completely out? */
if (page->index >= end_index+1 || !offset) if (page->index >= end_index+1 || !offset)
return -EIO; return 0; /* truncated - don't care */
do_it: do_it:
page_cache_get(page); page_cache_get(page);
err = smb_writepage_sync(inode, page, 0, offset); err = smb_writepage_sync(inode, page, 0, offset);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment