aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@fusionio.com>2013-02-20 14:05:45 -0500
committerChris Mason <chris.mason@fusionio.com>2013-02-20 14:05:45 -0500
commitb2c6b3e0611c58fbeb6b9c0892b6249f7bdfaf6b (patch)
treede7cf0825605aa6acf33a8d107003efd7aedbe72 /fs/btrfs/volumes.c
parent19f949f52599ba7c3f67a5897ac6be14bfcb1200 (diff)
parent272d26d0ad8c0e326689f2fa3cdc6a5fcc8e74e0 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next into for-linus-3.9
Signed-off-by: Chris Mason <chris.mason@fusionio.com> Conflicts: fs/btrfs/disk-io.c
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c236
1 files changed, 179 insertions, 57 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 5cbb7f4b1672..72b1cf1b2b5e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -792,26 +792,76 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
792 return ret; 792 return ret;
793} 793}
794 794
795/*
796 * Look for a btrfs signature on a device. This may be called out of the mount path
797 * and we are not allowed to call set_blocksize during the scan. The superblock
798 * is read via pagecache
799 */
795int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, 800int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
796 struct btrfs_fs_devices **fs_devices_ret) 801 struct btrfs_fs_devices **fs_devices_ret)
797{ 802{
798 struct btrfs_super_block *disk_super; 803 struct btrfs_super_block *disk_super;
799 struct block_device *bdev; 804 struct block_device *bdev;
800 struct buffer_head *bh; 805 struct page *page;
801 int ret; 806 void *p;
807 int ret = -EINVAL;
802 u64 devid; 808 u64 devid;
803 u64 transid; 809 u64 transid;
804 u64 total_devices; 810 u64 total_devices;
811 u64 bytenr;
812 pgoff_t index;
805 813
814 /*
815 * we would like to check all the supers, but that would make
816 * a btrfs mount succeed after a mkfs from a different FS.
817 * So, we need to add a special mount option to scan for
818 * later supers, using BTRFS_SUPER_MIRROR_MAX instead
819 */
820 bytenr = btrfs_sb_offset(0);
806 flags |= FMODE_EXCL; 821 flags |= FMODE_EXCL;
807 mutex_lock(&uuid_mutex); 822 mutex_lock(&uuid_mutex);
808 ret = btrfs_get_bdev_and_sb(path, flags, holder, 0, &bdev, &bh); 823
809 if (ret) 824 bdev = blkdev_get_by_path(path, flags, holder);
825
826 if (IS_ERR(bdev)) {
827 ret = PTR_ERR(bdev);
828 printk(KERN_INFO "btrfs: open %s failed\n", path);
810 goto error; 829 goto error;
811 disk_super = (struct btrfs_super_block *)bh->b_data; 830 }
831
832 /* make sure our super fits in the device */
833 if (bytenr + PAGE_CACHE_SIZE >= i_size_read(bdev->bd_inode))
834 goto error_bdev_put;
835
836 /* make sure our super fits in the page */
837 if (sizeof(*disk_super) > PAGE_CACHE_SIZE)
838 goto error_bdev_put;
839
840 /* make sure our super doesn't straddle pages on disk */
841 index = bytenr >> PAGE_CACHE_SHIFT;
842 if ((bytenr + sizeof(*disk_super) - 1) >> PAGE_CACHE_SHIFT != index)
843 goto error_bdev_put;
844
845 /* pull in the page with our super */
846 page = read_cache_page_gfp(bdev->bd_inode->i_mapping,
847 index, GFP_NOFS);
848
849 if (IS_ERR_OR_NULL(page))
850 goto error_bdev_put;
851
852 p = kmap(page);
853
854 /* align our pointer to the offset of the super block */
855 disk_super = p + (bytenr & ~PAGE_CACHE_MASK);
856
857 if (btrfs_super_bytenr(disk_super) != bytenr ||
858 disk_super->magic != cpu_to_le64(BTRFS_MAGIC))
859 goto error_unmap;
860
812 devid = btrfs_stack_device_id(&disk_super->dev_item); 861 devid = btrfs_stack_device_id(&disk_super->dev_item);
813 transid = btrfs_super_generation(disk_super); 862 transid = btrfs_super_generation(disk_super);
814 total_devices = btrfs_super_num_devices(disk_super); 863 total_devices = btrfs_super_num_devices(disk_super);
864
815 if (disk_super->label[0]) { 865 if (disk_super->label[0]) {
816 if (disk_super->label[BTRFS_LABEL_SIZE - 1]) 866 if (disk_super->label[BTRFS_LABEL_SIZE - 1])
817 disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0'; 867 disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0';
@@ -819,12 +869,19 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
819 } else { 869 } else {
820 printk(KERN_INFO "device fsid %pU ", disk_super->fsid); 870 printk(KERN_INFO "device fsid %pU ", disk_super->fsid);
821 } 871 }
872
822 printk(KERN_CONT "devid %llu transid %llu %s\n", 873 printk(KERN_CONT "devid %llu transid %llu %s\n",
823 (unsigned long long)devid, (unsigned long long)transid, path); 874 (unsigned long long)devid, (unsigned long long)transid, path);
875
824 ret = device_list_add(path, disk_super, devid, fs_devices_ret); 876 ret = device_list_add(path, disk_super, devid, fs_devices_ret);
825 if (!ret && fs_devices_ret) 877 if (!ret && fs_devices_ret)
826 (*fs_devices_ret)->total_devices = total_devices; 878 (*fs_devices_ret)->total_devices = total_devices;
827 brelse(bh); 879
880error_unmap:
881 kunmap(page);
882 page_cache_release(page);
883
884error_bdev_put:
828 blkdev_put(bdev, flags); 885 blkdev_put(bdev, flags);
829error: 886error:
830 mutex_unlock(&uuid_mutex); 887 mutex_unlock(&uuid_mutex);
@@ -1372,14 +1429,19 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
1372 u64 devid; 1429 u64 devid;
1373 u64 num_devices; 1430 u64 num_devices;
1374 u8 *dev_uuid; 1431 u8 *dev_uuid;
1432 unsigned seq;
1375 int ret = 0; 1433 int ret = 0;
1376 bool clear_super = false; 1434 bool clear_super = false;
1377 1435
1378 mutex_lock(&uuid_mutex); 1436 mutex_lock(&uuid_mutex);
1379 1437
1380 all_avail = root->fs_info->avail_data_alloc_bits | 1438 do {
1381 root->fs_info->avail_system_alloc_bits | 1439 seq = read_seqbegin(&root->fs_info->profiles_lock);
1382 root->fs_info->avail_metadata_alloc_bits; 1440
1441 all_avail = root->fs_info->avail_data_alloc_bits |
1442 root->fs_info->avail_system_alloc_bits |
1443 root->fs_info->avail_metadata_alloc_bits;
1444 } while (read_seqretry(&root->fs_info->profiles_lock, seq));
1383 1445
1384 num_devices = root->fs_info->fs_devices->num_devices; 1446 num_devices = root->fs_info->fs_devices->num_devices;
1385 btrfs_dev_replace_lock(&root->fs_info->dev_replace); 1447 btrfs_dev_replace_lock(&root->fs_info->dev_replace);
@@ -2616,7 +2678,7 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
2616 chunk_used = btrfs_block_group_used(&cache->item); 2678 chunk_used = btrfs_block_group_used(&cache->item);
2617 2679
2618 if (bargs->usage == 0) 2680 if (bargs->usage == 0)
2619 user_thresh = 0; 2681 user_thresh = 1;
2620 else if (bargs->usage > 100) 2682 else if (bargs->usage > 100)
2621 user_thresh = cache->key.offset; 2683 user_thresh = cache->key.offset;
2622 else 2684 else
@@ -2985,6 +3047,7 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
2985 int mixed = 0; 3047 int mixed = 0;
2986 int ret; 3048 int ret;
2987 u64 num_devices; 3049 u64 num_devices;
3050 unsigned seq;
2988 3051
2989 if (btrfs_fs_closing(fs_info) || 3052 if (btrfs_fs_closing(fs_info) ||
2990 atomic_read(&fs_info->balance_pause_req) || 3053 atomic_read(&fs_info->balance_pause_req) ||
@@ -3068,22 +3131,26 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
3068 /* allow to reduce meta or sys integrity only if force set */ 3131 /* allow to reduce meta or sys integrity only if force set */
3069 allowed = BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 | 3132 allowed = BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 |
3070 BTRFS_BLOCK_GROUP_RAID10; 3133 BTRFS_BLOCK_GROUP_RAID10;
3071 if (((bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) && 3134 do {
3072 (fs_info->avail_system_alloc_bits & allowed) && 3135 seq = read_seqbegin(&fs_info->profiles_lock);
3073 !(bctl->sys.target & allowed)) || 3136
3074 ((bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) && 3137 if (((bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
3075 (fs_info->avail_metadata_alloc_bits & allowed) && 3138 (fs_info->avail_system_alloc_bits & allowed) &&
3076 !(bctl->meta.target & allowed))) { 3139 !(bctl->sys.target & allowed)) ||
3077 if (bctl->flags & BTRFS_BALANCE_FORCE) { 3140 ((bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
3078 printk(KERN_INFO "btrfs: force reducing metadata " 3141 (fs_info->avail_metadata_alloc_bits & allowed) &&
3079 "integrity\n"); 3142 !(bctl->meta.target & allowed))) {
3080 } else { 3143 if (bctl->flags & BTRFS_BALANCE_FORCE) {
3081 printk(KERN_ERR "btrfs: balance will reduce metadata " 3144 printk(KERN_INFO "btrfs: force reducing metadata "
3082 "integrity, use force if you want this\n"); 3145 "integrity\n");
3083 ret = -EINVAL; 3146 } else {
3084 goto out; 3147 printk(KERN_ERR "btrfs: balance will reduce metadata "
3148 "integrity, use force if you want this\n");
3149 ret = -EINVAL;
3150 goto out;
3151 }
3085 } 3152 }
3086 } 3153 } while (read_seqretry(&fs_info->profiles_lock, seq));
3087 3154
3088 if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) { 3155 if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
3089 int num_tolerated_disk_barrier_failures; 3156 int num_tolerated_disk_barrier_failures;
@@ -3127,6 +3194,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
3127 mutex_lock(&fs_info->balance_mutex); 3194 mutex_lock(&fs_info->balance_mutex);
3128 atomic_dec(&fs_info->balance_running); 3195 atomic_dec(&fs_info->balance_running);
3129 3196
3197 if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
3198 fs_info->num_tolerated_disk_barrier_failures =
3199 btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
3200 }
3201
3130 if (bargs) { 3202 if (bargs) {
3131 memset(bargs, 0, sizeof(*bargs)); 3203 memset(bargs, 0, sizeof(*bargs));
3132 update_ioctl_balance_args(fs_info, 0, bargs); 3204 update_ioctl_balance_args(fs_info, 0, bargs);
@@ -3137,11 +3209,6 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
3137 __cancel_balance(fs_info); 3209 __cancel_balance(fs_info);
3138 } 3210 }
3139 3211
3140 if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
3141 fs_info->num_tolerated_disk_barrier_failures =
3142 btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
3143 }
3144
3145 wake_up(&fs_info->balance_wait_q); 3212 wake_up(&fs_info->balance_wait_q);
3146 3213
3147 return ret; 3214 return ret;
@@ -3504,13 +3571,48 @@ static int btrfs_cmp_device_info(const void *a, const void *b)
3504} 3571}
3505 3572
3506struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { 3573struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
3507 { 2, 1, 0, 4, 2, 2 /* raid10 */ }, 3574 [BTRFS_RAID_RAID10] = {
3508 { 1, 1, 2, 2, 2, 2 /* raid1 */ }, 3575 .sub_stripes = 2,
3509 { 1, 2, 1, 1, 1, 2 /* dup */ }, 3576 .dev_stripes = 1,
3510 { 1, 1, 0, 2, 1, 1 /* raid0 */ }, 3577 .devs_max = 0, /* 0 == as many as possible */
3511 { 1, 1, 1, 1, 1, 1 /* single */ }, 3578 .devs_min = 4,
3579 .devs_increment = 2,
3580 .ncopies = 2,
3581 },
3582 [BTRFS_RAID_RAID1] = {
3583 .sub_stripes = 1,
3584 .dev_stripes = 1,
3585 .devs_max = 2,
3586 .devs_min = 2,
3587 .devs_increment = 2,
3588 .ncopies = 2,
3589 },
3590 [BTRFS_RAID_DUP] = {
3591 .sub_stripes = 1,
3592 .dev_stripes = 2,
3593 .devs_max = 1,
3594 .devs_min = 1,
3595 .devs_increment = 1,
3596 .ncopies = 2,
3597 },
3598 [BTRFS_RAID_RAID0] = {
3599 .sub_stripes = 1,
3600 .dev_stripes = 1,
3601 .devs_max = 0,
3602 .devs_min = 2,
3603 .devs_increment = 1,
3604 .ncopies = 1,
3605 },
3606 [BTRFS_RAID_SINGLE] = {
3607 .sub_stripes = 1,
3608 .dev_stripes = 1,
3609 .devs_max = 1,
3610 .devs_min = 1,
3611 .devs_increment = 1,
3612 .ncopies = 1,
3613 },
3512}; 3614};
3513 3615
3514static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, 3616static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3515 struct btrfs_root *extent_root, 3617 struct btrfs_root *extent_root,
3516 struct map_lookup **map_ret, 3618 struct map_lookup **map_ret,
@@ -3631,12 +3733,16 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3631 if (max_avail < BTRFS_STRIPE_LEN * dev_stripes) 3733 if (max_avail < BTRFS_STRIPE_LEN * dev_stripes)
3632 continue; 3734 continue;
3633 3735
3736 if (ndevs == fs_devices->rw_devices) {
3737 WARN(1, "%s: found more than %llu devices\n",
3738 __func__, fs_devices->rw_devices);
3739 break;
3740 }
3634 devices_info[ndevs].dev_offset = dev_offset; 3741 devices_info[ndevs].dev_offset = dev_offset;
3635 devices_info[ndevs].max_avail = max_avail; 3742 devices_info[ndevs].max_avail = max_avail;
3636 devices_info[ndevs].total_avail = total_avail; 3743 devices_info[ndevs].total_avail = total_avail;
3637 devices_info[ndevs].dev = device; 3744 devices_info[ndevs].dev = device;
3638 ++ndevs; 3745 ++ndevs;
3639 WARN_ON(ndevs > fs_devices->rw_devices);
3640 } 3746 }
3641 3747
3642 /* 3748 /*
@@ -3718,15 +3824,10 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3718 write_lock(&em_tree->lock); 3824 write_lock(&em_tree->lock);
3719 ret = add_extent_mapping(em_tree, em); 3825 ret = add_extent_mapping(em_tree, em);
3720 write_unlock(&em_tree->lock); 3826 write_unlock(&em_tree->lock);
3721 free_extent_map(em); 3827 if (ret) {
3722 if (ret) 3828 free_extent_map(em);
3723 goto error;
3724
3725 ret = btrfs_make_block_group(trans, extent_root, 0, type,
3726 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3727 start, num_bytes);
3728 if (ret)
3729 goto error; 3829 goto error;
3830 }
3730 3831
3731 for (i = 0; i < map->num_stripes; ++i) { 3832 for (i = 0; i < map->num_stripes; ++i) {
3732 struct btrfs_device *device; 3833 struct btrfs_device *device;
@@ -3739,15 +3840,42 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3739 info->chunk_root->root_key.objectid, 3840 info->chunk_root->root_key.objectid,
3740 BTRFS_FIRST_CHUNK_TREE_OBJECTID, 3841 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3741 start, dev_offset, stripe_size); 3842 start, dev_offset, stripe_size);
3742 if (ret) { 3843 if (ret)
3743 btrfs_abort_transaction(trans, extent_root, ret); 3844 goto error_dev_extent;
3744 goto error;
3745 }
3746 } 3845 }
3747 3846
3847 ret = btrfs_make_block_group(trans, extent_root, 0, type,
3848 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3849 start, num_bytes);
3850 if (ret) {
3851 i = map->num_stripes - 1;
3852 goto error_dev_extent;
3853 }
3854
3855 free_extent_map(em);
3748 kfree(devices_info); 3856 kfree(devices_info);
3749 return 0; 3857 return 0;
3750 3858
3859error_dev_extent:
3860 for (; i >= 0; i--) {
3861 struct btrfs_device *device;
3862 int err;
3863
3864 device = map->stripes[i].dev;
3865 err = btrfs_free_dev_extent(trans, device, start);
3866 if (err) {
3867 btrfs_abort_transaction(trans, extent_root, err);
3868 break;
3869 }
3870 }
3871 write_lock(&em_tree->lock);
3872 remove_extent_mapping(em_tree, em);
3873 write_unlock(&em_tree->lock);
3874
3875 /* One for our allocation */
3876 free_extent_map(em);
3877 /* One for the tree reference */
3878 free_extent_map(em);
3751error: 3879error:
3752 kfree(map); 3880 kfree(map);
3753 kfree(devices_info); 3881 kfree(devices_info);
@@ -3887,10 +4015,7 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
3887 if (ret) 4015 if (ret)
3888 return ret; 4016 return ret;
3889 4017
3890 alloc_profile = BTRFS_BLOCK_GROUP_METADATA | 4018 alloc_profile = btrfs_get_alloc_profile(extent_root, 0);
3891 fs_info->avail_metadata_alloc_bits;
3892 alloc_profile = btrfs_reduce_alloc_profile(root, alloc_profile);
3893
3894 ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size, 4019 ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size,
3895 &stripe_size, chunk_offset, alloc_profile); 4020 &stripe_size, chunk_offset, alloc_profile);
3896 if (ret) 4021 if (ret)
@@ -3898,10 +4023,7 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
3898 4023
3899 sys_chunk_offset = chunk_offset + chunk_size; 4024 sys_chunk_offset = chunk_offset + chunk_size;
3900 4025
3901 alloc_profile = BTRFS_BLOCK_GROUP_SYSTEM | 4026 alloc_profile = btrfs_get_alloc_profile(fs_info->chunk_root, 0);
3902 fs_info->avail_system_alloc_bits;
3903 alloc_profile = btrfs_reduce_alloc_profile(root, alloc_profile);
3904
3905 ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map, 4027 ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map,
3906 &sys_chunk_size, &sys_stripe_size, 4028 &sys_chunk_size, &sys_stripe_size,
3907 sys_chunk_offset, alloc_profile); 4029 sys_chunk_offset, alloc_profile);