提交 239b14b3 编写于 作者: C Chris Mason

Btrfs: Bring back mount -o ssd optimizations

Signed-off-by: NChris Mason <chris.mason@oracle.com>
上级 0d81ba5d
......@@ -1405,6 +1405,9 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_path *path,
u64 isize);
/* inode.c */
int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
size_t size, struct bio *bio);
static inline void dec_i_blocks(struct inode *inode, u64 dec)
{
dec = dec >> 9;
......
......@@ -1103,4 +1103,6 @@ int btrfs_read_buffer(struct extent_buffer *buf)
static struct extent_io_ops btree_extent_io_ops = {
.writepage_io_hook = btree_writepage_io_hook,
.submit_bio_hook = btree_submit_bio_hook,
/* note we're sharing with inode.c for the merge bio hook */
.merge_bio_hook = btrfs_merge_bio_hook,
};
......@@ -1473,13 +1473,31 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
struct btrfs_root * root = orig_root->fs_info->extent_root;
struct btrfs_fs_info *info = root->fs_info;
u64 total_needed = num_bytes;
u64 *last_ptr = NULL;
struct btrfs_block_group_cache *block_group;
int full_scan = 0;
int wrapped = 0;
int empty_cluster = 2 * 1024 * 1024;
WARN_ON(num_bytes < root->sectorsize);
btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
if (data & BTRFS_BLOCK_GROUP_METADATA) {
last_ptr = &root->fs_info->last_alloc;
}
if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) {
last_ptr = &root->fs_info->last_data_alloc;
}
if (last_ptr) {
if (*last_ptr)
hint_byte = *last_ptr;
else {
empty_size += empty_cluster;
}
}
if (search_end == (u64)-1)
search_end = btrfs_super_total_bytes(&info->super_copy);
......@@ -1489,11 +1507,14 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
hint_byte = search_start;
block_group = btrfs_find_block_group(root, block_group,
hint_byte, data, 1);
if (last_ptr && *last_ptr == 0 && block_group)
hint_byte = block_group->key.objectid;
} else {
block_group = btrfs_find_block_group(root,
trans->block_group,
search_start, data, 1);
}
search_start = max(search_start, hint_byte);
total_needed += empty_size;
......@@ -1506,9 +1527,36 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
}
ret = find_search_start(root, &block_group, &search_start,
total_needed, data);
if (ret == -ENOSPC && last_ptr && *last_ptr) {
*last_ptr = 0;
block_group = btrfs_lookup_block_group(info,
orig_search_start);
search_start = orig_search_start;
ret = find_search_start(root, &block_group, &search_start,
total_needed, data);
}
if (ret == -ENOSPC)
goto enospc;
if (ret)
goto error;
if (last_ptr && *last_ptr && search_start != *last_ptr) {
*last_ptr = 0;
if (!empty_size) {
empty_size += empty_cluster;
total_needed += empty_size;
}
block_group = btrfs_lookup_block_group(info,
orig_search_start);
search_start = orig_search_start;
ret = find_search_start(root, &block_group,
&search_start, total_needed, data);
if (ret == -ENOSPC)
goto enospc;
if (ret)
goto error;
}
search_start = stripe_align(root, search_start);
ins->objectid = search_start;
ins->offset = num_bytes;
......@@ -1547,6 +1595,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
trans->block_group = block_group;
}
ins->offset = num_bytes;
if (last_ptr) {
*last_ptr = ins->objectid + ins->offset;
if (*last_ptr ==
btrfs_super_total_bytes(&root->fs_info->super_copy)) {
*last_ptr = 0;
}
}
return 0;
new_group:
......@@ -1612,12 +1667,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
if (root->ref_cows) {
if (data != BTRFS_BLOCK_GROUP_METADATA) {
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
num_bytes,
2 * 1024 * 1024,
BTRFS_BLOCK_GROUP_METADATA);
BUG_ON(ret);
}
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
num_bytes, data);
num_bytes + 2 * 1024 * 1024, data);
BUG_ON(ret);
}
......
......@@ -1730,6 +1730,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
if (bio_ret && *bio_ret) {
bio = *bio_ret;
if (bio->bi_sector + (bio->bi_size >> 9) != sector ||
(tree->ops && tree->ops->merge_bio_hook &&
tree->ops->merge_bio_hook(page, offset, size, bio)) ||
bio_add_page(bio, page, size, offset) < size) {
ret = submit_one_bio(rw, bio);
bio = NULL;
......
......@@ -29,6 +29,8 @@ struct extent_io_ops {
int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
int (*writepage_io_hook)(struct page *page, u64 start, u64 end);
int (*submit_bio_hook)(struct inode *inode, int rw, struct bio *bio);
int (*merge_bio_hook)(struct page *page, unsigned long offset,
size_t size, struct bio *bio);
int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
struct extent_state *state);
......
......@@ -296,6 +296,34 @@ int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
return 0;
}
int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
size_t size, struct bio *bio)
{
struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
struct btrfs_mapping_tree *map_tree;
struct btrfs_device *dev;
u64 logical = bio->bi_sector << 9;
u64 physical;
u64 length = 0;
u64 map_length;
struct bio_vec *bvec;
int i;
int ret;
bio_for_each_segment(bvec, bio, i) {
length += bvec->bv_len;
}
map_tree = &root->fs_info->mapping_tree;
map_length = length;
ret = btrfs_map_block(map_tree, logical, &physical, &map_length, &dev);
if (map_length < length + size) {
printk("merge bio hook logical %Lu bio len %Lu physical %Lu "
"len %Lu\n", logical, length, physical, map_length);
return 1;
}
return 0;
}
int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
......@@ -3033,6 +3061,7 @@ static struct file_operations btrfs_dir_file_operations = {
static struct extent_io_ops btrfs_extent_io_ops = {
.fill_delalloc = run_delalloc_range,
.submit_bio_hook = btrfs_submit_bio_hook,
.merge_bio_hook = btrfs_merge_bio_hook,
.readpage_io_hook = btrfs_readpage_io_hook,
.readpage_end_io_hook = btrfs_readpage_end_io_hook,
.set_bit_hook = btrfs_set_bit_hook,
......
......@@ -578,6 +578,11 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio)
map_tree = &root->fs_info->mapping_tree;
map_length = length;
ret = btrfs_map_block(map_tree, logical, &physical, &map_length, &dev);
if (map_length < length) {
printk("mapping failed logical %Lu bio len %Lu physical %Lu "
"len %Lu\n", logical, length, physical, map_length);
BUG();
}
BUG_ON(map_length < length);
bio->bi_sector = physical >> 9;
bio->bi_bdev = dev->bdev;
......
......@@ -64,4 +64,7 @@ void btrfs_mapping_init(struct btrfs_mapping_tree *tree);
void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree);
int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio);
int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf);
int btrfs_map_block(struct btrfs_mapping_tree *map_tree,
u64 logical, u64 *phys, u64 *length,
struct btrfs_device **dev);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册