From: Oliver Xymoron Get rid of newly exposed EIO errors from truncate races in filesystems DESC async write errors: truncate handling fixes EDESC - Missing kunmap in CIFS. - The reiserfs change needs review by the reiser guys. Looks OK. fs/buffer.c | 2 +- fs/cifs/file.c | 9 ++++++++- fs/nfs/write.c | 2 +- fs/ntfs/aops.c | 4 ++-- fs/reiserfs/inode.c | 4 ++-- fs/smbfs/file.c | 2 +- 6 files changed, 15 insertions(+), 8 deletions(-) diff -puN fs/buffer.c~awe-fix-truncate-errors fs/buffer.c --- 25/fs/buffer.c~awe-fix-truncate-errors 2003-08-06 20:21:03.000000000 -0700 +++ 25-akpm/fs/buffer.c 2003-08-06 20:21:03.000000000 -0700 @@ -2610,7 +2610,7 @@ int block_write_full_page(struct page *p */ block_invalidatepage(page, 0); unlock_page(page); - return -EIO; + return 0; /* don't care */ } /* diff -puN fs/cifs/file.c~awe-fix-truncate-errors fs/cifs/file.c --- 25/fs/cifs/file.c~awe-fix-truncate-errors 2003-08-06 20:21:03.000000000 -0700 +++ 25-akpm/fs/cifs/file.c 2003-08-06 20:21:03.000000000 -0700 @@ -500,12 +500,19 @@ cifs_partialpagewrite(struct page *page, write_data = kmap(page); write_data += from; - if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) { + if((to > PAGE_CACHE_SIZE) || (from > to)) { kunmap(page); FreeXid(xid); 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 */ if(mapping->host->i_size - offset < (loff_t)to) to = (unsigned)(mapping->host->i_size - offset); diff -puN fs/nfs/write.c~awe-fix-truncate-errors fs/nfs/write.c --- 25/fs/nfs/write.c~awe-fix-truncate-errors 2003-08-06 20:21:03.000000000 -0700 +++ 25-akpm/fs/nfs/write.c 2003-08-06 20:21:03.000000000 -0700 @@ -249,7 +249,7 @@ nfs_writepage(struct page *page, struct offset = i_size & (PAGE_CACHE_SIZE-1); /* OK, are we completely out? */ - err = -EIO; + err = 0; /* potential race with truncate - ignore */ if (page->index >= end_index+1 || !offset) goto out; do_it: diff -puN fs/ntfs/aops.c~awe-fix-truncate-errors fs/ntfs/aops.c --- 25/fs/ntfs/aops.c~awe-fix-truncate-errors 2003-08-06 20:21:03.000000000 -0700 +++ 25-akpm/fs/ntfs/aops.c 2003-08-06 20:21:03.000000000 -0700 @@ -811,8 +811,8 @@ static int ntfs_writepage(struct page *p if (unlikely(page->index >= (vi->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)) { unlock_page(page); - ntfs_debug("Write outside i_size. Returning i/o error."); - return -EIO; + ntfs_debug("Write outside i_size - truncated?"); + return 0; } ni = NTFS_I(vi); diff -puN fs/reiserfs/inode.c~awe-fix-truncate-errors fs/reiserfs/inode.c --- 25/fs/reiserfs/inode.c~awe-fix-truncate-errors 2003-08-06 20:21:03.000000000 -0700 +++ 25-akpm/fs/reiserfs/inode.c 2003-08-06 20:21:03.000000000 -0700 @@ -2048,8 +2048,8 @@ static int reiserfs_write_full_page(stru last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1) ; /* no file contents in this page */ if (page->index >= end_index + 1 || !last_offset) { - error = -EIO ; - goto fail ; + error = 0 ; + goto done ; } kaddr = kmap_atomic(page, KM_USER0); memset(kaddr + last_offset, 0, PAGE_CACHE_SIZE-last_offset) ; diff -puN fs/smbfs/file.c~awe-fix-truncate-errors fs/smbfs/file.c --- 25/fs/smbfs/file.c~awe-fix-truncate-errors 2003-08-06 20:21:03.000000000 -0700 +++ 25-akpm/fs/smbfs/file.c 2003-08-06 20:21:03.000000000 -0700 @@ -193,7 +193,7 @@ smb_writepage(struct page *page, struct offset = inode->i_size & (PAGE_CACHE_SIZE-1); /* OK, are we completely out? */ if (page->index >= end_index+1 || !offset) - return -EIO; + return 0; /* truncated - don't care */ do_it: page_cache_get(page); err = smb_writepage_sync(inode, page, 0, offset); _