The patch titled mm: trim more holes has been added to the -mm tree. Its filename is mm-trim-more-holes.patch *** Remember to use Documentation/SubmitChecklist when testing your code *** See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: mm: trim more holes From: Nick Piggin <npiggin@xxxxxxx> If prepare_write fails with AOP_TRUNCATED_PAGE, or if commit_write fails, then we may have failed the write operation despite prepare_write having instantiated blocks past i_size. Fix this, and consolidate the trimming into one place. Signed-off-by: Nick Piggin <npiggin@xxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/filemap.c | 80 ++++++++++++++++++++++++------------------------- 1 files changed, 40 insertions(+), 40 deletions(-) diff -puN mm/filemap.c~mm-trim-more-holes mm/filemap.c --- a/mm/filemap.c~mm-trim-more-holes +++ a/mm/filemap.c @@ -1949,22 +1949,9 @@ generic_file_buffered_write(struct kiocb } status = a_ops->prepare_write(file, page, offset, offset+bytes); - if (unlikely(status)) { - loff_t isize = i_size_read(inode); + if (unlikely(status)) + goto fs_write_aop_error; - if (status != AOP_TRUNCATED_PAGE) - unlock_page(page); - page_cache_release(page); - if (status == AOP_TRUNCATED_PAGE) - continue; - /* - * prepare_write() may have instantiated a few blocks - * outside i_size. Trim these off again. - */ - if (pos + bytes > isize) - vmtruncate(inode, isize); - break; - } if (likely(nr_segs == 1)) copied = filemap_copy_from_user(page, offset, buf, bytes); @@ -1973,40 +1960,53 @@ generic_file_buffered_write(struct kiocb cur_iov, iov_offset, bytes); flush_dcache_page(page); status = a_ops->commit_write(file, page, offset, offset+bytes); - if (status == AOP_TRUNCATED_PAGE) { - page_cache_release(page); - continue; + if (unlikely(status < 0 || status == AOP_TRUNCATED_PAGE)) + goto fs_write_aop_error; + if (unlikely(copied != bytes)) { + status = -EFAULT; + goto fs_write_aop_error; } - if (likely(copied > 0)) { - if (!status) - status = copied; + if (unlikely(status > 0)) /* filesystem did partial write */ + copied = status; - if (status >= 0) { - written += status; - count -= status; - pos += status; - buf += status; - if (unlikely(nr_segs > 1)) { - filemap_set_next_iovec(&cur_iov, - &iov_offset, status); - if (count) - buf = cur_iov->iov_base + - iov_offset; - } else { - iov_offset += status; - } + if (likely(copied > 0)) { + written += copied; + count -= copied; + pos += copied; + buf += copied; + if (unlikely(nr_segs > 1)) { + filemap_set_next_iovec(&cur_iov, + &iov_offset, copied); + if (count) + buf = cur_iov->iov_base + iov_offset; + } else { + iov_offset += copied; } } - if (unlikely(copied != bytes)) - if (status >= 0) - status = -EFAULT; unlock_page(page); mark_page_accessed(page); page_cache_release(page); - if (status < 0) - break; balance_dirty_pages_ratelimited(mapping); cond_resched(); + continue; + +fs_write_aop_error: + if (status != AOP_TRUNCATED_PAGE) + unlock_page(page); + page_cache_release(page); + + /* + * prepare_write() may have instantiated a few blocks + * outside i_size. Trim these off again. Don't need + * i_size_read because we hold i_mutex. + */ + if (pos + bytes > inode->i_size) + vmtruncate(inode, inode->i_size); + if (status == AOP_TRUNCATED_PAGE) + continue; + else + break; + } while (count); *ppos = pos; _ Patches currently in -mm which might be from npiggin@xxxxxxx are mm-fix-fault-vs-invalidate-race-for-linear-mappings.patch mm-fix-fault-vs-invalidate-race-for-linear-mappings-fix.patch mm-merge-populate-and-nopage-into-fault-fixes-nonlinear.patch mm-merge-nopfn-into-fault.patch mm-remove-legacy-cruft.patch mm-debug-check-for-the-fault-vs-invalidate-race.patch mm-fix-clear_page_dirty_for_io-vs-fault-race.patch git-arm-master.patch slob-rework-freelist-handling.patch slob-remove-bigblock-tracking.patch slob-improved-alignment-handling.patch mm-revert-kernel_ds-buffered-write-optimisation.patch revert-81b0c8713385ce1b1b9058e916edcf9561ad76d6.patch revert-6527c2bdf1f833cc18e8f42bd97973d583e4aa83.patch mm-clean-up-buffered-write-code.patch mm-debug-write-deadlocks.patch mm-trim-more-holes.patch mm-buffered-write-cleanup.patch mm-write-iovec-cleanup.patch mm-fix-pagecache-write-deadlocks.patch mm-buffered-write-iterator.patch fs-fix-data-loss-on-error.patch fs-introduce-write_begin-write_end-and-perform_write-aops.patch mm-restore-kernel_ds-optimisations.patch implement-simple-fs-aops.patch block_dev-convert-to-new-aops.patch ext2-convert-to-new-aops.patch ext3-convert-to-new-aops.patch ext4-convert-to-new-aops.patch xfs-convert-to-new-aops.patch fs-new-cont-helpers.patch fat-convert-to-new-aops.patch hfs-convert-to-new-aops.patch hfsplus-convert-to-new-aops.patch hpfs-convert-to-new-aops.patch bfs-convert-to-new-aops.patch qnx4-convert-to-new-aops.patch reiserfs-use-generic-write.patch reiserfs-convert-to-new-aops.patch reiserfs-use-generic_cont_expand_simple.patch with-reiserfs-no-longer-using-the-weird-generic_cont_expand-remove-it-completely.patch nfs-convert-to-new-aops.patch smb-convert-to-new-aops.patch fuse-convert-to-new-aops.patch hostfs-convert-to-new-aops.patch jffs2-convert-to-new-aops.patch ufs-convert-to-new-aops.patch udf-convert-to-new-aops.patch sysv-convert-to-new-aops.patch minix-convert-to-new-aops.patch jfs-convert-to-new-aops.patch mm-document-fault_data-and-flags.patch fs-introduce-some-page-buffer-invariants.patch fs-introduce-write_begin-write_end-and-perform_write-aops-revoke.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html