diff options
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r-- | fs/btrfs/scrub.c | 179 |
1 files changed, 65 insertions, 114 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 550de89a8661..2907a77fb1f6 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -248,14 +248,9 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check); | |||
248 | static int scrub_setup_recheck_block(struct scrub_block *original_sblock, | 248 | static int scrub_setup_recheck_block(struct scrub_block *original_sblock, |
249 | struct scrub_block *sblocks_for_recheck); | 249 | struct scrub_block *sblocks_for_recheck); |
250 | static void scrub_recheck_block(struct btrfs_fs_info *fs_info, | 250 | static void scrub_recheck_block(struct btrfs_fs_info *fs_info, |
251 | struct scrub_block *sblock, int is_metadata, | 251 | struct scrub_block *sblock, |
252 | int have_csum, u8 *csum, u64 generation, | 252 | int retry_failed_mirror); |
253 | u16 csum_size, int retry_failed_mirror); | 253 | static void scrub_recheck_block_checksum(struct scrub_block *sblock); |
254 | static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info, | ||
255 | struct scrub_block *sblock, | ||
256 | int is_metadata, int have_csum, | ||
257 | const u8 *csum, u64 generation, | ||
258 | u16 csum_size); | ||
259 | static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad, | 254 | static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad, |
260 | struct scrub_block *sblock_good); | 255 | struct scrub_block *sblock_good); |
261 | static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, | 256 | static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, |
@@ -889,11 +884,9 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) | |||
889 | struct btrfs_fs_info *fs_info; | 884 | struct btrfs_fs_info *fs_info; |
890 | u64 length; | 885 | u64 length; |
891 | u64 logical; | 886 | u64 logical; |
892 | u64 generation; | ||
893 | unsigned int failed_mirror_index; | 887 | unsigned int failed_mirror_index; |
894 | unsigned int is_metadata; | 888 | unsigned int is_metadata; |
895 | unsigned int have_csum; | 889 | unsigned int have_csum; |
896 | u8 *csum; | ||
897 | struct scrub_block *sblocks_for_recheck; /* holds one for each mirror */ | 890 | struct scrub_block *sblocks_for_recheck; /* holds one for each mirror */ |
898 | struct scrub_block *sblock_bad; | 891 | struct scrub_block *sblock_bad; |
899 | int ret; | 892 | int ret; |
@@ -918,13 +911,11 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) | |||
918 | } | 911 | } |
919 | length = sblock_to_check->page_count * PAGE_SIZE; | 912 | length = sblock_to_check->page_count * PAGE_SIZE; |
920 | logical = sblock_to_check->pagev[0]->logical; | 913 | logical = sblock_to_check->pagev[0]->logical; |
921 | generation = sblock_to_check->pagev[0]->generation; | ||
922 | BUG_ON(sblock_to_check->pagev[0]->mirror_num < 1); | 914 | BUG_ON(sblock_to_check->pagev[0]->mirror_num < 1); |
923 | failed_mirror_index = sblock_to_check->pagev[0]->mirror_num - 1; | 915 | failed_mirror_index = sblock_to_check->pagev[0]->mirror_num - 1; |
924 | is_metadata = !(sblock_to_check->pagev[0]->flags & | 916 | is_metadata = !(sblock_to_check->pagev[0]->flags & |
925 | BTRFS_EXTENT_FLAG_DATA); | 917 | BTRFS_EXTENT_FLAG_DATA); |
926 | have_csum = sblock_to_check->pagev[0]->have_csum; | 918 | have_csum = sblock_to_check->pagev[0]->have_csum; |
927 | csum = sblock_to_check->pagev[0]->csum; | ||
928 | dev = sblock_to_check->pagev[0]->dev; | 919 | dev = sblock_to_check->pagev[0]->dev; |
929 | 920 | ||
930 | if (sctx->is_dev_replace && !is_metadata && !have_csum) { | 921 | if (sctx->is_dev_replace && !is_metadata && !have_csum) { |
@@ -987,8 +978,7 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) | |||
987 | sblock_bad = sblocks_for_recheck + failed_mirror_index; | 978 | sblock_bad = sblocks_for_recheck + failed_mirror_index; |
988 | 979 | ||
989 | /* build and submit the bios for the failed mirror, check checksums */ | 980 | /* build and submit the bios for the failed mirror, check checksums */ |
990 | scrub_recheck_block(fs_info, sblock_bad, is_metadata, have_csum, | 981 | scrub_recheck_block(fs_info, sblock_bad, 1); |
991 | csum, generation, sctx->csum_size, 1); | ||
992 | 982 | ||
993 | if (!sblock_bad->header_error && !sblock_bad->checksum_error && | 983 | if (!sblock_bad->header_error && !sblock_bad->checksum_error && |
994 | sblock_bad->no_io_error_seen) { | 984 | sblock_bad->no_io_error_seen) { |
@@ -1101,9 +1091,7 @@ nodatasum_case: | |||
1101 | sblock_other = sblocks_for_recheck + mirror_index; | 1091 | sblock_other = sblocks_for_recheck + mirror_index; |
1102 | 1092 | ||
1103 | /* build and submit the bios, check checksums */ | 1093 | /* build and submit the bios, check checksums */ |
1104 | scrub_recheck_block(fs_info, sblock_other, is_metadata, | 1094 | scrub_recheck_block(fs_info, sblock_other, 0); |
1105 | have_csum, csum, generation, | ||
1106 | sctx->csum_size, 0); | ||
1107 | 1095 | ||
1108 | if (!sblock_other->header_error && | 1096 | if (!sblock_other->header_error && |
1109 | !sblock_other->checksum_error && | 1097 | !sblock_other->checksum_error && |
@@ -1215,9 +1203,7 @@ nodatasum_case: | |||
1215 | * is verified, but most likely the data comes out | 1203 | * is verified, but most likely the data comes out |
1216 | * of the page cache. | 1204 | * of the page cache. |
1217 | */ | 1205 | */ |
1218 | scrub_recheck_block(fs_info, sblock_bad, | 1206 | scrub_recheck_block(fs_info, sblock_bad, 1); |
1219 | is_metadata, have_csum, csum, | ||
1220 | generation, sctx->csum_size, 1); | ||
1221 | if (!sblock_bad->header_error && | 1207 | if (!sblock_bad->header_error && |
1222 | !sblock_bad->checksum_error && | 1208 | !sblock_bad->checksum_error && |
1223 | sblock_bad->no_io_error_seen) | 1209 | sblock_bad->no_io_error_seen) |
@@ -1318,6 +1304,9 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock, | |||
1318 | struct btrfs_fs_info *fs_info = sctx->dev_root->fs_info; | 1304 | struct btrfs_fs_info *fs_info = sctx->dev_root->fs_info; |
1319 | u64 length = original_sblock->page_count * PAGE_SIZE; | 1305 | u64 length = original_sblock->page_count * PAGE_SIZE; |
1320 | u64 logical = original_sblock->pagev[0]->logical; | 1306 | u64 logical = original_sblock->pagev[0]->logical; |
1307 | u64 generation = original_sblock->pagev[0]->generation; | ||
1308 | u64 flags = original_sblock->pagev[0]->flags; | ||
1309 | u64 have_csum = original_sblock->pagev[0]->have_csum; | ||
1321 | struct scrub_recover *recover; | 1310 | struct scrub_recover *recover; |
1322 | struct btrfs_bio *bbio; | 1311 | struct btrfs_bio *bbio; |
1323 | u64 sublen; | 1312 | u64 sublen; |
@@ -1372,6 +1361,7 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock, | |||
1372 | 1361 | ||
1373 | sblock = sblocks_for_recheck + mirror_index; | 1362 | sblock = sblocks_for_recheck + mirror_index; |
1374 | sblock->sctx = sctx; | 1363 | sblock->sctx = sctx; |
1364 | |||
1375 | page = kzalloc(sizeof(*page), GFP_NOFS); | 1365 | page = kzalloc(sizeof(*page), GFP_NOFS); |
1376 | if (!page) { | 1366 | if (!page) { |
1377 | leave_nomem: | 1367 | leave_nomem: |
@@ -1383,7 +1373,15 @@ leave_nomem: | |||
1383 | } | 1373 | } |
1384 | scrub_page_get(page); | 1374 | scrub_page_get(page); |
1385 | sblock->pagev[page_index] = page; | 1375 | sblock->pagev[page_index] = page; |
1376 | page->sblock = sblock; | ||
1377 | page->flags = flags; | ||
1378 | page->generation = generation; | ||
1386 | page->logical = logical; | 1379 | page->logical = logical; |
1380 | page->have_csum = have_csum; | ||
1381 | if (have_csum) | ||
1382 | memcpy(page->csum, | ||
1383 | original_sblock->pagev[0]->csum, | ||
1384 | sctx->csum_size); | ||
1387 | 1385 | ||
1388 | scrub_stripe_index_and_offset(logical, | 1386 | scrub_stripe_index_and_offset(logical, |
1389 | bbio->map_type, | 1387 | bbio->map_type, |
@@ -1474,15 +1472,12 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info, | |||
1474 | * the pages that are errored in the just handled mirror can be repaired. | 1472 | * the pages that are errored in the just handled mirror can be repaired. |
1475 | */ | 1473 | */ |
1476 | static void scrub_recheck_block(struct btrfs_fs_info *fs_info, | 1474 | static void scrub_recheck_block(struct btrfs_fs_info *fs_info, |
1477 | struct scrub_block *sblock, int is_metadata, | 1475 | struct scrub_block *sblock, |
1478 | int have_csum, u8 *csum, u64 generation, | 1476 | int retry_failed_mirror) |
1479 | u16 csum_size, int retry_failed_mirror) | ||
1480 | { | 1477 | { |
1481 | int page_num; | 1478 | int page_num; |
1482 | 1479 | ||
1483 | sblock->no_io_error_seen = 1; | 1480 | sblock->no_io_error_seen = 1; |
1484 | sblock->header_error = 0; | ||
1485 | sblock->checksum_error = 0; | ||
1486 | 1481 | ||
1487 | for (page_num = 0; page_num < sblock->page_count; page_num++) { | 1482 | for (page_num = 0; page_num < sblock->page_count; page_num++) { |
1488 | struct bio *bio; | 1483 | struct bio *bio; |
@@ -1518,9 +1513,7 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info, | |||
1518 | } | 1513 | } |
1519 | 1514 | ||
1520 | if (sblock->no_io_error_seen) | 1515 | if (sblock->no_io_error_seen) |
1521 | scrub_recheck_block_checksum(fs_info, sblock, is_metadata, | 1516 | scrub_recheck_block_checksum(sblock); |
1522 | have_csum, csum, generation, | ||
1523 | csum_size); | ||
1524 | 1517 | ||
1525 | return; | 1518 | return; |
1526 | } | 1519 | } |
@@ -1535,61 +1528,16 @@ static inline int scrub_check_fsid(u8 fsid[], | |||
1535 | return !ret; | 1528 | return !ret; |
1536 | } | 1529 | } |
1537 | 1530 | ||
1538 | static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info, | 1531 | static void scrub_recheck_block_checksum(struct scrub_block *sblock) |
1539 | struct scrub_block *sblock, | ||
1540 | int is_metadata, int have_csum, | ||
1541 | const u8 *csum, u64 generation, | ||
1542 | u16 csum_size) | ||
1543 | { | 1532 | { |
1544 | int page_num; | 1533 | sblock->header_error = 0; |
1545 | u8 calculated_csum[BTRFS_CSUM_SIZE]; | 1534 | sblock->checksum_error = 0; |
1546 | u32 crc = ~(u32)0; | 1535 | sblock->generation_error = 0; |
1547 | void *mapped_buffer; | ||
1548 | |||
1549 | WARN_ON(!sblock->pagev[0]->page); | ||
1550 | if (is_metadata) { | ||
1551 | struct btrfs_header *h; | ||
1552 | |||
1553 | mapped_buffer = kmap_atomic(sblock->pagev[0]->page); | ||
1554 | h = (struct btrfs_header *)mapped_buffer; | ||
1555 | |||
1556 | if (sblock->pagev[0]->logical != btrfs_stack_header_bytenr(h) || | ||
1557 | !scrub_check_fsid(h->fsid, sblock->pagev[0]) || | ||
1558 | memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid, | ||
1559 | BTRFS_UUID_SIZE)) { | ||
1560 | sblock->header_error = 1; | ||
1561 | } else if (generation != btrfs_stack_header_generation(h)) { | ||
1562 | sblock->header_error = 1; | ||
1563 | sblock->generation_error = 1; | ||
1564 | } | ||
1565 | csum = h->csum; | ||
1566 | } else { | ||
1567 | if (!have_csum) | ||
1568 | return; | ||
1569 | |||
1570 | mapped_buffer = kmap_atomic(sblock->pagev[0]->page); | ||
1571 | } | ||
1572 | |||
1573 | for (page_num = 0;;) { | ||
1574 | if (page_num == 0 && is_metadata) | ||
1575 | crc = btrfs_csum_data( | ||
1576 | ((u8 *)mapped_buffer) + BTRFS_CSUM_SIZE, | ||
1577 | crc, PAGE_SIZE - BTRFS_CSUM_SIZE); | ||
1578 | else | ||
1579 | crc = btrfs_csum_data(mapped_buffer, crc, PAGE_SIZE); | ||
1580 | |||
1581 | kunmap_atomic(mapped_buffer); | ||
1582 | page_num++; | ||
1583 | if (page_num >= sblock->page_count) | ||
1584 | break; | ||
1585 | WARN_ON(!sblock->pagev[page_num]->page); | ||
1586 | |||
1587 | mapped_buffer = kmap_atomic(sblock->pagev[page_num]->page); | ||
1588 | } | ||
1589 | 1536 | ||
1590 | btrfs_csum_final(crc, calculated_csum); | 1537 | if (sblock->pagev[0]->flags & BTRFS_EXTENT_FLAG_DATA) |
1591 | if (memcmp(calculated_csum, csum, csum_size)) | 1538 | scrub_checksum_data(sblock); |
1592 | sblock->checksum_error = 1; | 1539 | else |
1540 | scrub_checksum_tree_block(sblock); | ||
1593 | } | 1541 | } |
1594 | 1542 | ||
1595 | static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad, | 1543 | static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad, |
@@ -1833,6 +1781,18 @@ static int scrub_checksum(struct scrub_block *sblock) | |||
1833 | u64 flags; | 1781 | u64 flags; |
1834 | int ret; | 1782 | int ret; |
1835 | 1783 | ||
1784 | /* | ||
1785 | * No need to initialize these stats currently, | ||
1786 | * because this function only use return value | ||
1787 | * instead of these stats value. | ||
1788 | * | ||
1789 | * Todo: | ||
1790 | * always use stats | ||
1791 | */ | ||
1792 | sblock->header_error = 0; | ||
1793 | sblock->generation_error = 0; | ||
1794 | sblock->checksum_error = 0; | ||
1795 | |||
1836 | WARN_ON(sblock->page_count < 1); | 1796 | WARN_ON(sblock->page_count < 1); |
1837 | flags = sblock->pagev[0]->flags; | 1797 | flags = sblock->pagev[0]->flags; |
1838 | ret = 0; | 1798 | ret = 0; |
@@ -1858,7 +1818,6 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1858 | struct page *page; | 1818 | struct page *page; |
1859 | void *buffer; | 1819 | void *buffer; |
1860 | u32 crc = ~(u32)0; | 1820 | u32 crc = ~(u32)0; |
1861 | int fail = 0; | ||
1862 | u64 len; | 1821 | u64 len; |
1863 | int index; | 1822 | int index; |
1864 | 1823 | ||
@@ -1889,9 +1848,9 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1889 | 1848 | ||
1890 | btrfs_csum_final(crc, csum); | 1849 | btrfs_csum_final(crc, csum); |
1891 | if (memcmp(csum, on_disk_csum, sctx->csum_size)) | 1850 | if (memcmp(csum, on_disk_csum, sctx->csum_size)) |
1892 | fail = 1; | 1851 | sblock->checksum_error = 1; |
1893 | 1852 | ||
1894 | return fail; | 1853 | return sblock->checksum_error; |
1895 | } | 1854 | } |
1896 | 1855 | ||
1897 | static int scrub_checksum_tree_block(struct scrub_block *sblock) | 1856 | static int scrub_checksum_tree_block(struct scrub_block *sblock) |
@@ -1907,8 +1866,6 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1907 | u64 mapped_size; | 1866 | u64 mapped_size; |
1908 | void *p; | 1867 | void *p; |
1909 | u32 crc = ~(u32)0; | 1868 | u32 crc = ~(u32)0; |
1910 | int fail = 0; | ||
1911 | int crc_fail = 0; | ||
1912 | u64 len; | 1869 | u64 len; |
1913 | int index; | 1870 | int index; |
1914 | 1871 | ||
@@ -1923,19 +1880,20 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1923 | * a) don't have an extent buffer and | 1880 | * a) don't have an extent buffer and |
1924 | * b) the page is already kmapped | 1881 | * b) the page is already kmapped |
1925 | */ | 1882 | */ |
1926 | |||
1927 | if (sblock->pagev[0]->logical != btrfs_stack_header_bytenr(h)) | 1883 | if (sblock->pagev[0]->logical != btrfs_stack_header_bytenr(h)) |
1928 | ++fail; | 1884 | sblock->header_error = 1; |
1929 | 1885 | ||
1930 | if (sblock->pagev[0]->generation != btrfs_stack_header_generation(h)) | 1886 | if (sblock->pagev[0]->generation != btrfs_stack_header_generation(h)) { |
1931 | ++fail; | 1887 | sblock->header_error = 1; |
1888 | sblock->generation_error = 1; | ||
1889 | } | ||
1932 | 1890 | ||
1933 | if (!scrub_check_fsid(h->fsid, sblock->pagev[0])) | 1891 | if (!scrub_check_fsid(h->fsid, sblock->pagev[0])) |
1934 | ++fail; | 1892 | sblock->header_error = 1; |
1935 | 1893 | ||
1936 | if (memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid, | 1894 | if (memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid, |
1937 | BTRFS_UUID_SIZE)) | 1895 | BTRFS_UUID_SIZE)) |
1938 | ++fail; | 1896 | sblock->header_error = 1; |
1939 | 1897 | ||
1940 | len = sctx->nodesize - BTRFS_CSUM_SIZE; | 1898 | len = sctx->nodesize - BTRFS_CSUM_SIZE; |
1941 | mapped_size = PAGE_SIZE - BTRFS_CSUM_SIZE; | 1899 | mapped_size = PAGE_SIZE - BTRFS_CSUM_SIZE; |
@@ -1960,9 +1918,9 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1960 | 1918 | ||
1961 | btrfs_csum_final(crc, calculated_csum); | 1919 | btrfs_csum_final(crc, calculated_csum); |
1962 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) | 1920 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) |
1963 | ++crc_fail; | 1921 | sblock->checksum_error = 1; |
1964 | 1922 | ||
1965 | return fail || crc_fail; | 1923 | return sblock->header_error || sblock->checksum_error; |
1966 | } | 1924 | } |
1967 | 1925 | ||
1968 | static int scrub_checksum_super(struct scrub_block *sblock) | 1926 | static int scrub_checksum_super(struct scrub_block *sblock) |
@@ -2176,39 +2134,27 @@ static void scrub_missing_raid56_worker(struct btrfs_work *work) | |||
2176 | { | 2134 | { |
2177 | struct scrub_block *sblock = container_of(work, struct scrub_block, work); | 2135 | struct scrub_block *sblock = container_of(work, struct scrub_block, work); |
2178 | struct scrub_ctx *sctx = sblock->sctx; | 2136 | struct scrub_ctx *sctx = sblock->sctx; |
2179 | struct btrfs_fs_info *fs_info = sctx->dev_root->fs_info; | ||
2180 | unsigned int is_metadata; | ||
2181 | unsigned int have_csum; | ||
2182 | u8 *csum; | ||
2183 | u64 generation; | ||
2184 | u64 logical; | 2137 | u64 logical; |
2185 | struct btrfs_device *dev; | 2138 | struct btrfs_device *dev; |
2186 | 2139 | ||
2187 | is_metadata = !(sblock->pagev[0]->flags & BTRFS_EXTENT_FLAG_DATA); | ||
2188 | have_csum = sblock->pagev[0]->have_csum; | ||
2189 | csum = sblock->pagev[0]->csum; | ||
2190 | generation = sblock->pagev[0]->generation; | ||
2191 | logical = sblock->pagev[0]->logical; | 2140 | logical = sblock->pagev[0]->logical; |
2192 | dev = sblock->pagev[0]->dev; | 2141 | dev = sblock->pagev[0]->dev; |
2193 | 2142 | ||
2194 | if (sblock->no_io_error_seen) { | 2143 | if (sblock->no_io_error_seen) |
2195 | scrub_recheck_block_checksum(fs_info, sblock, is_metadata, | 2144 | scrub_recheck_block_checksum(sblock); |
2196 | have_csum, csum, generation, | ||
2197 | sctx->csum_size); | ||
2198 | } | ||
2199 | 2145 | ||
2200 | if (!sblock->no_io_error_seen) { | 2146 | if (!sblock->no_io_error_seen) { |
2201 | spin_lock(&sctx->stat_lock); | 2147 | spin_lock(&sctx->stat_lock); |
2202 | sctx->stat.read_errors++; | 2148 | sctx->stat.read_errors++; |
2203 | spin_unlock(&sctx->stat_lock); | 2149 | spin_unlock(&sctx->stat_lock); |
2204 | btrfs_err_rl_in_rcu(fs_info, | 2150 | btrfs_err_rl_in_rcu(sctx->dev_root->fs_info, |
2205 | "IO error rebuilding logical %llu for dev %s", | 2151 | "IO error rebuilding logical %llu for dev %s", |
2206 | logical, rcu_str_deref(dev->name)); | 2152 | logical, rcu_str_deref(dev->name)); |
2207 | } else if (sblock->header_error || sblock->checksum_error) { | 2153 | } else if (sblock->header_error || sblock->checksum_error) { |
2208 | spin_lock(&sctx->stat_lock); | 2154 | spin_lock(&sctx->stat_lock); |
2209 | sctx->stat.uncorrectable_errors++; | 2155 | sctx->stat.uncorrectable_errors++; |
2210 | spin_unlock(&sctx->stat_lock); | 2156 | spin_unlock(&sctx->stat_lock); |
2211 | btrfs_err_rl_in_rcu(fs_info, | 2157 | btrfs_err_rl_in_rcu(sctx->dev_root->fs_info, |
2212 | "failed to rebuild valid logical %llu for dev %s", | 2158 | "failed to rebuild valid logical %llu for dev %s", |
2213 | logical, rcu_str_deref(dev->name)); | 2159 | logical, rcu_str_deref(dev->name)); |
2214 | } else { | 2160 | } else { |
@@ -2500,8 +2446,7 @@ static void scrub_block_complete(struct scrub_block *sblock) | |||
2500 | } | 2446 | } |
2501 | } | 2447 | } |
2502 | 2448 | ||
2503 | static int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u64 len, | 2449 | static int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u8 *csum) |
2504 | u8 *csum) | ||
2505 | { | 2450 | { |
2506 | struct btrfs_ordered_sum *sum = NULL; | 2451 | struct btrfs_ordered_sum *sum = NULL; |
2507 | unsigned long index; | 2452 | unsigned long index; |
@@ -2565,7 +2510,7 @@ static int scrub_extent(struct scrub_ctx *sctx, u64 logical, u64 len, | |||
2565 | 2510 | ||
2566 | if (flags & BTRFS_EXTENT_FLAG_DATA) { | 2511 | if (flags & BTRFS_EXTENT_FLAG_DATA) { |
2567 | /* push csums to sbio */ | 2512 | /* push csums to sbio */ |
2568 | have_csum = scrub_find_csum(sctx, logical, l, csum); | 2513 | have_csum = scrub_find_csum(sctx, logical, csum); |
2569 | if (have_csum == 0) | 2514 | if (have_csum == 0) |
2570 | ++sctx->stat.no_csum; | 2515 | ++sctx->stat.no_csum; |
2571 | if (sctx->is_dev_replace && !have_csum) { | 2516 | if (sctx->is_dev_replace && !have_csum) { |
@@ -2703,7 +2648,7 @@ static int scrub_extent_for_parity(struct scrub_parity *sparity, | |||
2703 | 2648 | ||
2704 | if (flags & BTRFS_EXTENT_FLAG_DATA) { | 2649 | if (flags & BTRFS_EXTENT_FLAG_DATA) { |
2705 | /* push csums to sbio */ | 2650 | /* push csums to sbio */ |
2706 | have_csum = scrub_find_csum(sctx, logical, l, csum); | 2651 | have_csum = scrub_find_csum(sctx, logical, csum); |
2707 | if (have_csum == 0) | 2652 | if (have_csum == 0) |
2708 | goto skip; | 2653 | goto skip; |
2709 | } | 2654 | } |
@@ -3012,6 +2957,9 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx, | |||
3012 | logic_start + map->stripe_len)) { | 2957 | logic_start + map->stripe_len)) { |
3013 | btrfs_err(fs_info, "scrub: tree block %llu spanning stripes, ignored. logical=%llu", | 2958 | btrfs_err(fs_info, "scrub: tree block %llu spanning stripes, ignored. logical=%llu", |
3014 | key.objectid, logic_start); | 2959 | key.objectid, logic_start); |
2960 | spin_lock(&sctx->stat_lock); | ||
2961 | sctx->stat.uncorrectable_errors++; | ||
2962 | spin_unlock(&sctx->stat_lock); | ||
3015 | goto next; | 2963 | goto next; |
3016 | } | 2964 | } |
3017 | again: | 2965 | again: |
@@ -3361,6 +3309,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
3361 | "scrub: tree block %llu spanning " | 3309 | "scrub: tree block %llu spanning " |
3362 | "stripes, ignored. logical=%llu", | 3310 | "stripes, ignored. logical=%llu", |
3363 | key.objectid, logical); | 3311 | key.objectid, logical); |
3312 | spin_lock(&sctx->stat_lock); | ||
3313 | sctx->stat.uncorrectable_errors++; | ||
3314 | spin_unlock(&sctx->stat_lock); | ||
3364 | goto next; | 3315 | goto next; |
3365 | } | 3316 | } |
3366 | 3317 | ||