aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-06 22:02:51 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-06 22:02:51 -0500
commit771ed689d2cd53439e28e095bc38fbe40a71429e (patch)
tree518801f7141928e398d40c2b5955720d4346ce1a /fs/btrfs/file.c
parent4a69a41009c4ac691f7d9c289f5f37fabeddce46 (diff)
Btrfs: Optimize compressed writeback and reads
When reading compressed extents, try to put pages into the page cache for any pages covered by the compressed extent that readpages didn't already preload. Add an async work queue to handle transformations at delayed allocation processing time. Right now this is just compression. The workflow is: 1) Find offsets in the file marked for delayed allocation 2) Lock the pages 3) Lock the state bits 4) Call the async delalloc code The async delalloc code clears the state lock bits and delalloc bits. It is important this happens before the range goes into the work queue because otherwise it might deadlock with other work queue items that try to lock those extent bits. The file pages are compressed, and if the compression doesn't work the pages are written back directly. An ordered work queue is used to make sure the inodes are written in the same order that pdflush or writepages sent them down. This changes extent_write_cache_pages to let the writepage function update the wbc nr_written count. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c53
1 files changed, 36 insertions, 17 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 0c8cc35a8b97..337221ecca27 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -368,6 +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 u64 orig_parent = 0;
372 u64 disk_bytenr = 0;
371 u8 compression; 373 u8 compression;
372 u8 encryption; 374 u8 encryption;
373 u16 other_encoding = 0; 375 u16 other_encoding = 0;
@@ -500,17 +502,31 @@ next_slot:
500 keep = 1; 502 keep = 1;
501 } 503 }
502 504
503 if (bookend && found_extent && locked_end < extent_end) { 505 if (bookend && found_extent) {
504 ret = try_lock_extent(&BTRFS_I(inode)->io_tree, 506 if (locked_end < extent_end) {
505 locked_end, extent_end - 1, GFP_NOFS); 507 ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
506 if (!ret) { 508 locked_end, extent_end - 1,
507 btrfs_release_path(root, path); 509 GFP_NOFS);
508 lock_extent(&BTRFS_I(inode)->io_tree, 510 if (!ret) {
509 locked_end, extent_end - 1, GFP_NOFS); 511 btrfs_release_path(root, path);
512 lock_extent(&BTRFS_I(inode)->io_tree,
513 locked_end, extent_end - 1,
514 GFP_NOFS);
515 locked_end = extent_end;
516 continue;
517 }
510 locked_end = extent_end; 518 locked_end = extent_end;
511 continue;
512 } 519 }
513 locked_end = extent_end; 520 orig_parent = path->nodes[0]->start;
521 disk_bytenr = le64_to_cpu(old.disk_bytenr);
522 if (disk_bytenr != 0) {
523 ret = btrfs_inc_extent_ref(trans, root,
524 disk_bytenr,
525 le64_to_cpu(old.disk_num_bytes),
526 orig_parent, root->root_key.objectid,
527 trans->transid, inode->i_ino);
528 BUG_ON(ret);
529 }
514 } 530 }
515 531
516 if (found_inline) { 532 if (found_inline) {
@@ -537,8 +553,12 @@ next_slot:
537 inode_sub_bytes(inode, old_num - 553 inode_sub_bytes(inode, old_num -
538 new_num); 554 new_num);
539 } 555 }
540 btrfs_set_file_extent_num_bytes(leaf, extent, 556 if (!compression && !encryption) {
541 new_num); 557 btrfs_set_file_extent_ram_bytes(leaf,
558 extent, new_num);
559 }
560 btrfs_set_file_extent_num_bytes(leaf,
561 extent, new_num);
542 btrfs_mark_buffer_dirty(leaf); 562 btrfs_mark_buffer_dirty(leaf);
543 } else if (key.offset < inline_limit && 563 } else if (key.offset < inline_limit &&
544 (end > extent_end) && 564 (end > extent_end) &&
@@ -582,11 +602,11 @@ next_slot:
582 } 602 }
583 /* create bookend, splitting the extent in two */ 603 /* create bookend, splitting the extent in two */
584 if (bookend && found_extent) { 604 if (bookend && found_extent) {
585 u64 disk_bytenr;
586 struct btrfs_key ins; 605 struct btrfs_key ins;
587 ins.objectid = inode->i_ino; 606 ins.objectid = inode->i_ino;
588 ins.offset = end; 607 ins.offset = end;
589 btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); 608 btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
609
590 btrfs_release_path(root, path); 610 btrfs_release_path(root, path);
591 ret = btrfs_insert_empty_item(trans, root, path, &ins, 611 ret = btrfs_insert_empty_item(trans, root, path, &ins,
592 sizeof(*extent)); 612 sizeof(*extent));
@@ -623,14 +643,13 @@ next_slot:
623 643
624 btrfs_mark_buffer_dirty(path->nodes[0]); 644 btrfs_mark_buffer_dirty(path->nodes[0]);
625 645
626 disk_bytenr = le64_to_cpu(old.disk_bytenr);
627 if (disk_bytenr != 0) { 646 if (disk_bytenr != 0) {
628 ret = btrfs_inc_extent_ref(trans, root, 647 ret = btrfs_update_extent_ref(trans, root,
629 disk_bytenr, 648 disk_bytenr, orig_parent,
630 le64_to_cpu(old.disk_num_bytes), 649 leaf->start,
631 leaf->start,
632 root->root_key.objectid, 650 root->root_key.objectid,
633 trans->transid, ins.objectid); 651 trans->transid, ins.objectid);
652
634 BUG_ON(ret); 653 BUG_ON(ret);
635 } 654 }
636 btrfs_release_path(root, path); 655 btrfs_release_path(root, path);