Skip to content

Commit

Permalink
Fix corners in writepage and btrfs_truncate_page
Browse files Browse the repository at this point in the history
The extent_io writepage calls needed an extra check for discarding
pages that started on th last byte in the file.

btrfs_truncate_page needed checks to make sure the page was still part
of the file after reading it, and most importantly, needed to wait for
all IO to the page to finish before freeing the corresponding extents on
disk.

Signed-off-by: Chris Mason <[email protected]>
  • Loading branch information
chrismason-xx committed Sep 25, 2008
1 parent a0af469 commit 211c17f
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 15 deletions.
15 changes: 9 additions & 6 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1988,23 +1988,26 @@ 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;
}

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);

Expand Down
8 changes: 0 additions & 8 deletions fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
Expand Down
9 changes: 8 additions & 1 deletion fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 211c17f

Please sign in to comment.