forked from Minki/linux
Btrfs: Bring back mount -o ssd optimizations
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
0d81ba5dbe
commit
239b14b32d
@ -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 @@ check_failed:
|
||||
}
|
||||
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 @@ check_failed:
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user