summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/extent_io.c15
-rw-r--r--fs/btrfs/file.c8
-rw-r--r--fs/btrfs/inode.c9
3 files changed, 17 insertions, 15 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 2a3624a..17c508a 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 df97d47..d968900 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 08760ff..40b4a8e 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);
OpenPOWER on IntegriCloud