aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/extent-tree.c59
-rw-r--r--fs/btrfs/extent_io.c2
-rw-r--r--fs/btrfs/extent_io.h2
-rw-r--r--fs/btrfs/inode.c29
-rw-r--r--fs/btrfs/volumes.c5
-rw-r--r--fs/btrfs/volumes.h3
8 files changed, 103 insertions, 2 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 96a493217860..acf22ad6115c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1405,6 +1405,9 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
1405 struct btrfs_root *root, struct btrfs_path *path, 1405 struct btrfs_root *root, struct btrfs_path *path,
1406 u64 isize); 1406 u64 isize);
1407/* inode.c */ 1407/* inode.c */
1408int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
1409 size_t size, struct bio *bio);
1410
1408static inline void dec_i_blocks(struct inode *inode, u64 dec) 1411static inline void dec_i_blocks(struct inode *inode, u64 dec)
1409{ 1412{
1410 dec = dec >> 9; 1413 dec = dec >> 9;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 26185d46712c..4890151cd68d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1103,4 +1103,6 @@ int btrfs_read_buffer(struct extent_buffer *buf)
1103static struct extent_io_ops btree_extent_io_ops = { 1103static struct extent_io_ops btree_extent_io_ops = {
1104 .writepage_io_hook = btree_writepage_io_hook, 1104 .writepage_io_hook = btree_writepage_io_hook,
1105 .submit_bio_hook = btree_submit_bio_hook, 1105 .submit_bio_hook = btree_submit_bio_hook,
1106 /* note we're sharing with inode.c for the merge bio hook */
1107 .merge_bio_hook = btrfs_merge_bio_hook,
1106}; 1108};
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 14eb8fc87015..e9ef644ff56f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1473,13 +1473,31 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
1473 struct btrfs_root * root = orig_root->fs_info->extent_root; 1473 struct btrfs_root * root = orig_root->fs_info->extent_root;
1474 struct btrfs_fs_info *info = root->fs_info; 1474 struct btrfs_fs_info *info = root->fs_info;
1475 u64 total_needed = num_bytes; 1475 u64 total_needed = num_bytes;
1476 u64 *last_ptr = NULL;
1476 struct btrfs_block_group_cache *block_group; 1477 struct btrfs_block_group_cache *block_group;
1477 int full_scan = 0; 1478 int full_scan = 0;
1478 int wrapped = 0; 1479 int wrapped = 0;
1480 int empty_cluster = 2 * 1024 * 1024;
1479 1481
1480 WARN_ON(num_bytes < root->sectorsize); 1482 WARN_ON(num_bytes < root->sectorsize);
1481 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); 1483 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
1482 1484
1485 if (data & BTRFS_BLOCK_GROUP_METADATA) {
1486 last_ptr = &root->fs_info->last_alloc;
1487 }
1488
1489 if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) {
1490 last_ptr = &root->fs_info->last_data_alloc;
1491 }
1492
1493 if (last_ptr) {
1494 if (*last_ptr)
1495 hint_byte = *last_ptr;
1496 else {
1497 empty_size += empty_cluster;
1498 }
1499 }
1500
1483 if (search_end == (u64)-1) 1501 if (search_end == (u64)-1)
1484 search_end = btrfs_super_total_bytes(&info->super_copy); 1502 search_end = btrfs_super_total_bytes(&info->super_copy);
1485 1503
@@ -1489,11 +1507,14 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
1489 hint_byte = search_start; 1507 hint_byte = search_start;
1490 block_group = btrfs_find_block_group(root, block_group, 1508 block_group = btrfs_find_block_group(root, block_group,
1491 hint_byte, data, 1); 1509 hint_byte, data, 1);
1510 if (last_ptr && *last_ptr == 0 && block_group)
1511 hint_byte = block_group->key.objectid;
1492 } else { 1512 } else {
1493 block_group = btrfs_find_block_group(root, 1513 block_group = btrfs_find_block_group(root,
1494 trans->block_group, 1514 trans->block_group,
1495 search_start, data, 1); 1515 search_start, data, 1);
1496 } 1516 }
1517 search_start = max(search_start, hint_byte);
1497 1518
1498 total_needed += empty_size; 1519 total_needed += empty_size;
1499 1520
@@ -1506,9 +1527,36 @@ check_failed:
1506 } 1527 }
1507 ret = find_search_start(root, &block_group, &search_start, 1528 ret = find_search_start(root, &block_group, &search_start,
1508 total_needed, data); 1529 total_needed, data);
1530 if (ret == -ENOSPC && last_ptr && *last_ptr) {
1531 *last_ptr = 0;
1532 block_group = btrfs_lookup_block_group(info,
1533 orig_search_start);
1534 search_start = orig_search_start;
1535 ret = find_search_start(root, &block_group, &search_start,
1536 total_needed, data);
1537 }
1538 if (ret == -ENOSPC)
1539 goto enospc;
1509 if (ret) 1540 if (ret)
1510 goto error; 1541 goto error;
1511 1542
1543 if (last_ptr && *last_ptr && search_start != *last_ptr) {
1544 *last_ptr = 0;
1545 if (!empty_size) {
1546 empty_size += empty_cluster;
1547 total_needed += empty_size;
1548 }
1549 block_group = btrfs_lookup_block_group(info,
1550 orig_search_start);
1551 search_start = orig_search_start;
1552 ret = find_search_start(root, &block_group,
1553 &search_start, total_needed, data);
1554 if (ret == -ENOSPC)
1555 goto enospc;
1556 if (ret)
1557 goto error;
1558 }
1559
1512 search_start = stripe_align(root, search_start); 1560 search_start = stripe_align(root, search_start);
1513 ins->objectid = search_start; 1561 ins->objectid = search_start;
1514 ins->offset = num_bytes; 1562 ins->offset = num_bytes;
@@ -1547,6 +1595,13 @@ check_failed:
1547 trans->block_group = block_group; 1595 trans->block_group = block_group;
1548 } 1596 }
1549 ins->offset = num_bytes; 1597 ins->offset = num_bytes;
1598 if (last_ptr) {
1599 *last_ptr = ins->objectid + ins->offset;
1600 if (*last_ptr ==
1601 btrfs_super_total_bytes(&root->fs_info->super_copy)) {
1602 *last_ptr = 0;
1603 }
1604 }
1550 return 0; 1605 return 0;
1551 1606
1552new_group: 1607new_group:
@@ -1612,12 +1667,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1612 if (root->ref_cows) { 1667 if (root->ref_cows) {
1613 if (data != BTRFS_BLOCK_GROUP_METADATA) { 1668 if (data != BTRFS_BLOCK_GROUP_METADATA) {
1614 ret = do_chunk_alloc(trans, root->fs_info->extent_root, 1669 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
1615 num_bytes, 1670 2 * 1024 * 1024,
1616 BTRFS_BLOCK_GROUP_METADATA); 1671 BTRFS_BLOCK_GROUP_METADATA);
1617 BUG_ON(ret); 1672 BUG_ON(ret);
1618 } 1673 }
1619 ret = do_chunk_alloc(trans, root->fs_info->extent_root, 1674 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
1620 num_bytes, data); 1675 num_bytes + 2 * 1024 * 1024, data);
1621 BUG_ON(ret); 1676 BUG_ON(ret);
1622 } 1677 }
1623 1678
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 7e3a1ebde9fc..6dab664529c1 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1730,6 +1730,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
1730 if (bio_ret && *bio_ret) { 1730 if (bio_ret && *bio_ret) {
1731 bio = *bio_ret; 1731 bio = *bio_ret;
1732 if (bio->bi_sector + (bio->bi_size >> 9) != sector || 1732 if (bio->bi_sector + (bio->bi_size >> 9) != sector ||
1733 (tree->ops && tree->ops->merge_bio_hook &&
1734 tree->ops->merge_bio_hook(page, offset, size, bio)) ||
1733 bio_add_page(bio, page, size, offset) < size) { 1735 bio_add_page(bio, page, size, offset) < size) {
1734 ret = submit_one_bio(rw, bio); 1736 ret = submit_one_bio(rw, bio);
1735 bio = NULL; 1737 bio = NULL;
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 0dca89328f98..8b5319db2516 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -29,6 +29,8 @@ struct extent_io_ops {
29 int (*fill_delalloc)(struct inode *inode, u64 start, u64 end); 29 int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
30 int (*writepage_io_hook)(struct page *page, u64 start, u64 end); 30 int (*writepage_io_hook)(struct page *page, u64 start, u64 end);
31 int (*submit_bio_hook)(struct inode *inode, int rw, struct bio *bio); 31 int (*submit_bio_hook)(struct inode *inode, int rw, struct bio *bio);
32 int (*merge_bio_hook)(struct page *page, unsigned long offset,
33 size_t size, struct bio *bio);
32 int (*readpage_io_hook)(struct page *page, u64 start, u64 end); 34 int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
33 int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end, 35 int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
34 struct extent_state *state); 36 struct extent_state *state);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 109576b57f69..5140d6801846 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -296,6 +296,34 @@ int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
296 return 0; 296 return 0;
297} 297}
298 298
299int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
300 size_t size, struct bio *bio)
301{
302 struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
303 struct btrfs_mapping_tree *map_tree;
304 struct btrfs_device *dev;
305 u64 logical = bio->bi_sector << 9;
306 u64 physical;
307 u64 length = 0;
308 u64 map_length;
309 struct bio_vec *bvec;
310 int i;
311 int ret;
312
313 bio_for_each_segment(bvec, bio, i) {
314 length += bvec->bv_len;
315 }
316 map_tree = &root->fs_info->mapping_tree;
317 map_length = length;
318 ret = btrfs_map_block(map_tree, logical, &physical, &map_length, &dev);
319 if (map_length < length + size) {
320 printk("merge bio hook logical %Lu bio len %Lu physical %Lu "
321 "len %Lu\n", logical, length, physical, map_length);
322 return 1;
323 }
324 return 0;
325}
326
299int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio) 327int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
300{ 328{
301 struct btrfs_root *root = BTRFS_I(inode)->root; 329 struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -3033,6 +3061,7 @@ static struct file_operations btrfs_dir_file_operations = {
3033static struct extent_io_ops btrfs_extent_io_ops = { 3061static struct extent_io_ops btrfs_extent_io_ops = {
3034 .fill_delalloc = run_delalloc_range, 3062 .fill_delalloc = run_delalloc_range,
3035 .submit_bio_hook = btrfs_submit_bio_hook, 3063 .submit_bio_hook = btrfs_submit_bio_hook,
3064 .merge_bio_hook = btrfs_merge_bio_hook,
3036 .readpage_io_hook = btrfs_readpage_io_hook, 3065 .readpage_io_hook = btrfs_readpage_io_hook,
3037 .readpage_end_io_hook = btrfs_readpage_end_io_hook, 3066 .readpage_end_io_hook = btrfs_readpage_end_io_hook,
3038 .set_bit_hook = btrfs_set_bit_hook, 3067 .set_bit_hook = btrfs_set_bit_hook,
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index ae22d01ecf54..16fb6bbe6e28 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -578,6 +578,11 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio)
578 map_tree = &root->fs_info->mapping_tree; 578 map_tree = &root->fs_info->mapping_tree;
579 map_length = length; 579 map_length = length;
580 ret = btrfs_map_block(map_tree, logical, &physical, &map_length, &dev); 580 ret = btrfs_map_block(map_tree, logical, &physical, &map_length, &dev);
581 if (map_length < length) {
582 printk("mapping failed logical %Lu bio len %Lu physical %Lu "
583 "len %Lu\n", logical, length, physical, map_length);
584 BUG();
585 }
581 BUG_ON(map_length < length); 586 BUG_ON(map_length < length);
582 bio->bi_sector = physical >> 9; 587 bio->bi_sector = physical >> 9;
583 bio->bi_bdev = dev->bdev; 588 bio->bi_bdev = dev->bdev;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 77fa6efd79cf..20259128152e 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -64,4 +64,7 @@ void btrfs_mapping_init(struct btrfs_mapping_tree *tree);
64void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree); 64void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree);
65int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio); 65int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio);
66int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf); 66int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf);
67int btrfs_map_block(struct btrfs_mapping_tree *map_tree,
68 u64 logical, u64 *phys, u64 *length,
69 struct btrfs_device **dev);
67#endif 70#endif