diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
| -rw-r--r-- | fs/btrfs/volumes.c | 124 |
1 files changed, 75 insertions, 49 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8a3d2594b807..e86ae04abe6a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -429,6 +429,7 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | |||
| 429 | mutex_init(&fs_devices->device_list_mutex); | 429 | mutex_init(&fs_devices->device_list_mutex); |
| 430 | fs_devices->latest_devid = orig->latest_devid; | 430 | fs_devices->latest_devid = orig->latest_devid; |
| 431 | fs_devices->latest_trans = orig->latest_trans; | 431 | fs_devices->latest_trans = orig->latest_trans; |
| 432 | fs_devices->total_devices = orig->total_devices; | ||
| 432 | memcpy(fs_devices->fsid, orig->fsid, sizeof(fs_devices->fsid)); | 433 | memcpy(fs_devices->fsid, orig->fsid, sizeof(fs_devices->fsid)); |
| 433 | 434 | ||
| 434 | /* We have held the volume lock, it is safe to get the devices. */ | 435 | /* We have held the volume lock, it is safe to get the devices. */ |
| @@ -739,6 +740,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
| 739 | int ret; | 740 | int ret; |
| 740 | u64 devid; | 741 | u64 devid; |
| 741 | u64 transid; | 742 | u64 transid; |
| 743 | u64 total_devices; | ||
| 742 | 744 | ||
| 743 | flags |= FMODE_EXCL; | 745 | flags |= FMODE_EXCL; |
| 744 | bdev = blkdev_get_by_path(path, flags, holder); | 746 | bdev = blkdev_get_by_path(path, flags, holder); |
| @@ -760,6 +762,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
| 760 | disk_super = (struct btrfs_super_block *)bh->b_data; | 762 | disk_super = (struct btrfs_super_block *)bh->b_data; |
| 761 | devid = btrfs_stack_device_id(&disk_super->dev_item); | 763 | devid = btrfs_stack_device_id(&disk_super->dev_item); |
| 762 | transid = btrfs_super_generation(disk_super); | 764 | transid = btrfs_super_generation(disk_super); |
| 765 | total_devices = btrfs_super_num_devices(disk_super); | ||
| 763 | if (disk_super->label[0]) | 766 | if (disk_super->label[0]) |
| 764 | printk(KERN_INFO "device label %s ", disk_super->label); | 767 | printk(KERN_INFO "device label %s ", disk_super->label); |
| 765 | else | 768 | else |
| @@ -767,7 +770,8 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
| 767 | printk(KERN_CONT "devid %llu transid %llu %s\n", | 770 | printk(KERN_CONT "devid %llu transid %llu %s\n", |
| 768 | (unsigned long long)devid, (unsigned long long)transid, path); | 771 | (unsigned long long)devid, (unsigned long long)transid, path); |
| 769 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); | 772 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); |
| 770 | 773 | if (!ret && fs_devices_ret) | |
| 774 | (*fs_devices_ret)->total_devices = total_devices; | ||
| 771 | brelse(bh); | 775 | brelse(bh); |
| 772 | error_close: | 776 | error_close: |
| 773 | mutex_unlock(&uuid_mutex); | 777 | mutex_unlock(&uuid_mutex); |
| @@ -1433,6 +1437,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
| 1433 | list_del_rcu(&device->dev_list); | 1437 | list_del_rcu(&device->dev_list); |
| 1434 | 1438 | ||
| 1435 | device->fs_devices->num_devices--; | 1439 | device->fs_devices->num_devices--; |
| 1440 | device->fs_devices->total_devices--; | ||
| 1436 | 1441 | ||
| 1437 | if (device->missing) | 1442 | if (device->missing) |
| 1438 | root->fs_info->fs_devices->missing_devices--; | 1443 | root->fs_info->fs_devices->missing_devices--; |
| @@ -1550,6 +1555,7 @@ static int btrfs_prepare_sprout(struct btrfs_root *root) | |||
| 1550 | fs_devices->seeding = 0; | 1555 | fs_devices->seeding = 0; |
| 1551 | fs_devices->num_devices = 0; | 1556 | fs_devices->num_devices = 0; |
| 1552 | fs_devices->open_devices = 0; | 1557 | fs_devices->open_devices = 0; |
| 1558 | fs_devices->total_devices = 0; | ||
| 1553 | fs_devices->seed = seed_devices; | 1559 | fs_devices->seed = seed_devices; |
| 1554 | 1560 | ||
| 1555 | generate_random_uuid(fs_devices->fsid); | 1561 | generate_random_uuid(fs_devices->fsid); |
| @@ -1738,10 +1744,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1738 | 1744 | ||
| 1739 | device->fs_devices = root->fs_info->fs_devices; | 1745 | device->fs_devices = root->fs_info->fs_devices; |
| 1740 | 1746 | ||
| 1741 | /* | ||
| 1742 | * we don't want write_supers to jump in here with our device | ||
| 1743 | * half setup | ||
| 1744 | */ | ||
| 1745 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | 1747 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); |
| 1746 | list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices); | 1748 | list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices); |
| 1747 | list_add(&device->dev_alloc_list, | 1749 | list_add(&device->dev_alloc_list, |
| @@ -1749,6 +1751,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1749 | root->fs_info->fs_devices->num_devices++; | 1751 | root->fs_info->fs_devices->num_devices++; |
| 1750 | root->fs_info->fs_devices->open_devices++; | 1752 | root->fs_info->fs_devices->open_devices++; |
| 1751 | root->fs_info->fs_devices->rw_devices++; | 1753 | root->fs_info->fs_devices->rw_devices++; |
| 1754 | root->fs_info->fs_devices->total_devices++; | ||
| 1752 | if (device->can_discard) | 1755 | if (device->can_discard) |
| 1753 | root->fs_info->fs_devices->num_can_discard++; | 1756 | root->fs_info->fs_devices->num_can_discard++; |
| 1754 | root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; | 1757 | root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; |
| @@ -2845,31 +2848,48 @@ out: | |||
| 2845 | 2848 | ||
| 2846 | static int balance_kthread(void *data) | 2849 | static int balance_kthread(void *data) |
| 2847 | { | 2850 | { |
| 2848 | struct btrfs_balance_control *bctl = | 2851 | struct btrfs_fs_info *fs_info = data; |
| 2849 | (struct btrfs_balance_control *)data; | ||
| 2850 | struct btrfs_fs_info *fs_info = bctl->fs_info; | ||
| 2851 | int ret = 0; | 2852 | int ret = 0; |
| 2852 | 2853 | ||
| 2853 | mutex_lock(&fs_info->volume_mutex); | 2854 | mutex_lock(&fs_info->volume_mutex); |
| 2854 | mutex_lock(&fs_info->balance_mutex); | 2855 | mutex_lock(&fs_info->balance_mutex); |
| 2855 | 2856 | ||
| 2856 | set_balance_control(bctl); | 2857 | if (fs_info->balance_ctl) { |
| 2857 | |||
| 2858 | if (btrfs_test_opt(fs_info->tree_root, SKIP_BALANCE)) { | ||
| 2859 | printk(KERN_INFO "btrfs: force skipping balance\n"); | ||
| 2860 | } else { | ||
| 2861 | printk(KERN_INFO "btrfs: continuing balance\n"); | 2858 | printk(KERN_INFO "btrfs: continuing balance\n"); |
| 2862 | ret = btrfs_balance(bctl, NULL); | 2859 | ret = btrfs_balance(fs_info->balance_ctl, NULL); |
| 2863 | } | 2860 | } |
| 2864 | 2861 | ||
| 2865 | mutex_unlock(&fs_info->balance_mutex); | 2862 | mutex_unlock(&fs_info->balance_mutex); |
| 2866 | mutex_unlock(&fs_info->volume_mutex); | 2863 | mutex_unlock(&fs_info->volume_mutex); |
| 2864 | |||
| 2867 | return ret; | 2865 | return ret; |
| 2868 | } | 2866 | } |
| 2869 | 2867 | ||
| 2870 | int btrfs_recover_balance(struct btrfs_root *tree_root) | 2868 | int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info) |
| 2871 | { | 2869 | { |
| 2872 | struct task_struct *tsk; | 2870 | struct task_struct *tsk; |
| 2871 | |||
| 2872 | spin_lock(&fs_info->balance_lock); | ||
| 2873 | if (!fs_info->balance_ctl) { | ||
| 2874 | spin_unlock(&fs_info->balance_lock); | ||
| 2875 | return 0; | ||
| 2876 | } | ||
| 2877 | spin_unlock(&fs_info->balance_lock); | ||
| 2878 | |||
| 2879 | if (btrfs_test_opt(fs_info->tree_root, SKIP_BALANCE)) { | ||
| 2880 | printk(KERN_INFO "btrfs: force skipping balance\n"); | ||
| 2881 | return 0; | ||
| 2882 | } | ||
| 2883 | |||
| 2884 | tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); | ||
| 2885 | if (IS_ERR(tsk)) | ||
| 2886 | return PTR_ERR(tsk); | ||
| 2887 | |||
| 2888 | return 0; | ||
| 2889 | } | ||
| 2890 | |||
| 2891 | int btrfs_recover_balance(struct btrfs_fs_info *fs_info) | ||
| 2892 | { | ||
| 2873 | struct btrfs_balance_control *bctl; | 2893 | struct btrfs_balance_control *bctl; |
| 2874 | struct btrfs_balance_item *item; | 2894 | struct btrfs_balance_item *item; |
| 2875 | struct btrfs_disk_balance_args disk_bargs; | 2895 | struct btrfs_disk_balance_args disk_bargs; |
| @@ -2882,29 +2902,30 @@ int btrfs_recover_balance(struct btrfs_root *tree_root) | |||
| 2882 | if (!path) | 2902 | if (!path) |
| 2883 | return -ENOMEM; | 2903 | return -ENOMEM; |
| 2884 | 2904 | ||
| 2885 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | ||
| 2886 | if (!bctl) { | ||
| 2887 | ret = -ENOMEM; | ||
| 2888 | goto out; | ||
| 2889 | } | ||
| 2890 | |||
| 2891 | key.objectid = BTRFS_BALANCE_OBJECTID; | 2905 | key.objectid = BTRFS_BALANCE_OBJECTID; |
| 2892 | key.type = BTRFS_BALANCE_ITEM_KEY; | 2906 | key.type = BTRFS_BALANCE_ITEM_KEY; |
| 2893 | key.offset = 0; | 2907 | key.offset = 0; |
| 2894 | 2908 | ||
| 2895 | ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); | 2909 | ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, path, 0, 0); |
| 2896 | if (ret < 0) | 2910 | if (ret < 0) |
| 2897 | goto out_bctl; | 2911 | goto out; |
| 2898 | if (ret > 0) { /* ret = -ENOENT; */ | 2912 | if (ret > 0) { /* ret = -ENOENT; */ |
| 2899 | ret = 0; | 2913 | ret = 0; |
| 2900 | goto out_bctl; | 2914 | goto out; |
| 2915 | } | ||
| 2916 | |||
| 2917 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | ||
| 2918 | if (!bctl) { | ||
| 2919 | ret = -ENOMEM; | ||
| 2920 | goto out; | ||
| 2901 | } | 2921 | } |
| 2902 | 2922 | ||
| 2903 | leaf = path->nodes[0]; | 2923 | leaf = path->nodes[0]; |
| 2904 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item); | 2924 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item); |
| 2905 | 2925 | ||
| 2906 | bctl->fs_info = tree_root->fs_info; | 2926 | bctl->fs_info = fs_info; |
| 2907 | bctl->flags = btrfs_balance_flags(leaf, item) | BTRFS_BALANCE_RESUME; | 2927 | bctl->flags = btrfs_balance_flags(leaf, item); |
| 2928 | bctl->flags |= BTRFS_BALANCE_RESUME; | ||
| 2908 | 2929 | ||
| 2909 | btrfs_balance_data(leaf, item, &disk_bargs); | 2930 | btrfs_balance_data(leaf, item, &disk_bargs); |
| 2910 | btrfs_disk_balance_args_to_cpu(&bctl->data, &disk_bargs); | 2931 | btrfs_disk_balance_args_to_cpu(&bctl->data, &disk_bargs); |
| @@ -2913,14 +2934,13 @@ int btrfs_recover_balance(struct btrfs_root *tree_root) | |||
| 2913 | btrfs_balance_sys(leaf, item, &disk_bargs); | 2934 | btrfs_balance_sys(leaf, item, &disk_bargs); |
| 2914 | btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); | 2935 | btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); |
| 2915 | 2936 | ||
| 2916 | tsk = kthread_run(balance_kthread, bctl, "btrfs-balance"); | 2937 | mutex_lock(&fs_info->volume_mutex); |
| 2917 | if (IS_ERR(tsk)) | 2938 | mutex_lock(&fs_info->balance_mutex); |
| 2918 | ret = PTR_ERR(tsk); | ||
| 2919 | else | ||
| 2920 | goto out; | ||
| 2921 | 2939 | ||
| 2922 | out_bctl: | 2940 | set_balance_control(bctl); |
| 2923 | kfree(bctl); | 2941 | |
| 2942 | mutex_unlock(&fs_info->balance_mutex); | ||
| 2943 | mutex_unlock(&fs_info->volume_mutex); | ||
| 2924 | out: | 2944 | out: |
| 2925 | btrfs_free_path(path); | 2945 | btrfs_free_path(path); |
| 2926 | return ret; | 2946 | return ret; |
| @@ -4061,16 +4081,18 @@ static void btrfs_end_bio(struct bio *bio, int err) | |||
| 4061 | 4081 | ||
| 4062 | BUG_ON(stripe_index >= bbio->num_stripes); | 4082 | BUG_ON(stripe_index >= bbio->num_stripes); |
| 4063 | dev = bbio->stripes[stripe_index].dev; | 4083 | dev = bbio->stripes[stripe_index].dev; |
| 4064 | if (bio->bi_rw & WRITE) | 4084 | if (dev->bdev) { |
| 4065 | btrfs_dev_stat_inc(dev, | 4085 | if (bio->bi_rw & WRITE) |
| 4066 | BTRFS_DEV_STAT_WRITE_ERRS); | 4086 | btrfs_dev_stat_inc(dev, |
| 4067 | else | 4087 | BTRFS_DEV_STAT_WRITE_ERRS); |
| 4068 | btrfs_dev_stat_inc(dev, | 4088 | else |
| 4069 | BTRFS_DEV_STAT_READ_ERRS); | 4089 | btrfs_dev_stat_inc(dev, |
| 4070 | if ((bio->bi_rw & WRITE_FLUSH) == WRITE_FLUSH) | 4090 | BTRFS_DEV_STAT_READ_ERRS); |
| 4071 | btrfs_dev_stat_inc(dev, | 4091 | if ((bio->bi_rw & WRITE_FLUSH) == WRITE_FLUSH) |
| 4072 | BTRFS_DEV_STAT_FLUSH_ERRS); | 4092 | btrfs_dev_stat_inc(dev, |
| 4073 | btrfs_dev_stat_print_on_error(dev); | 4093 | BTRFS_DEV_STAT_FLUSH_ERRS); |
| 4094 | btrfs_dev_stat_print_on_error(dev); | ||
| 4095 | } | ||
| 4074 | } | 4096 | } |
| 4075 | } | 4097 | } |
| 4076 | 4098 | ||
| @@ -4717,9 +4739,6 @@ int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info) | |||
| 4717 | key.offset = device->devid; | 4739 | key.offset = device->devid; |
| 4718 | ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0); | 4740 | ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0); |
| 4719 | if (ret) { | 4741 | if (ret) { |
| 4720 | printk_in_rcu(KERN_WARNING "btrfs: no dev_stats entry found for device %s (devid %llu) (OK on first mount after mkfs)\n", | ||
| 4721 | rcu_str_deref(device->name), | ||
| 4722 | (unsigned long long)device->devid); | ||
| 4723 | __btrfs_reset_dev_stats(device); | 4742 | __btrfs_reset_dev_stats(device); |
| 4724 | device->dev_stats_valid = 1; | 4743 | device->dev_stats_valid = 1; |
| 4725 | btrfs_release_path(path); | 4744 | btrfs_release_path(path); |
| @@ -4861,6 +4880,14 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev) | |||
| 4861 | 4880 | ||
| 4862 | static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev) | 4881 | static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev) |
| 4863 | { | 4882 | { |
| 4883 | int i; | ||
| 4884 | |||
| 4885 | for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) | ||
| 4886 | if (btrfs_dev_stat_read(dev, i) != 0) | ||
| 4887 | break; | ||
| 4888 | if (i == BTRFS_DEV_STAT_VALUES_MAX) | ||
| 4889 | return; /* all values == 0, suppress message */ | ||
| 4890 | |||
| 4864 | printk_in_rcu(KERN_INFO "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n", | 4891 | printk_in_rcu(KERN_INFO "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n", |
| 4865 | rcu_str_deref(dev->name), | 4892 | rcu_str_deref(dev->name), |
| 4866 | btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS), | 4893 | btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS), |
| @@ -4871,8 +4898,7 @@ static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev) | |||
| 4871 | } | 4898 | } |
| 4872 | 4899 | ||
| 4873 | int btrfs_get_dev_stats(struct btrfs_root *root, | 4900 | int btrfs_get_dev_stats(struct btrfs_root *root, |
| 4874 | struct btrfs_ioctl_get_dev_stats *stats, | 4901 | struct btrfs_ioctl_get_dev_stats *stats) |
| 4875 | int reset_after_read) | ||
| 4876 | { | 4902 | { |
| 4877 | struct btrfs_device *dev; | 4903 | struct btrfs_device *dev; |
| 4878 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; | 4904 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; |
| @@ -4890,7 +4916,7 @@ int btrfs_get_dev_stats(struct btrfs_root *root, | |||
| 4890 | printk(KERN_WARNING | 4916 | printk(KERN_WARNING |
| 4891 | "btrfs: get dev_stats failed, not yet valid\n"); | 4917 | "btrfs: get dev_stats failed, not yet valid\n"); |
| 4892 | return -ENODEV; | 4918 | return -ENODEV; |
| 4893 | } else if (reset_after_read) { | 4919 | } else if (stats->flags & BTRFS_DEV_STATS_RESET) { |
| 4894 | for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) { | 4920 | for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) { |
| 4895 | if (stats->nr_items > i) | 4921 | if (stats->nr_items > i) |
| 4896 | stats->values[i] = | 4922 | stats->values[i] = |
