diff options
| -rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/scrub.c | 69 | 
2 files changed, 39 insertions, 32 deletions
| diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 33b744a5ac03..9f68c6898653 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -1668,8 +1668,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1668 | init_waitqueue_head(&fs_info->scrub_pause_wait); | 1668 | init_waitqueue_head(&fs_info->scrub_pause_wait); | 
| 1669 | init_rwsem(&fs_info->scrub_super_lock); | 1669 | init_rwsem(&fs_info->scrub_super_lock); | 
| 1670 | fs_info->scrub_workers_refcnt = 0; | 1670 | fs_info->scrub_workers_refcnt = 0; | 
| 1671 | btrfs_init_workers(&fs_info->scrub_workers, "scrub", | ||
| 1672 | fs_info->thread_pool_size, &fs_info->generic_worker); | ||
| 1673 | 1671 | ||
| 1674 | sb->s_blocksize = 4096; | 1672 | sb->s_blocksize = 4096; | 
| 1675 | sb->s_blocksize_bits = blksize_bits(4096); | 1673 | sb->s_blocksize_bits = blksize_bits(4096); | 
| diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index df50fd1eca8f..a8d03d5efb5d 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
| @@ -16,13 +16,7 @@ | |||
| 16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. | 
| 17 | */ | 17 | */ | 
| 18 | 18 | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/pagemap.h> | ||
| 21 | #include <linux/writeback.h> | ||
| 22 | #include <linux/blkdev.h> | 19 | #include <linux/blkdev.h> | 
| 23 | #include <linux/rbtree.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/workqueue.h> | ||
| 26 | #include "ctree.h" | 20 | #include "ctree.h" | 
| 27 | #include "volumes.h" | 21 | #include "volumes.h" | 
| 28 | #include "disk-io.h" | 22 | #include "disk-io.h" | 
| @@ -804,18 +798,12 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, | |||
| 804 | 798 | ||
| 805 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 799 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 
| 806 | if (ret < 0) | 800 | if (ret < 0) | 
| 807 | goto out; | 801 | goto out_noplug; | 
| 808 | |||
| 809 | l = path->nodes[0]; | ||
| 810 | slot = path->slots[0]; | ||
| 811 | btrfs_item_key_to_cpu(l, &key, slot); | ||
| 812 | if (key.objectid != logical) { | ||
| 813 | ret = btrfs_previous_item(root, path, 0, | ||
| 814 | BTRFS_EXTENT_ITEM_KEY); | ||
| 815 | if (ret < 0) | ||
| 816 | goto out; | ||
| 817 | } | ||
| 818 | 802 | ||
| 803 | /* | ||
| 804 | * we might miss half an extent here, but that doesn't matter, | ||
| 805 | * as it's only the prefetch | ||
| 806 | */ | ||
| 819 | while (1) { | 807 | while (1) { | 
| 820 | l = path->nodes[0]; | 808 | l = path->nodes[0]; | 
| 821 | slot = path->slots[0]; | 809 | slot = path->slots[0]; | 
| @@ -824,7 +812,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, | |||
| 824 | if (ret == 0) | 812 | if (ret == 0) | 
| 825 | continue; | 813 | continue; | 
| 826 | if (ret < 0) | 814 | if (ret < 0) | 
| 827 | goto out; | 815 | goto out_noplug; | 
| 828 | 816 | ||
| 829 | break; | 817 | break; | 
| 830 | } | 818 | } | 
| @@ -906,15 +894,20 @@ again: | |||
| 906 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 894 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 
| 907 | if (ret < 0) | 895 | if (ret < 0) | 
| 908 | goto out; | 896 | goto out; | 
| 909 | 897 | if (ret > 0) { | |
| 910 | l = path->nodes[0]; | ||
| 911 | slot = path->slots[0]; | ||
| 912 | btrfs_item_key_to_cpu(l, &key, slot); | ||
| 913 | if (key.objectid != logical) { | ||
| 914 | ret = btrfs_previous_item(root, path, 0, | 898 | ret = btrfs_previous_item(root, path, 0, | 
| 915 | BTRFS_EXTENT_ITEM_KEY); | 899 | BTRFS_EXTENT_ITEM_KEY); | 
| 916 | if (ret < 0) | 900 | if (ret < 0) | 
| 917 | goto out; | 901 | goto out; | 
| 902 | if (ret > 0) { | ||
| 903 | /* there's no smaller item, so stick with the | ||
| 904 | * larger one */ | ||
| 905 | btrfs_release_path(path); | ||
| 906 | ret = btrfs_search_slot(NULL, root, &key, | ||
| 907 | path, 0, 0); | ||
| 908 | if (ret < 0) | ||
| 909 | goto out; | ||
| 910 | } | ||
| 918 | } | 911 | } | 
| 919 | 912 | ||
| 920 | while (1) { | 913 | while (1) { | 
| @@ -989,6 +982,7 @@ next: | |||
| 989 | 982 | ||
| 990 | out: | 983 | out: | 
| 991 | blk_finish_plug(&plug); | 984 | blk_finish_plug(&plug); | 
| 985 | out_noplug: | ||
| 992 | btrfs_free_path(path); | 986 | btrfs_free_path(path); | 
| 993 | return ret < 0 ? ret : 0; | 987 | return ret < 0 ? ret : 0; | 
| 994 | } | 988 | } | 
| @@ -1064,8 +1058,15 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) | |||
| 1064 | while (1) { | 1058 | while (1) { | 
| 1065 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 1059 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 
| 1066 | if (ret < 0) | 1060 | if (ret < 0) | 
| 1067 | goto out; | 1061 | break; | 
| 1068 | ret = 0; | 1062 | if (ret > 0) { | 
| 1063 | if (path->slots[0] >= | ||
| 1064 | btrfs_header_nritems(path->nodes[0])) { | ||
| 1065 | ret = btrfs_next_leaf(root, path); | ||
| 1066 | if (ret) | ||
| 1067 | break; | ||
| 1068 | } | ||
| 1069 | } | ||
| 1069 | 1070 | ||
| 1070 | l = path->nodes[0]; | 1071 | l = path->nodes[0]; | 
| 1071 | slot = path->slots[0]; | 1072 | slot = path->slots[0]; | 
| @@ -1075,7 +1076,7 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) | |||
| 1075 | if (found_key.objectid != sdev->dev->devid) | 1076 | if (found_key.objectid != sdev->dev->devid) | 
| 1076 | break; | 1077 | break; | 
| 1077 | 1078 | ||
| 1078 | if (btrfs_key_type(&key) != BTRFS_DEV_EXTENT_KEY) | 1079 | if (btrfs_key_type(&found_key) != BTRFS_DEV_EXTENT_KEY) | 
| 1079 | break; | 1080 | break; | 
| 1080 | 1081 | ||
| 1081 | if (found_key.offset >= end) | 1082 | if (found_key.offset >= end) | 
| @@ -1104,7 +1105,7 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) | |||
| 1104 | cache = btrfs_lookup_block_group(fs_info, chunk_offset); | 1105 | cache = btrfs_lookup_block_group(fs_info, chunk_offset); | 
| 1105 | if (!cache) { | 1106 | if (!cache) { | 
| 1106 | ret = -ENOENT; | 1107 | ret = -ENOENT; | 
| 1107 | goto out; | 1108 | break; | 
| 1108 | } | 1109 | } | 
| 1109 | ret = scrub_chunk(sdev, chunk_tree, chunk_objectid, | 1110 | ret = scrub_chunk(sdev, chunk_tree, chunk_objectid, | 
| 1110 | chunk_offset, length); | 1111 | chunk_offset, length); | 
| @@ -1116,9 +1117,13 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) | |||
| 1116 | btrfs_release_path(path); | 1117 | btrfs_release_path(path); | 
| 1117 | } | 1118 | } | 
| 1118 | 1119 | ||
| 1119 | out: | ||
| 1120 | btrfs_free_path(path); | 1120 | btrfs_free_path(path); | 
| 1121 | return ret; | 1121 | |
| 1122 | /* | ||
| 1123 | * ret can still be 1 from search_slot or next_leaf, | ||
| 1124 | * that's not an error | ||
| 1125 | */ | ||
| 1126 | return ret < 0 ? ret : 0; | ||
| 1122 | } | 1127 | } | 
| 1123 | 1128 | ||
| 1124 | static noinline_for_stack int scrub_supers(struct scrub_dev *sdev) | 1129 | static noinline_for_stack int scrub_supers(struct scrub_dev *sdev) | 
| @@ -1155,8 +1160,12 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_root *root) | |||
| 1155 | struct btrfs_fs_info *fs_info = root->fs_info; | 1160 | struct btrfs_fs_info *fs_info = root->fs_info; | 
| 1156 | 1161 | ||
| 1157 | mutex_lock(&fs_info->scrub_lock); | 1162 | mutex_lock(&fs_info->scrub_lock); | 
| 1158 | if (fs_info->scrub_workers_refcnt == 0) | 1163 | if (fs_info->scrub_workers_refcnt == 0) { | 
| 1164 | btrfs_init_workers(&fs_info->scrub_workers, "scrub", | ||
| 1165 | fs_info->thread_pool_size, &fs_info->generic_worker); | ||
| 1166 | fs_info->scrub_workers.idle_thresh = 4; | ||
| 1159 | btrfs_start_workers(&fs_info->scrub_workers, 1); | 1167 | btrfs_start_workers(&fs_info->scrub_workers, 1); | 
| 1168 | } | ||
| 1160 | ++fs_info->scrub_workers_refcnt; | 1169 | ++fs_info->scrub_workers_refcnt; | 
| 1161 | mutex_unlock(&fs_info->scrub_lock); | 1170 | mutex_unlock(&fs_info->scrub_lock); | 
| 1162 | 1171 | ||
