diff options
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r-- | fs/btrfs/scrub.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index f7b29f9db5e2..0c99cf9fb595 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/blkdev.h> | 6 | #include <linux/blkdev.h> |
7 | #include <linux/ratelimit.h> | 7 | #include <linux/ratelimit.h> |
8 | #include <linux/sched/mm.h> | 8 | #include <linux/sched/mm.h> |
9 | #include <crypto/hash.h> | ||
9 | #include "ctree.h" | 10 | #include "ctree.h" |
10 | #include "volumes.h" | 11 | #include "volumes.h" |
11 | #include "disk-io.h" | 12 | #include "disk-io.h" |
@@ -1787,11 +1788,12 @@ static int scrub_checksum(struct scrub_block *sblock) | |||
1787 | static int scrub_checksum_data(struct scrub_block *sblock) | 1788 | static int scrub_checksum_data(struct scrub_block *sblock) |
1788 | { | 1789 | { |
1789 | struct scrub_ctx *sctx = sblock->sctx; | 1790 | struct scrub_ctx *sctx = sblock->sctx; |
1791 | struct btrfs_fs_info *fs_info = sctx->fs_info; | ||
1792 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
1790 | u8 csum[BTRFS_CSUM_SIZE]; | 1793 | u8 csum[BTRFS_CSUM_SIZE]; |
1791 | u8 *on_disk_csum; | 1794 | u8 *on_disk_csum; |
1792 | struct page *page; | 1795 | struct page *page; |
1793 | void *buffer; | 1796 | void *buffer; |
1794 | u32 crc = ~(u32)0; | ||
1795 | u64 len; | 1797 | u64 len; |
1796 | int index; | 1798 | int index; |
1797 | 1799 | ||
@@ -1799,6 +1801,9 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1799 | if (!sblock->pagev[0]->have_csum) | 1801 | if (!sblock->pagev[0]->have_csum) |
1800 | return 0; | 1802 | return 0; |
1801 | 1803 | ||
1804 | shash->tfm = fs_info->csum_shash; | ||
1805 | crypto_shash_init(shash); | ||
1806 | |||
1802 | on_disk_csum = sblock->pagev[0]->csum; | 1807 | on_disk_csum = sblock->pagev[0]->csum; |
1803 | page = sblock->pagev[0]->page; | 1808 | page = sblock->pagev[0]->page; |
1804 | buffer = kmap_atomic(page); | 1809 | buffer = kmap_atomic(page); |
@@ -1808,7 +1813,7 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1808 | for (;;) { | 1813 | for (;;) { |
1809 | u64 l = min_t(u64, len, PAGE_SIZE); | 1814 | u64 l = min_t(u64, len, PAGE_SIZE); |
1810 | 1815 | ||
1811 | crc = btrfs_csum_data(buffer, crc, l); | 1816 | crypto_shash_update(shash, buffer, l); |
1812 | kunmap_atomic(buffer); | 1817 | kunmap_atomic(buffer); |
1813 | len -= l; | 1818 | len -= l; |
1814 | if (len == 0) | 1819 | if (len == 0) |
@@ -1820,7 +1825,7 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1820 | buffer = kmap_atomic(page); | 1825 | buffer = kmap_atomic(page); |
1821 | } | 1826 | } |
1822 | 1827 | ||
1823 | btrfs_csum_final(crc, csum); | 1828 | crypto_shash_final(shash, csum); |
1824 | if (memcmp(csum, on_disk_csum, sctx->csum_size)) | 1829 | if (memcmp(csum, on_disk_csum, sctx->csum_size)) |
1825 | sblock->checksum_error = 1; | 1830 | sblock->checksum_error = 1; |
1826 | 1831 | ||
@@ -1832,16 +1837,19 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1832 | struct scrub_ctx *sctx = sblock->sctx; | 1837 | struct scrub_ctx *sctx = sblock->sctx; |
1833 | struct btrfs_header *h; | 1838 | struct btrfs_header *h; |
1834 | struct btrfs_fs_info *fs_info = sctx->fs_info; | 1839 | struct btrfs_fs_info *fs_info = sctx->fs_info; |
1840 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
1835 | u8 calculated_csum[BTRFS_CSUM_SIZE]; | 1841 | u8 calculated_csum[BTRFS_CSUM_SIZE]; |
1836 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; | 1842 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; |
1837 | struct page *page; | 1843 | struct page *page; |
1838 | void *mapped_buffer; | 1844 | void *mapped_buffer; |
1839 | u64 mapped_size; | 1845 | u64 mapped_size; |
1840 | void *p; | 1846 | void *p; |
1841 | u32 crc = ~(u32)0; | ||
1842 | u64 len; | 1847 | u64 len; |
1843 | int index; | 1848 | int index; |
1844 | 1849 | ||
1850 | shash->tfm = fs_info->csum_shash; | ||
1851 | crypto_shash_init(shash); | ||
1852 | |||
1845 | BUG_ON(sblock->page_count < 1); | 1853 | BUG_ON(sblock->page_count < 1); |
1846 | page = sblock->pagev[0]->page; | 1854 | page = sblock->pagev[0]->page; |
1847 | mapped_buffer = kmap_atomic(page); | 1855 | mapped_buffer = kmap_atomic(page); |
@@ -1875,7 +1883,7 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1875 | for (;;) { | 1883 | for (;;) { |
1876 | u64 l = min_t(u64, len, mapped_size); | 1884 | u64 l = min_t(u64, len, mapped_size); |
1877 | 1885 | ||
1878 | crc = btrfs_csum_data(p, crc, l); | 1886 | crypto_shash_update(shash, p, l); |
1879 | kunmap_atomic(mapped_buffer); | 1887 | kunmap_atomic(mapped_buffer); |
1880 | len -= l; | 1888 | len -= l; |
1881 | if (len == 0) | 1889 | if (len == 0) |
@@ -1889,7 +1897,7 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1889 | p = mapped_buffer; | 1897 | p = mapped_buffer; |
1890 | } | 1898 | } |
1891 | 1899 | ||
1892 | btrfs_csum_final(crc, calculated_csum); | 1900 | crypto_shash_final(shash, calculated_csum); |
1893 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) | 1901 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) |
1894 | sblock->checksum_error = 1; | 1902 | sblock->checksum_error = 1; |
1895 | 1903 | ||
@@ -1900,18 +1908,22 @@ static int scrub_checksum_super(struct scrub_block *sblock) | |||
1900 | { | 1908 | { |
1901 | struct btrfs_super_block *s; | 1909 | struct btrfs_super_block *s; |
1902 | struct scrub_ctx *sctx = sblock->sctx; | 1910 | struct scrub_ctx *sctx = sblock->sctx; |
1911 | struct btrfs_fs_info *fs_info = sctx->fs_info; | ||
1912 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
1903 | u8 calculated_csum[BTRFS_CSUM_SIZE]; | 1913 | u8 calculated_csum[BTRFS_CSUM_SIZE]; |
1904 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; | 1914 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; |
1905 | struct page *page; | 1915 | struct page *page; |
1906 | void *mapped_buffer; | 1916 | void *mapped_buffer; |
1907 | u64 mapped_size; | 1917 | u64 mapped_size; |
1908 | void *p; | 1918 | void *p; |
1909 | u32 crc = ~(u32)0; | ||
1910 | int fail_gen = 0; | 1919 | int fail_gen = 0; |
1911 | int fail_cor = 0; | 1920 | int fail_cor = 0; |
1912 | u64 len; | 1921 | u64 len; |
1913 | int index; | 1922 | int index; |
1914 | 1923 | ||
1924 | shash->tfm = fs_info->csum_shash; | ||
1925 | crypto_shash_init(shash); | ||
1926 | |||
1915 | BUG_ON(sblock->page_count < 1); | 1927 | BUG_ON(sblock->page_count < 1); |
1916 | page = sblock->pagev[0]->page; | 1928 | page = sblock->pagev[0]->page; |
1917 | mapped_buffer = kmap_atomic(page); | 1929 | mapped_buffer = kmap_atomic(page); |
@@ -1934,7 +1946,7 @@ static int scrub_checksum_super(struct scrub_block *sblock) | |||
1934 | for (;;) { | 1946 | for (;;) { |
1935 | u64 l = min_t(u64, len, mapped_size); | 1947 | u64 l = min_t(u64, len, mapped_size); |
1936 | 1948 | ||
1937 | crc = btrfs_csum_data(p, crc, l); | 1949 | crypto_shash_update(shash, p, l); |
1938 | kunmap_atomic(mapped_buffer); | 1950 | kunmap_atomic(mapped_buffer); |
1939 | len -= l; | 1951 | len -= l; |
1940 | if (len == 0) | 1952 | if (len == 0) |
@@ -1948,7 +1960,7 @@ static int scrub_checksum_super(struct scrub_block *sblock) | |||
1948 | p = mapped_buffer; | 1960 | p = mapped_buffer; |
1949 | } | 1961 | } |
1950 | 1962 | ||
1951 | btrfs_csum_final(crc, calculated_csum); | 1963 | crypto_shash_final(shash, calculated_csum); |
1952 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) | 1964 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) |
1953 | ++fail_cor; | 1965 | ++fail_cor; |
1954 | 1966 | ||
@@ -2448,7 +2460,7 @@ static int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u8 *csum) | |||
2448 | ASSERT(index < UINT_MAX); | 2460 | ASSERT(index < UINT_MAX); |
2449 | 2461 | ||
2450 | num_sectors = sum->len / sctx->fs_info->sectorsize; | 2462 | num_sectors = sum->len / sctx->fs_info->sectorsize; |
2451 | memcpy(csum, sum->sums + index, sctx->csum_size); | 2463 | memcpy(csum, sum->sums + index * sctx->csum_size, sctx->csum_size); |
2452 | if (index == num_sectors - 1) { | 2464 | if (index == num_sectors - 1) { |
2453 | list_del(&sum->list); | 2465 | list_del(&sum->list); |
2454 | kfree(sum); | 2466 | kfree(sum); |
@@ -2660,18 +2672,18 @@ static int get_raid56_logic_offset(u64 physical, int num, | |||
2660 | u64 last_offset; | 2672 | u64 last_offset; |
2661 | u32 stripe_index; | 2673 | u32 stripe_index; |
2662 | u32 rot; | 2674 | u32 rot; |
2675 | const int data_stripes = nr_data_stripes(map); | ||
2663 | 2676 | ||
2664 | last_offset = (physical - map->stripes[num].physical) * | 2677 | last_offset = (physical - map->stripes[num].physical) * data_stripes; |
2665 | nr_data_stripes(map); | ||
2666 | if (stripe_start) | 2678 | if (stripe_start) |
2667 | *stripe_start = last_offset; | 2679 | *stripe_start = last_offset; |
2668 | 2680 | ||
2669 | *offset = last_offset; | 2681 | *offset = last_offset; |
2670 | for (i = 0; i < nr_data_stripes(map); i++) { | 2682 | for (i = 0; i < data_stripes; i++) { |
2671 | *offset = last_offset + i * map->stripe_len; | 2683 | *offset = last_offset + i * map->stripe_len; |
2672 | 2684 | ||
2673 | stripe_nr = div64_u64(*offset, map->stripe_len); | 2685 | stripe_nr = div64_u64(*offset, map->stripe_len); |
2674 | stripe_nr = div_u64(stripe_nr, nr_data_stripes(map)); | 2686 | stripe_nr = div_u64(stripe_nr, data_stripes); |
2675 | 2687 | ||
2676 | /* Work out the disk rotation on this stripe-set */ | 2688 | /* Work out the disk rotation on this stripe-set */ |
2677 | stripe_nr = div_u64_rem(stripe_nr, map->num_stripes, &rot); | 2689 | stripe_nr = div_u64_rem(stripe_nr, map->num_stripes, &rot); |
@@ -3079,7 +3091,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
3079 | offset = map->stripe_len * (num / map->sub_stripes); | 3091 | offset = map->stripe_len * (num / map->sub_stripes); |
3080 | increment = map->stripe_len * factor; | 3092 | increment = map->stripe_len * factor; |
3081 | mirror_num = num % map->sub_stripes + 1; | 3093 | mirror_num = num % map->sub_stripes + 1; |
3082 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) { | 3094 | } else if (map->type & BTRFS_BLOCK_GROUP_RAID1_MASK) { |
3083 | increment = map->stripe_len; | 3095 | increment = map->stripe_len; |
3084 | mirror_num = num % map->num_stripes + 1; | 3096 | mirror_num = num % map->num_stripes + 1; |
3085 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { | 3097 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
@@ -3410,15 +3422,15 @@ static noinline_for_stack int scrub_chunk(struct scrub_ctx *sctx, | |||
3410 | struct btrfs_block_group_cache *cache) | 3422 | struct btrfs_block_group_cache *cache) |
3411 | { | 3423 | { |
3412 | struct btrfs_fs_info *fs_info = sctx->fs_info; | 3424 | struct btrfs_fs_info *fs_info = sctx->fs_info; |
3413 | struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; | 3425 | struct extent_map_tree *map_tree = &fs_info->mapping_tree; |
3414 | struct map_lookup *map; | 3426 | struct map_lookup *map; |
3415 | struct extent_map *em; | 3427 | struct extent_map *em; |
3416 | int i; | 3428 | int i; |
3417 | int ret = 0; | 3429 | int ret = 0; |
3418 | 3430 | ||
3419 | read_lock(&map_tree->map_tree.lock); | 3431 | read_lock(&map_tree->lock); |
3420 | em = lookup_extent_mapping(&map_tree->map_tree, chunk_offset, 1); | 3432 | em = lookup_extent_mapping(map_tree, chunk_offset, 1); |
3421 | read_unlock(&map_tree->map_tree.lock); | 3433 | read_unlock(&map_tree->lock); |
3422 | 3434 | ||
3423 | if (!em) { | 3435 | if (!em) { |
3424 | /* | 3436 | /* |