diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-10-31 12:46:39 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-10-31 12:46:39 -0400 |
commit | 70b99e6959a4c28ae1b314985eca731f3db72f1d (patch) | |
tree | 81578759fe422f7b17a734b8bf16b042aa02a046 /fs/btrfs/inode.c | |
parent | d899e05215178fed903ad0e7fc1cb4d8e0cc0a88 (diff) |
Btrfs: Compression corner fixes
Make sure we keep page->mapping NULL on the pages we're getting
via alloc_page. It gets set so a few of the callbacks can do the right
thing, but in general these pages don't have a mapping.
Don't try to truncate compressed inline items in btrfs_drop_extents.
The whole compressed item must be preserved.
Don't try to create multipage inline compressed items. When we try to
overwrite just the first page of the file, we would have to read in and recow
all the pages after it in the same compressed inline items. For now, only
create single page inline items.
Make sure we lock pages in the correct order during delalloc. The
search into the state tree for delalloc bytes can return bytes before
the page we already have locked.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 789c376157f9..806708dd7e38 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -239,6 +239,7 @@ static int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
239 | data_len = compressed_size; | 239 | data_len = compressed_size; |
240 | 240 | ||
241 | if (start > 0 || | 241 | if (start > 0 || |
242 | actual_end >= PAGE_CACHE_SIZE || | ||
242 | data_len >= BTRFS_MAX_INLINE_DATA_SIZE(root) || | 243 | data_len >= BTRFS_MAX_INLINE_DATA_SIZE(root) || |
243 | (!compressed_size && | 244 | (!compressed_size && |
244 | (actual_end & (root->sectorsize - 1)) == 0) || | 245 | (actual_end & (root->sectorsize - 1)) == 0) || |
@@ -248,7 +249,7 @@ static int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
248 | } | 249 | } |
249 | 250 | ||
250 | ret = btrfs_drop_extents(trans, root, inode, start, | 251 | ret = btrfs_drop_extents(trans, root, inode, start, |
251 | aligned_end, aligned_end, &hint_byte); | 252 | aligned_end, start, &hint_byte); |
252 | BUG_ON(ret); | 253 | BUG_ON(ret); |
253 | 254 | ||
254 | if (isize > actual_end) | 255 | if (isize > actual_end) |
@@ -423,6 +424,7 @@ again: | |||
423 | * free any pages it allocated and our page pointer array | 424 | * free any pages it allocated and our page pointer array |
424 | */ | 425 | */ |
425 | for (i = 0; i < nr_pages_ret; i++) { | 426 | for (i = 0; i < nr_pages_ret; i++) { |
427 | WARN_ON(pages[i]->mapping); | ||
426 | page_cache_release(pages[i]); | 428 | page_cache_release(pages[i]); |
427 | } | 429 | } |
428 | kfree(pages); | 430 | kfree(pages); |
@@ -572,8 +574,10 @@ free_pages_out_fail: | |||
572 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, | 574 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, |
573 | start, end, locked_page, 0, 0, 0); | 575 | start, end, locked_page, 0, 0, 0); |
574 | free_pages_out: | 576 | free_pages_out: |
575 | for (i = 0; i < nr_pages_ret; i++) | 577 | for (i = 0; i < nr_pages_ret; i++) { |
578 | WARN_ON(pages[i]->mapping); | ||
576 | page_cache_release(pages[i]); | 579 | page_cache_release(pages[i]); |
580 | } | ||
577 | if (pages) | 581 | if (pages) |
578 | kfree(pages); | 582 | kfree(pages); |
579 | 583 | ||