diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 5 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 109 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 8 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 7 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 30 |
6 files changed, 142 insertions, 19 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 50dcd0fbae11..1630be831210 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1468,6 +1468,8 @@ struct btrfs_fs_info { | |||
1468 | 1468 | ||
1469 | /* next backup root to be overwritten */ | 1469 | /* next backup root to be overwritten */ |
1470 | int backup_root_index; | 1470 | int backup_root_index; |
1471 | |||
1472 | int num_tolerated_disk_barrier_failures; | ||
1471 | }; | 1473 | }; |
1472 | 1474 | ||
1473 | /* | 1475 | /* |
@@ -3361,6 +3363,9 @@ void btrfs_inherit_iflags(struct inode *inode, struct inode *dir); | |||
3361 | int btrfs_defrag_file(struct inode *inode, struct file *file, | 3363 | int btrfs_defrag_file(struct inode *inode, struct file *file, |
3362 | struct btrfs_ioctl_defrag_range_args *range, | 3364 | struct btrfs_ioctl_defrag_range_args *range, |
3363 | u64 newer_than, unsigned long max_pages); | 3365 | u64 newer_than, unsigned long max_pages); |
3366 | void btrfs_get_block_group_info(struct list_head *groups_list, | ||
3367 | struct btrfs_ioctl_space_info *space); | ||
3368 | |||
3364 | /* file.c */ | 3369 | /* file.c */ |
3365 | int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, | 3370 | int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, |
3366 | struct inode *inode); | 3371 | struct inode *inode); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c69995556f61..835523687707 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2505,6 +2505,8 @@ retry_root_backup: | |||
2505 | printk(KERN_ERR "Failed to read block groups: %d\n", ret); | 2505 | printk(KERN_ERR "Failed to read block groups: %d\n", ret); |
2506 | goto fail_block_groups; | 2506 | goto fail_block_groups; |
2507 | } | 2507 | } |
2508 | fs_info->num_tolerated_disk_barrier_failures = | ||
2509 | btrfs_calc_num_tolerated_disk_barrier_failures(fs_info); | ||
2508 | 2510 | ||
2509 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, | 2511 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, |
2510 | "btrfs-cleaner"); | 2512 | "btrfs-cleaner"); |
@@ -2888,12 +2890,10 @@ static int write_dev_flush(struct btrfs_device *device, int wait) | |||
2888 | printk_in_rcu("btrfs: disabling barriers on dev %s\n", | 2890 | printk_in_rcu("btrfs: disabling barriers on dev %s\n", |
2889 | rcu_str_deref(device->name)); | 2891 | rcu_str_deref(device->name)); |
2890 | device->nobarriers = 1; | 2892 | device->nobarriers = 1; |
2891 | } | 2893 | } else if (!bio_flagged(bio, BIO_UPTODATE)) { |
2892 | if (!bio_flagged(bio, BIO_UPTODATE)) { | ||
2893 | ret = -EIO; | 2894 | ret = -EIO; |
2894 | if (!bio_flagged(bio, BIO_EOPNOTSUPP)) | 2895 | btrfs_dev_stat_inc_and_print(device, |
2895 | btrfs_dev_stat_inc_and_print(device, | 2896 | BTRFS_DEV_STAT_FLUSH_ERRS); |
2896 | BTRFS_DEV_STAT_FLUSH_ERRS); | ||
2897 | } | 2897 | } |
2898 | 2898 | ||
2899 | /* drop the reference from the wait == 0 run */ | 2899 | /* drop the reference from the wait == 0 run */ |
@@ -2932,14 +2932,15 @@ static int barrier_all_devices(struct btrfs_fs_info *info) | |||
2932 | { | 2932 | { |
2933 | struct list_head *head; | 2933 | struct list_head *head; |
2934 | struct btrfs_device *dev; | 2934 | struct btrfs_device *dev; |
2935 | int errors = 0; | 2935 | int errors_send = 0; |
2936 | int errors_wait = 0; | ||
2936 | int ret; | 2937 | int ret; |
2937 | 2938 | ||
2938 | /* send down all the barriers */ | 2939 | /* send down all the barriers */ |
2939 | head = &info->fs_devices->devices; | 2940 | head = &info->fs_devices->devices; |
2940 | list_for_each_entry_rcu(dev, head, dev_list) { | 2941 | list_for_each_entry_rcu(dev, head, dev_list) { |
2941 | if (!dev->bdev) { | 2942 | if (!dev->bdev) { |
2942 | errors++; | 2943 | errors_send++; |
2943 | continue; | 2944 | continue; |
2944 | } | 2945 | } |
2945 | if (!dev->in_fs_metadata || !dev->writeable) | 2946 | if (!dev->in_fs_metadata || !dev->writeable) |
@@ -2947,13 +2948,13 @@ static int barrier_all_devices(struct btrfs_fs_info *info) | |||
2947 | 2948 | ||
2948 | ret = write_dev_flush(dev, 0); | 2949 | ret = write_dev_flush(dev, 0); |
2949 | if (ret) | 2950 | if (ret) |
2950 | errors++; | 2951 | errors_send++; |
2951 | } | 2952 | } |
2952 | 2953 | ||
2953 | /* wait for all the barriers */ | 2954 | /* wait for all the barriers */ |
2954 | list_for_each_entry_rcu(dev, head, dev_list) { | 2955 | list_for_each_entry_rcu(dev, head, dev_list) { |
2955 | if (!dev->bdev) { | 2956 | if (!dev->bdev) { |
2956 | errors++; | 2957 | errors_wait++; |
2957 | continue; | 2958 | continue; |
2958 | } | 2959 | } |
2959 | if (!dev->in_fs_metadata || !dev->writeable) | 2960 | if (!dev->in_fs_metadata || !dev->writeable) |
@@ -2961,13 +2962,87 @@ static int barrier_all_devices(struct btrfs_fs_info *info) | |||
2961 | 2962 | ||
2962 | ret = write_dev_flush(dev, 1); | 2963 | ret = write_dev_flush(dev, 1); |
2963 | if (ret) | 2964 | if (ret) |
2964 | errors++; | 2965 | errors_wait++; |
2965 | } | 2966 | } |
2966 | if (errors) | 2967 | if (errors_send > info->num_tolerated_disk_barrier_failures || |
2968 | errors_wait > info->num_tolerated_disk_barrier_failures) | ||
2967 | return -EIO; | 2969 | return -EIO; |
2968 | return 0; | 2970 | return 0; |
2969 | } | 2971 | } |
2970 | 2972 | ||
2973 | int btrfs_calc_num_tolerated_disk_barrier_failures( | ||
2974 | struct btrfs_fs_info *fs_info) | ||
2975 | { | ||
2976 | struct btrfs_ioctl_space_info space; | ||
2977 | struct btrfs_space_info *sinfo; | ||
2978 | u64 types[] = {BTRFS_BLOCK_GROUP_DATA, | ||
2979 | BTRFS_BLOCK_GROUP_SYSTEM, | ||
2980 | BTRFS_BLOCK_GROUP_METADATA, | ||
2981 | BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA}; | ||
2982 | int num_types = 4; | ||
2983 | int i; | ||
2984 | int c; | ||
2985 | int num_tolerated_disk_barrier_failures = | ||
2986 | (int)fs_info->fs_devices->num_devices; | ||
2987 | |||
2988 | for (i = 0; i < num_types; i++) { | ||
2989 | struct btrfs_space_info *tmp; | ||
2990 | |||
2991 | sinfo = NULL; | ||
2992 | rcu_read_lock(); | ||
2993 | list_for_each_entry_rcu(tmp, &fs_info->space_info, list) { | ||
2994 | if (tmp->flags == types[i]) { | ||
2995 | sinfo = tmp; | ||
2996 | break; | ||
2997 | } | ||
2998 | } | ||
2999 | rcu_read_unlock(); | ||
3000 | |||
3001 | if (!sinfo) | ||
3002 | continue; | ||
3003 | |||
3004 | down_read(&sinfo->groups_sem); | ||
3005 | for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) { | ||
3006 | if (!list_empty(&sinfo->block_groups[c])) { | ||
3007 | u64 flags; | ||
3008 | |||
3009 | btrfs_get_block_group_info( | ||
3010 | &sinfo->block_groups[c], &space); | ||
3011 | if (space.total_bytes == 0 || | ||
3012 | space.used_bytes == 0) | ||
3013 | continue; | ||
3014 | flags = space.flags; | ||
3015 | /* | ||
3016 | * return | ||
3017 | * 0: if dup, single or RAID0 is configured for | ||
3018 | * any of metadata, system or data, else | ||
3019 | * 1: if RAID5 is configured, or if RAID1 or | ||
3020 | * RAID10 is configured and only two mirrors | ||
3021 | * are used, else | ||
3022 | * 2: if RAID6 is configured, else | ||
3023 | * num_mirrors - 1: if RAID1 or RAID10 is | ||
3024 | * configured and more than | ||
3025 | * 2 mirrors are used. | ||
3026 | */ | ||
3027 | if (num_tolerated_disk_barrier_failures > 0 && | ||
3028 | ((flags & (BTRFS_BLOCK_GROUP_DUP | | ||
3029 | BTRFS_BLOCK_GROUP_RAID0)) || | ||
3030 | ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) | ||
3031 | == 0))) | ||
3032 | num_tolerated_disk_barrier_failures = 0; | ||
3033 | else if (num_tolerated_disk_barrier_failures > 1 | ||
3034 | && | ||
3035 | (flags & (BTRFS_BLOCK_GROUP_RAID1 | | ||
3036 | BTRFS_BLOCK_GROUP_RAID10))) | ||
3037 | num_tolerated_disk_barrier_failures = 1; | ||
3038 | } | ||
3039 | } | ||
3040 | up_read(&sinfo->groups_sem); | ||
3041 | } | ||
3042 | |||
3043 | return num_tolerated_disk_barrier_failures; | ||
3044 | } | ||
3045 | |||
2971 | int write_all_supers(struct btrfs_root *root, int max_mirrors) | 3046 | int write_all_supers(struct btrfs_root *root, int max_mirrors) |
2972 | { | 3047 | { |
2973 | struct list_head *head; | 3048 | struct list_head *head; |
@@ -2990,8 +3065,16 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors) | |||
2990 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | 3065 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); |
2991 | head = &root->fs_info->fs_devices->devices; | 3066 | head = &root->fs_info->fs_devices->devices; |
2992 | 3067 | ||
2993 | if (do_barriers) | 3068 | if (do_barriers) { |
2994 | barrier_all_devices(root->fs_info); | 3069 | ret = barrier_all_devices(root->fs_info); |
3070 | if (ret) { | ||
3071 | mutex_unlock( | ||
3072 | &root->fs_info->fs_devices->device_list_mutex); | ||
3073 | btrfs_error(root->fs_info, ret, | ||
3074 | "errors while submitting device barriers."); | ||
3075 | return ret; | ||
3076 | } | ||
3077 | } | ||
2995 | 3078 | ||
2996 | list_for_each_entry_rcu(dev, head, dev_list) { | 3079 | list_for_each_entry_rcu(dev, head, dev_list) { |
2997 | if (!dev->bdev) { | 3080 | if (!dev->bdev) { |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index c5b00a735fef..2025a9132c16 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -95,6 +95,8 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, | |||
95 | u64 objectid); | 95 | u64 objectid); |
96 | int btree_lock_page_hook(struct page *page, void *data, | 96 | int btree_lock_page_hook(struct page *page, void *data, |
97 | void (*flush_fn)(void *)); | 97 | void (*flush_fn)(void *)); |
98 | int btrfs_calc_num_tolerated_disk_barrier_failures( | ||
99 | struct btrfs_fs_info *fs_info); | ||
98 | 100 | ||
99 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 101 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
100 | void btrfs_init_lockdep(void); | 102 | void btrfs_init_lockdep(void); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index d6836af6d60f..f5a2e6c4320a 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -2875,8 +2875,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
2875 | return 0; | 2875 | return 0; |
2876 | } | 2876 | } |
2877 | 2877 | ||
2878 | static void get_block_group_info(struct list_head *groups_list, | 2878 | void btrfs_get_block_group_info(struct list_head *groups_list, |
2879 | struct btrfs_ioctl_space_info *space) | 2879 | struct btrfs_ioctl_space_info *space) |
2880 | { | 2880 | { |
2881 | struct btrfs_block_group_cache *block_group; | 2881 | struct btrfs_block_group_cache *block_group; |
2882 | 2882 | ||
@@ -2984,8 +2984,8 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2984 | down_read(&info->groups_sem); | 2984 | down_read(&info->groups_sem); |
2985 | for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) { | 2985 | for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) { |
2986 | if (!list_empty(&info->block_groups[c])) { | 2986 | if (!list_empty(&info->block_groups[c])) { |
2987 | get_block_group_info(&info->block_groups[c], | 2987 | btrfs_get_block_group_info( |
2988 | &space); | 2988 | &info->block_groups[c], &space); |
2989 | memcpy(dest, &space, sizeof(space)); | 2989 | memcpy(dest, &space, sizeof(space)); |
2990 | dest++; | 2990 | dest++; |
2991 | space_args.total_spaces++; | 2991 | space_args.total_spaces++; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 47911fd18310..67eab2d4d8a9 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2425,9 +2425,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2425 | * in and cause problems either. | 2425 | * in and cause problems either. |
2426 | */ | 2426 | */ |
2427 | btrfs_scrub_pause_super(root); | 2427 | btrfs_scrub_pause_super(root); |
2428 | write_ctree_super(trans, root->fs_info->tree_root, 1); | 2428 | ret = write_ctree_super(trans, root->fs_info->tree_root, 1); |
2429 | btrfs_scrub_continue_super(root); | 2429 | btrfs_scrub_continue_super(root); |
2430 | ret = 0; | 2430 | if (ret) { |
2431 | btrfs_abort_transaction(trans, root, ret); | ||
2432 | goto out_wake_log_root; | ||
2433 | } | ||
2431 | 2434 | ||
2432 | mutex_lock(&root->log_mutex); | 2435 | mutex_lock(&root->log_mutex); |
2433 | if (root->last_log_commit < log_transid) | 2436 | if (root->last_log_commit < log_transid) |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dfe5e3a22f55..029b903a4ae3 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1475,6 +1475,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1475 | free_fs_devices(cur_devices); | 1475 | free_fs_devices(cur_devices); |
1476 | } | 1476 | } |
1477 | 1477 | ||
1478 | root->fs_info->num_tolerated_disk_barrier_failures = | ||
1479 | btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info); | ||
1480 | |||
1478 | /* | 1481 | /* |
1479 | * at this point, the device is zero sized. We want to | 1482 | * at this point, the device is zero sized. We want to |
1480 | * remove it from the devices list and zero out the old super | 1483 | * remove it from the devices list and zero out the old super |
@@ -1799,6 +1802,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1799 | btrfs_clear_space_info_full(root->fs_info); | 1802 | btrfs_clear_space_info_full(root->fs_info); |
1800 | 1803 | ||
1801 | unlock_chunks(root); | 1804 | unlock_chunks(root); |
1805 | root->fs_info->num_tolerated_disk_barrier_failures = | ||
1806 | btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info); | ||
1802 | ret = btrfs_commit_transaction(trans, root); | 1807 | ret = btrfs_commit_transaction(trans, root); |
1803 | 1808 | ||
1804 | if (seeding_dev) { | 1809 | if (seeding_dev) { |
@@ -2809,6 +2814,26 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
2809 | } | 2814 | } |
2810 | } | 2815 | } |
2811 | 2816 | ||
2817 | if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
2818 | int num_tolerated_disk_barrier_failures; | ||
2819 | u64 target = bctl->sys.target; | ||
2820 | |||
2821 | num_tolerated_disk_barrier_failures = | ||
2822 | btrfs_calc_num_tolerated_disk_barrier_failures(fs_info); | ||
2823 | if (num_tolerated_disk_barrier_failures > 0 && | ||
2824 | (target & | ||
2825 | (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID0 | | ||
2826 | BTRFS_AVAIL_ALLOC_BIT_SINGLE))) | ||
2827 | num_tolerated_disk_barrier_failures = 0; | ||
2828 | else if (num_tolerated_disk_barrier_failures > 1 && | ||
2829 | (target & | ||
2830 | (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10))) | ||
2831 | num_tolerated_disk_barrier_failures = 1; | ||
2832 | |||
2833 | fs_info->num_tolerated_disk_barrier_failures = | ||
2834 | num_tolerated_disk_barrier_failures; | ||
2835 | } | ||
2836 | |||
2812 | ret = insert_balance_item(fs_info->tree_root, bctl); | 2837 | ret = insert_balance_item(fs_info->tree_root, bctl); |
2813 | if (ret && ret != -EEXIST) | 2838 | if (ret && ret != -EEXIST) |
2814 | goto out; | 2839 | goto out; |
@@ -2841,6 +2866,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
2841 | __cancel_balance(fs_info); | 2866 | __cancel_balance(fs_info); |
2842 | } | 2867 | } |
2843 | 2868 | ||
2869 | if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
2870 | fs_info->num_tolerated_disk_barrier_failures = | ||
2871 | btrfs_calc_num_tolerated_disk_barrier_failures(fs_info); | ||
2872 | } | ||
2873 | |||
2844 | wake_up(&fs_info->balance_wait_q); | 2874 | wake_up(&fs_info->balance_wait_q); |
2845 | 2875 | ||
2846 | return ret; | 2876 | return ret; |