diff options
author | Zhao Lei <zhaolei@cn.fujitsu.com> | 2015-01-20 02:11:41 -0500 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-01-21 21:06:49 -0500 |
commit | b968fed1c3810a0a0d575cab8a72431fbc807615 (patch) | |
tree | fd5aa5d589e91e11de1f86dfef6157ff59988fc1 /fs/btrfs/scrub.c | |
parent | 8d6738c1bd74a27ff6a5043c5211c7bff7745420 (diff) |
Btrfs: Combine per-page recover in dev-replace and scrub
The code are similar, combine them to make code clean and easy to maintenance.
Some lost condition are also completed with benefit of this combination.
Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r-- | fs/btrfs/scrub.c | 120 |
1 files changed, 48 insertions, 72 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index c40ffbc9581f..aac40aefa552 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -1107,54 +1107,10 @@ nodatasum_case: | |||
1107 | } | 1107 | } |
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | /* | 1110 | if (sblock_bad->no_io_error_seen && !sctx->is_dev_replace) |
1111 | * for dev_replace, pick good pages and write to the target device. | 1111 | goto did_not_correct_error; |
1112 | */ | ||
1113 | if (sctx->is_dev_replace) { | ||
1114 | success = 1; | ||
1115 | for (page_num = 0; page_num < sblock_bad->page_count; | ||
1116 | page_num++) { | ||
1117 | struct scrub_block *sblock_other = NULL; | ||
1118 | |||
1119 | for (mirror_index = 0; | ||
1120 | mirror_index < BTRFS_MAX_MIRRORS && | ||
1121 | sblocks_for_recheck[mirror_index].page_count > 0; | ||
1122 | mirror_index++) { | ||
1123 | if (!sblocks_for_recheck[mirror_index]. | ||
1124 | pagev[page_num]->io_error) { | ||
1125 | sblock_other = sblocks_for_recheck + | ||
1126 | mirror_index; | ||
1127 | break; | ||
1128 | } | ||
1129 | } | ||
1130 | |||
1131 | if (!sblock_other) { | ||
1132 | /* | ||
1133 | * did not find a mirror to fetch the page | ||
1134 | * from. scrub_write_page_to_dev_replace() | ||
1135 | * handles this case (page->io_error), by | ||
1136 | * filling the block with zeros before | ||
1137 | * submitting the write request | ||
1138 | */ | ||
1139 | sblock_other = sblock_bad; | ||
1140 | success = 0; | ||
1141 | } | ||
1142 | |||
1143 | if (scrub_write_page_to_dev_replace(sblock_other, | ||
1144 | page_num) != 0) { | ||
1145 | btrfs_dev_replace_stats_inc( | ||
1146 | &sctx->dev_root-> | ||
1147 | fs_info->dev_replace. | ||
1148 | num_write_errors); | ||
1149 | success = 0; | ||
1150 | } | ||
1151 | } | ||
1152 | |||
1153 | goto out; | ||
1154 | } | ||
1155 | 1112 | ||
1156 | /* | 1113 | /* |
1157 | * for regular scrub, repair those pages that are errored. | ||
1158 | * In case of I/O errors in the area that is supposed to be | 1114 | * In case of I/O errors in the area that is supposed to be |
1159 | * repaired, continue by picking good copies of those pages. | 1115 | * repaired, continue by picking good copies of those pages. |
1160 | * Select the good pages from mirrors to rewrite bad pages from | 1116 | * Select the good pages from mirrors to rewrite bad pages from |
@@ -1178,44 +1134,64 @@ nodatasum_case: | |||
1178 | * mirror, even if other 512 byte sectors in the same PAGE_SIZE | 1134 | * mirror, even if other 512 byte sectors in the same PAGE_SIZE |
1179 | * area are unreadable. | 1135 | * area are unreadable. |
1180 | */ | 1136 | */ |
1181 | |||
1182 | /* can only fix I/O errors from here on */ | ||
1183 | if (sblock_bad->no_io_error_seen) | ||
1184 | goto did_not_correct_error; | ||
1185 | |||
1186 | success = 1; | 1137 | success = 1; |
1187 | for (page_num = 0; page_num < sblock_bad->page_count; page_num++) { | 1138 | for (page_num = 0; page_num < sblock_bad->page_count; |
1139 | page_num++) { | ||
1188 | struct scrub_page *page_bad = sblock_bad->pagev[page_num]; | 1140 | struct scrub_page *page_bad = sblock_bad->pagev[page_num]; |
1141 | struct scrub_block *sblock_other = NULL; | ||
1189 | 1142 | ||
1190 | if (!page_bad->io_error) | 1143 | /* skip no-io-error page in scrub */ |
1144 | if (!page_bad->io_error && !sctx->is_dev_replace) | ||
1191 | continue; | 1145 | continue; |
1192 | 1146 | ||
1193 | for (mirror_index = 0; | 1147 | /* try to find no-io-error page in mirrors */ |
1194 | mirror_index < BTRFS_MAX_MIRRORS && | 1148 | if (page_bad->io_error) { |
1195 | sblocks_for_recheck[mirror_index].page_count > 0; | 1149 | for (mirror_index = 0; |
1196 | mirror_index++) { | 1150 | mirror_index < BTRFS_MAX_MIRRORS && |
1197 | struct scrub_block *sblock_other = sblocks_for_recheck + | 1151 | sblocks_for_recheck[mirror_index].page_count > 0; |
1198 | mirror_index; | 1152 | mirror_index++) { |
1199 | struct scrub_page *page_other = sblock_other->pagev[ | 1153 | if (!sblocks_for_recheck[mirror_index]. |
1200 | page_num]; | 1154 | pagev[page_num]->io_error) { |
1201 | 1155 | sblock_other = sblocks_for_recheck + | |
1202 | if (!page_other->io_error) { | 1156 | mirror_index; |
1203 | ret = scrub_repair_page_from_good_copy( | 1157 | break; |
1204 | sblock_bad, sblock_other, page_num, 0); | ||
1205 | if (0 == ret) { | ||
1206 | page_bad->io_error = 0; | ||
1207 | break; /* succeeded for this page */ | ||
1208 | } | 1158 | } |
1209 | } | 1159 | } |
1160 | if (!sblock_other) | ||
1161 | success = 0; | ||
1210 | } | 1162 | } |
1211 | 1163 | ||
1212 | if (page_bad->io_error) { | 1164 | if (sctx->is_dev_replace) { |
1213 | /* did not find a mirror to copy the page from */ | 1165 | /* |
1214 | success = 0; | 1166 | * did not find a mirror to fetch the page |
1167 | * from. scrub_write_page_to_dev_replace() | ||
1168 | * handles this case (page->io_error), by | ||
1169 | * filling the block with zeros before | ||
1170 | * submitting the write request | ||
1171 | */ | ||
1172 | if (!sblock_other) | ||
1173 | sblock_other = sblock_bad; | ||
1174 | |||
1175 | if (scrub_write_page_to_dev_replace(sblock_other, | ||
1176 | page_num) != 0) { | ||
1177 | btrfs_dev_replace_stats_inc( | ||
1178 | &sctx->dev_root-> | ||
1179 | fs_info->dev_replace. | ||
1180 | num_write_errors); | ||
1181 | success = 0; | ||
1182 | } | ||
1183 | } else if (sblock_other) { | ||
1184 | ret = scrub_repair_page_from_good_copy(sblock_bad, | ||
1185 | sblock_other, | ||
1186 | page_num, 0); | ||
1187 | if (0 == ret) | ||
1188 | page_bad->io_error = 0; | ||
1189 | else | ||
1190 | success = 0; | ||
1215 | } | 1191 | } |
1216 | } | 1192 | } |
1217 | 1193 | ||
1218 | if (success) { | 1194 | if (success && !sctx->is_dev_replace) { |
1219 | if (is_metadata || have_csum) { | 1195 | if (is_metadata || have_csum) { |
1220 | /* | 1196 | /* |
1221 | * need to verify the checksum now that all | 1197 | * need to verify the checksum now that all |