aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-10-31 12:46:39 -0400
committerChris Mason <chris.mason@oracle.com>2008-10-31 12:46:39 -0400
commit70b99e6959a4c28ae1b314985eca731f3db72f1d (patch)
tree81578759fe422f7b17a734b8bf16b042aa02a046 /fs/btrfs
parentd899e05215178fed903ad0e7fc1cb4d8e0cc0a88 (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')
-rw-r--r--fs/btrfs/compression.c4
-rw-r--r--fs/btrfs/extent_io.c11
-rw-r--r--fs/btrfs/file.c21
-rw-r--r--fs/btrfs/inode.c8
4 files changed, 35 insertions, 9 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 9adaa79adad9..354913177ba6 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -220,10 +220,12 @@ static void end_compressed_bio_write(struct bio *bio, int err)
220 */ 220 */
221 inode = cb->inode; 221 inode = cb->inode;
222 tree = &BTRFS_I(inode)->io_tree; 222 tree = &BTRFS_I(inode)->io_tree;
223 cb->compressed_pages[0]->mapping = cb->inode->i_mapping;
223 tree->ops->writepage_end_io_hook(cb->compressed_pages[0], 224 tree->ops->writepage_end_io_hook(cb->compressed_pages[0],
224 cb->start, 225 cb->start,
225 cb->start + cb->len - 1, 226 cb->start + cb->len - 1,
226 NULL, 1); 227 NULL, 1);
228 cb->compressed_pages[0]->mapping = NULL;
227 229
228 end_compressed_writeback(inode, cb->start, cb->len); 230 end_compressed_writeback(inode, cb->start, cb->len);
229 /* note, our inode could be gone now */ 231 /* note, our inode could be gone now */
@@ -306,6 +308,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
306 else 308 else
307 ret = 0; 309 ret = 0;
308 310
311 page->mapping = NULL;
309 if (ret || bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < 312 if (ret || bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) <
310 PAGE_CACHE_SIZE) { 313 PAGE_CACHE_SIZE) {
311 bio_get(bio); 314 bio_get(bio);
@@ -423,6 +426,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
423 else 426 else
424 ret = 0; 427 ret = 0;
425 428
429 page->mapping = NULL;
426 if (ret || bio_add_page(comp_bio, page, PAGE_CACHE_SIZE, 0) < 430 if (ret || bio_add_page(comp_bio, page, PAGE_CACHE_SIZE, 0) <
427 PAGE_CACHE_SIZE) { 431 PAGE_CACHE_SIZE) {
428 bio_get(comp_bio); 432 bio_get(comp_bio);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index eb3c12e7beaf..9b37ce6e5168 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1242,13 +1242,22 @@ again:
1242 delalloc_end = 0; 1242 delalloc_end = 0;
1243 found = find_delalloc_range(tree, &delalloc_start, &delalloc_end, 1243 found = find_delalloc_range(tree, &delalloc_start, &delalloc_end,
1244 max_bytes); 1244 max_bytes);
1245 if (!found) { 1245 if (!found || delalloc_end <= *start) {
1246 *start = delalloc_start; 1246 *start = delalloc_start;
1247 *end = delalloc_end; 1247 *end = delalloc_end;
1248 return found; 1248 return found;
1249 } 1249 }
1250 1250
1251 /* 1251 /*
1252 * start comes from the offset of locked_page. We have to lock
1253 * pages in order, so we can't process delalloc bytes before
1254 * locked_page
1255 */
1256 if (delalloc_start < *start) {
1257 delalloc_start = *start;
1258 }
1259
1260 /*
1252 * make sure to limit the number of pages we try to lock down 1261 * make sure to limit the number of pages we try to lock down
1253 * if we're looping. 1262 * if we're looping.
1254 */ 1263 */
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 238a8e215eb9..0c8cc35a8b97 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -368,8 +368,8 @@ int noinline btrfs_drop_extents(struct btrfs_trans_handle *trans,
368 u64 search_start = start; 368 u64 search_start = start;
369 u64 leaf_start; 369 u64 leaf_start;
370 u64 ram_bytes = 0; 370 u64 ram_bytes = 0;
371 u8 compression = 0; 371 u8 compression;
372 u8 encryption = 0; 372 u8 encryption;
373 u16 other_encoding = 0; 373 u16 other_encoding = 0;
374 u64 root_gen; 374 u64 root_gen;
375 u64 root_owner; 375 u64 root_owner;
@@ -415,6 +415,8 @@ next_slot:
415 leaf_start = 0; 415 leaf_start = 0;
416 root_gen = 0; 416 root_gen = 0;
417 root_owner = 0; 417 root_owner = 0;
418 compression = 0;
419 encryption = 0;
418 extent = NULL; 420 extent = NULL;
419 leaf = path->nodes[0]; 421 leaf = path->nodes[0];
420 slot = path->slots[0]; 422 slot = path->slots[0];
@@ -546,8 +548,12 @@ next_slot:
546 inline_limit - key.offset); 548 inline_limit - key.offset);
547 inode_sub_bytes(inode, extent_end - 549 inode_sub_bytes(inode, extent_end -
548 inline_limit); 550 inline_limit);
549 btrfs_truncate_item(trans, root, path, 551 btrfs_set_file_extent_ram_bytes(leaf, extent,
550 new_size, 1); 552 new_size);
553 if (!compression && !encryption) {
554 btrfs_truncate_item(trans, root, path,
555 new_size, 1);
556 }
551 } 557 }
552 } 558 }
553 /* delete the entire extent */ 559 /* delete the entire extent */
@@ -567,8 +573,11 @@ next_slot:
567 new_size = btrfs_file_extent_calc_inline_size( 573 new_size = btrfs_file_extent_calc_inline_size(
568 extent_end - end); 574 extent_end - end);
569 inode_sub_bytes(inode, end - key.offset); 575 inode_sub_bytes(inode, end - key.offset);
570 ret = btrfs_truncate_item(trans, root, path, 576 btrfs_set_file_extent_ram_bytes(leaf, extent,
571 new_size, 0); 577 new_size);
578 if (!compression && !encryption)
579 ret = btrfs_truncate_item(trans, root, path,
580 new_size, 0);
572 BUG_ON(ret); 581 BUG_ON(ret);
573 } 582 }
574 /* create bookend, splitting the extent in two */ 583 /* create bookend, splitting the extent in two */
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);
574free_pages_out: 576free_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