diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 974be09e7556..e99ccd6ffb2c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "locking.h" | 42 | #include "locking.h" |
43 | #include "tree-log.h" | 43 | #include "tree-log.h" |
44 | #include "free-space-cache.h" | 44 | #include "free-space-cache.h" |
45 | #include "free-space-tree.h" | ||
45 | #include "inode-map.h" | 46 | #include "inode-map.h" |
46 | #include "check-integrity.h" | 47 | #include "check-integrity.h" |
47 | #include "rcu-string.h" | 48 | #include "rcu-string.h" |
@@ -362,7 +363,7 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
362 | } | 363 | } |
363 | 364 | ||
364 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, | 365 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
365 | 0, &cached_state); | 366 | &cached_state); |
366 | if (extent_buffer_uptodate(eb) && | 367 | if (extent_buffer_uptodate(eb) && |
367 | btrfs_header_generation(eb) == parent_transid) { | 368 | btrfs_header_generation(eb) == parent_transid) { |
368 | ret = 0; | 369 | ret = 0; |
@@ -923,7 +924,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags) | |||
923 | if (bio_flags & EXTENT_BIO_TREE_LOG) | 924 | if (bio_flags & EXTENT_BIO_TREE_LOG) |
924 | return 0; | 925 | return 0; |
925 | #ifdef CONFIG_X86 | 926 | #ifdef CONFIG_X86 |
926 | if (cpu_has_xmm4_2) | 927 | if (static_cpu_has_safe(X86_FEATURE_XMM4_2)) |
927 | return 0; | 928 | return 0; |
928 | #endif | 929 | #endif |
929 | return 1; | 930 | return 1; |
@@ -1650,6 +1651,9 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info, | |||
1650 | if (location->objectid == BTRFS_UUID_TREE_OBJECTID) | 1651 | if (location->objectid == BTRFS_UUID_TREE_OBJECTID) |
1651 | return fs_info->uuid_root ? fs_info->uuid_root : | 1652 | return fs_info->uuid_root ? fs_info->uuid_root : |
1652 | ERR_PTR(-ENOENT); | 1653 | ERR_PTR(-ENOENT); |
1654 | if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID) | ||
1655 | return fs_info->free_space_root ? fs_info->free_space_root : | ||
1656 | ERR_PTR(-ENOENT); | ||
1653 | again: | 1657 | again: |
1654 | root = btrfs_lookup_fs_root(fs_info, location->objectid); | 1658 | root = btrfs_lookup_fs_root(fs_info, location->objectid); |
1655 | if (root) { | 1659 | if (root) { |
@@ -2148,6 +2152,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root) | |||
2148 | free_root_extent_buffers(info->uuid_root); | 2152 | free_root_extent_buffers(info->uuid_root); |
2149 | if (chunk_root) | 2153 | if (chunk_root) |
2150 | free_root_extent_buffers(info->chunk_root); | 2154 | free_root_extent_buffers(info->chunk_root); |
2155 | free_root_extent_buffers(info->free_space_root); | ||
2151 | } | 2156 | } |
2152 | 2157 | ||
2153 | void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info) | 2158 | void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info) |
@@ -2448,6 +2453,15 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info, | |||
2448 | fs_info->uuid_root = root; | 2453 | fs_info->uuid_root = root; |
2449 | } | 2454 | } |
2450 | 2455 | ||
2456 | if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { | ||
2457 | location.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID; | ||
2458 | root = btrfs_read_tree_root(tree_root, &location); | ||
2459 | if (IS_ERR(root)) | ||
2460 | return PTR_ERR(root); | ||
2461 | set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state); | ||
2462 | fs_info->free_space_root = root; | ||
2463 | } | ||
2464 | |||
2451 | return 0; | 2465 | return 0; |
2452 | } | 2466 | } |
2453 | 2467 | ||
@@ -2668,6 +2682,7 @@ int open_ctree(struct super_block *sb, | |||
2668 | if (btrfs_check_super_csum(bh->b_data)) { | 2682 | if (btrfs_check_super_csum(bh->b_data)) { |
2669 | printk(KERN_ERR "BTRFS: superblock checksum mismatch\n"); | 2683 | printk(KERN_ERR "BTRFS: superblock checksum mismatch\n"); |
2670 | err = -EINVAL; | 2684 | err = -EINVAL; |
2685 | brelse(bh); | ||
2671 | goto fail_alloc; | 2686 | goto fail_alloc; |
2672 | } | 2687 | } |
2673 | 2688 | ||
@@ -2809,7 +2824,7 @@ int open_ctree(struct super_block *sb, | |||
2809 | 2824 | ||
2810 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); | 2825 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); |
2811 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, | 2826 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, |
2812 | 4 * 1024 * 1024 / PAGE_CACHE_SIZE); | 2827 | SZ_4M / PAGE_CACHE_SIZE); |
2813 | 2828 | ||
2814 | tree_root->nodesize = nodesize; | 2829 | tree_root->nodesize = nodesize; |
2815 | tree_root->sectorsize = sectorsize; | 2830 | tree_root->sectorsize = sectorsize; |
@@ -3051,6 +3066,18 @@ retry_root_backup: | |||
3051 | if (sb->s_flags & MS_RDONLY) | 3066 | if (sb->s_flags & MS_RDONLY) |
3052 | return 0; | 3067 | return 0; |
3053 | 3068 | ||
3069 | if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) && | ||
3070 | !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { | ||
3071 | pr_info("BTRFS: creating free space tree\n"); | ||
3072 | ret = btrfs_create_free_space_tree(fs_info); | ||
3073 | if (ret) { | ||
3074 | pr_warn("BTRFS: failed to create free space tree %d\n", | ||
3075 | ret); | ||
3076 | close_ctree(tree_root); | ||
3077 | return ret; | ||
3078 | } | ||
3079 | } | ||
3080 | |||
3054 | down_read(&fs_info->cleanup_work_sem); | 3081 | down_read(&fs_info->cleanup_work_sem); |
3055 | if ((ret = btrfs_orphan_cleanup(fs_info->fs_root)) || | 3082 | if ((ret = btrfs_orphan_cleanup(fs_info->fs_root)) || |
3056 | (ret = btrfs_orphan_cleanup(fs_info->tree_root))) { | 3083 | (ret = btrfs_orphan_cleanup(fs_info->tree_root))) { |
@@ -3076,6 +3103,18 @@ retry_root_backup: | |||
3076 | 3103 | ||
3077 | btrfs_qgroup_rescan_resume(fs_info); | 3104 | btrfs_qgroup_rescan_resume(fs_info); |
3078 | 3105 | ||
3106 | if (btrfs_test_opt(tree_root, CLEAR_CACHE) && | ||
3107 | btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { | ||
3108 | pr_info("BTRFS: clearing free space tree\n"); | ||
3109 | ret = btrfs_clear_free_space_tree(fs_info); | ||
3110 | if (ret) { | ||
3111 | pr_warn("BTRFS: failed to clear free space tree %d\n", | ||
3112 | ret); | ||
3113 | close_ctree(tree_root); | ||
3114 | return ret; | ||
3115 | } | ||
3116 | } | ||
3117 | |||
3079 | if (!fs_info->uuid_root) { | 3118 | if (!fs_info->uuid_root) { |
3080 | pr_info("BTRFS: creating UUID tree\n"); | 3119 | pr_info("BTRFS: creating UUID tree\n"); |
3081 | ret = btrfs_create_uuid_tree(fs_info); | 3120 | ret = btrfs_create_uuid_tree(fs_info); |
@@ -3902,11 +3941,6 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, | |||
3902 | return !ret; | 3941 | return !ret; |
3903 | } | 3942 | } |
3904 | 3943 | ||
3905 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf) | ||
3906 | { | ||
3907 | return set_extent_buffer_uptodate(buf); | ||
3908 | } | ||
3909 | |||
3910 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf) | 3944 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf) |
3911 | { | 3945 | { |
3912 | struct btrfs_root *root; | 3946 | struct btrfs_root *root; |
@@ -3962,7 +3996,6 @@ static void __btrfs_btree_balance_dirty(struct btrfs_root *root, | |||
3962 | balance_dirty_pages_ratelimited( | 3996 | balance_dirty_pages_ratelimited( |
3963 | root->fs_info->btree_inode->i_mapping); | 3997 | root->fs_info->btree_inode->i_mapping); |
3964 | } | 3998 | } |
3965 | return; | ||
3966 | } | 3999 | } |
3967 | 4000 | ||
3968 | void btrfs_btree_balance_dirty(struct btrfs_root *root) | 4001 | void btrfs_btree_balance_dirty(struct btrfs_root *root) |