diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 2a3624adc0cf..17c508a941eb 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1988,9 +1988,12 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, u64 nr_delalloc; u64 delalloc_end; + WARN_ON(!PageLocked(page)); - if (page->index > end_index) { - clear_extent_dirty(tree, start, page_end, GFP_NOFS); + page_offset = i_size & (PAGE_CACHE_SIZE - 1); + if (page->index > end_index || + (page->index == end_index && !page_offset)) { + page->mapping->a_ops->invalidatepage(page, 0); unlock_page(page); return 0; } @@ -1998,13 +2001,13 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, if (page->index == end_index) { char *userpage; - size_t offset = i_size & (PAGE_CACHE_SIZE - 1); - userpage = kmap_atomic(page, KM_USER0); - memset(userpage + offset, 0, PAGE_CACHE_SIZE - offset); - flush_dcache_page(page); + memset(userpage + page_offset, 0, + PAGE_CACHE_SIZE - page_offset); kunmap_atomic(userpage, KM_USER0); + flush_dcache_page(page); } + page_offset = 0; set_page_extent_mapped(page); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index df97d470812a..d968900c6973 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -305,7 +305,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans, (inline_size & (root->sectorsize -1)) == 0 || inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) { u64 last_end; - u64 existing_delalloc = 0; for (i = 0; i < num_pages; i++) { struct page *p = pages[i]; @@ -315,13 +314,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans, last_end = (u64)(pages[num_pages -1]->index) << PAGE_CACHE_SHIFT; last_end += PAGE_CACHE_SIZE - 1; - if (start_pos < isize) { - u64 delalloc_start = start_pos; - existing_delalloc = count_range_bits(io_tree, - &delalloc_start, - end_of_last_block, (u64)-1, - EXTENT_DELALLOC); - } set_extent_delalloc(io_tree, start_pos, end_of_last_block, GFP_NOFS); btrfs_add_ordered_inode(inode); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 08760ff9bab7..40b4a8ec17fe 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1180,19 +1180,26 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) goto out; ret = -ENOMEM; +again: page = grab_cache_page(mapping, index); if (!page) goto out; if (!PageUptodate(page)) { ret = btrfs_readpage(NULL, page); lock_page(page); + if (page->mapping != mapping) { + unlock_page(page); + page_cache_release(page); + goto again; + } if (!PageUptodate(page)) { ret = -EIO; goto out; } } - page_start = (u64)page->index << PAGE_CACHE_SHIFT; + page_start = (u64)page->index << PAGE_CACHE_SHIFT; + wait_on_page_writeback(page); ret = btrfs_cow_one_page(inode, page, offset); unlock_page(page);