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 | ||