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>
This commit is contained in:
@@ -368,6 +368,8 @@ int noinline btrfs_drop_extents(struct btrfs_trans_handle *trans,
|
||||
u64 search_start = start;
|
||||
u64 leaf_start;
|
||||
u64 ram_bytes = 0;
|
||||
u64 orig_parent = 0;
|
||||
u64 disk_bytenr = 0;
|
||||
u8 compression;
|
||||
u8 encryption;
|
||||
u16 other_encoding = 0;
|
||||
@@ -500,17 +502,31 @@ next_slot:
|
||||
keep = 1;
|
||||
}
|
||||
|
||||
if (bookend && found_extent && locked_end < extent_end) {
|
||||
ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
|
||||
locked_end, extent_end - 1, GFP_NOFS);
|
||||
if (!ret) {
|
||||
btrfs_release_path(root, path);
|
||||
lock_extent(&BTRFS_I(inode)->io_tree,
|
||||
locked_end, extent_end - 1, GFP_NOFS);
|
||||
if (bookend && found_extent) {
|
||||
if (locked_end < extent_end) {
|
||||
ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
|
||||
locked_end, extent_end - 1,
|
||||
GFP_NOFS);
|
||||
if (!ret) {
|
||||
btrfs_release_path(root, path);
|
||||
lock_extent(&BTRFS_I(inode)->io_tree,
|
||||
locked_end, extent_end - 1,
|
||||
GFP_NOFS);
|
||||
locked_end = extent_end;
|
||||
continue;
|
||||
}
|
||||
locked_end = extent_end;
|
||||
continue;
|
||||
}
|
||||
locked_end = extent_end;
|
||||
orig_parent = path->nodes[0]->start;
|
||||
disk_bytenr = le64_to_cpu(old.disk_bytenr);
|
||||
if (disk_bytenr != 0) {
|
||||
ret = btrfs_inc_extent_ref(trans, root,
|
||||
disk_bytenr,
|
||||
le64_to_cpu(old.disk_num_bytes),
|
||||
orig_parent, root->root_key.objectid,
|
||||
trans->transid, inode->i_ino);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (found_inline) {
|
||||
@@ -537,8 +553,12 @@ next_slot:
|
||||
inode_sub_bytes(inode, old_num -
|
||||
new_num);
|
||||
}
|
||||
btrfs_set_file_extent_num_bytes(leaf, extent,
|
||||
new_num);
|
||||
if (!compression && !encryption) {
|
||||
btrfs_set_file_extent_ram_bytes(leaf,
|
||||
extent, new_num);
|
||||
}
|
||||
btrfs_set_file_extent_num_bytes(leaf,
|
||||
extent, new_num);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
} else if (key.offset < inline_limit &&
|
||||
(end > extent_end) &&
|
||||
@@ -582,11 +602,11 @@ next_slot:
|
||||
}
|
||||
/* create bookend, splitting the extent in two */
|
||||
if (bookend && found_extent) {
|
||||
u64 disk_bytenr;
|
||||
struct btrfs_key ins;
|
||||
ins.objectid = inode->i_ino;
|
||||
ins.offset = end;
|
||||
btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
|
||||
|
||||
btrfs_release_path(root, path);
|
||||
ret = btrfs_insert_empty_item(trans, root, path, &ins,
|
||||
sizeof(*extent));
|
||||
@@ -623,14 +643,13 @@ next_slot:
|
||||
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
|
||||
disk_bytenr = le64_to_cpu(old.disk_bytenr);
|
||||
if (disk_bytenr != 0) {
|
||||
ret = btrfs_inc_extent_ref(trans, root,
|
||||
disk_bytenr,
|
||||
le64_to_cpu(old.disk_num_bytes),
|
||||
leaf->start,
|
||||
ret = btrfs_update_extent_ref(trans, root,
|
||||
disk_bytenr, orig_parent,
|
||||
leaf->start,
|
||||
root->root_key.objectid,
|
||||
trans->transid, ins.objectid);
|
||||
|
||||
BUG_ON(ret);
|
||||
}
|
||||
btrfs_release_path(root, path);
|
||||
|
Reference in New Issue
Block a user