diff options
Diffstat (limited to 'fs/btrfs/check-integrity.c')
-rw-r--r-- | fs/btrfs/check-integrity.c | 163 |
1 files changed, 65 insertions, 98 deletions
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index cb7f3fe9c9f6..d897ef803b3b 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c | |||
@@ -94,6 +94,7 @@ | |||
94 | #include <linux/mutex.h> | 94 | #include <linux/mutex.h> |
95 | #include <linux/genhd.h> | 95 | #include <linux/genhd.h> |
96 | #include <linux/blkdev.h> | 96 | #include <linux/blkdev.h> |
97 | #include <linux/vmalloc.h> | ||
97 | #include "ctree.h" | 98 | #include "ctree.h" |
98 | #include "disk-io.h" | 99 | #include "disk-io.h" |
99 | #include "hash.h" | 100 | #include "hash.h" |
@@ -326,9 +327,6 @@ static int btrfsic_handle_extent_data(struct btrfsic_state *state, | |||
326 | static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len, | 327 | static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len, |
327 | struct btrfsic_block_data_ctx *block_ctx_out, | 328 | struct btrfsic_block_data_ctx *block_ctx_out, |
328 | int mirror_num); | 329 | int mirror_num); |
329 | static int btrfsic_map_superblock(struct btrfsic_state *state, u64 bytenr, | ||
330 | u32 len, struct block_device *bdev, | ||
331 | struct btrfsic_block_data_ctx *block_ctx_out); | ||
332 | static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx); | 330 | static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx); |
333 | static int btrfsic_read_block(struct btrfsic_state *state, | 331 | static int btrfsic_read_block(struct btrfsic_state *state, |
334 | struct btrfsic_block_data_ctx *block_ctx); | 332 | struct btrfsic_block_data_ctx *block_ctx); |
@@ -1326,24 +1324,25 @@ static int btrfsic_create_link_to_next_block( | |||
1326 | l = NULL; | 1324 | l = NULL; |
1327 | next_block->generation = BTRFSIC_GENERATION_UNKNOWN; | 1325 | next_block->generation = BTRFSIC_GENERATION_UNKNOWN; |
1328 | } else { | 1326 | } else { |
1329 | if (next_block->logical_bytenr != next_bytenr && | 1327 | if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) { |
1330 | !(!next_block->is_metadata && | 1328 | if (next_block->logical_bytenr != next_bytenr && |
1331 | 0 == next_block->logical_bytenr)) { | 1329 | !(!next_block->is_metadata && |
1332 | printk(KERN_INFO | 1330 | 0 == next_block->logical_bytenr)) |
1333 | "Referenced block @%llu (%s/%llu/%d)" | 1331 | printk(KERN_INFO |
1334 | " found in hash table, %c," | 1332 | "Referenced block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n", |
1335 | " bytenr mismatch (!= stored %llu).\n", | 1333 | next_bytenr, next_block_ctx->dev->name, |
1336 | next_bytenr, next_block_ctx->dev->name, | 1334 | next_block_ctx->dev_bytenr, *mirror_nump, |
1337 | next_block_ctx->dev_bytenr, *mirror_nump, | 1335 | btrfsic_get_block_type(state, |
1338 | btrfsic_get_block_type(state, next_block), | 1336 | next_block), |
1339 | next_block->logical_bytenr); | 1337 | next_block->logical_bytenr); |
1340 | } else if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) | 1338 | else |
1341 | printk(KERN_INFO | 1339 | printk(KERN_INFO |
1342 | "Referenced block @%llu (%s/%llu/%d)" | 1340 | "Referenced block @%llu (%s/%llu/%d) found in hash table, %c.\n", |
1343 | " found in hash table, %c.\n", | 1341 | next_bytenr, next_block_ctx->dev->name, |
1344 | next_bytenr, next_block_ctx->dev->name, | 1342 | next_block_ctx->dev_bytenr, *mirror_nump, |
1345 | next_block_ctx->dev_bytenr, *mirror_nump, | 1343 | btrfsic_get_block_type(state, |
1346 | btrfsic_get_block_type(state, next_block)); | 1344 | next_block)); |
1345 | } | ||
1347 | next_block->logical_bytenr = next_bytenr; | 1346 | next_block->logical_bytenr = next_bytenr; |
1348 | 1347 | ||
1349 | next_block->mirror_num = *mirror_nump; | 1348 | next_block->mirror_num = *mirror_nump; |
@@ -1529,7 +1528,9 @@ static int btrfsic_handle_extent_data( | |||
1529 | return -1; | 1528 | return -1; |
1530 | } | 1529 | } |
1531 | if (!block_was_created) { | 1530 | if (!block_was_created) { |
1532 | if (next_block->logical_bytenr != next_bytenr && | 1531 | if ((state->print_mask & |
1532 | BTRFSIC_PRINT_MASK_VERBOSE) && | ||
1533 | next_block->logical_bytenr != next_bytenr && | ||
1533 | !(!next_block->is_metadata && | 1534 | !(!next_block->is_metadata && |
1534 | 0 == next_block->logical_bytenr)) { | 1535 | 0 == next_block->logical_bytenr)) { |
1535 | printk(KERN_INFO | 1536 | printk(KERN_INFO |
@@ -1607,25 +1608,6 @@ static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len, | |||
1607 | return ret; | 1608 | return ret; |
1608 | } | 1609 | } |
1609 | 1610 | ||
1610 | static int btrfsic_map_superblock(struct btrfsic_state *state, u64 bytenr, | ||
1611 | u32 len, struct block_device *bdev, | ||
1612 | struct btrfsic_block_data_ctx *block_ctx_out) | ||
1613 | { | ||
1614 | block_ctx_out->dev = btrfsic_dev_state_lookup(bdev); | ||
1615 | block_ctx_out->dev_bytenr = bytenr; | ||
1616 | block_ctx_out->start = bytenr; | ||
1617 | block_ctx_out->len = len; | ||
1618 | block_ctx_out->datav = NULL; | ||
1619 | block_ctx_out->pagev = NULL; | ||
1620 | block_ctx_out->mem_to_free = NULL; | ||
1621 | if (NULL != block_ctx_out->dev) { | ||
1622 | return 0; | ||
1623 | } else { | ||
1624 | printk(KERN_INFO "btrfsic: error, cannot lookup dev (#2)!\n"); | ||
1625 | return -ENXIO; | ||
1626 | } | ||
1627 | } | ||
1628 | |||
1629 | static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx) | 1611 | static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx) |
1630 | { | 1612 | { |
1631 | if (block_ctx->mem_to_free) { | 1613 | if (block_ctx->mem_to_free) { |
@@ -1901,25 +1883,26 @@ again: | |||
1901 | dev_state, | 1883 | dev_state, |
1902 | dev_bytenr); | 1884 | dev_bytenr); |
1903 | } | 1885 | } |
1904 | if (block->logical_bytenr != bytenr && | 1886 | if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) { |
1905 | !(!block->is_metadata && | 1887 | if (block->logical_bytenr != bytenr && |
1906 | block->logical_bytenr == 0)) | 1888 | !(!block->is_metadata && |
1907 | printk(KERN_INFO | 1889 | block->logical_bytenr == 0)) |
1908 | "Written block @%llu (%s/%llu/%d)" | 1890 | printk(KERN_INFO |
1909 | " found in hash table, %c," | 1891 | "Written block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n", |
1910 | " bytenr mismatch" | 1892 | bytenr, dev_state->name, |
1911 | " (!= stored %llu).\n", | 1893 | dev_bytenr, |
1912 | bytenr, dev_state->name, dev_bytenr, | 1894 | block->mirror_num, |
1913 | block->mirror_num, | 1895 | btrfsic_get_block_type(state, |
1914 | btrfsic_get_block_type(state, block), | 1896 | block), |
1915 | block->logical_bytenr); | 1897 | block->logical_bytenr); |
1916 | else if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) | 1898 | else |
1917 | printk(KERN_INFO | 1899 | printk(KERN_INFO |
1918 | "Written block @%llu (%s/%llu/%d)" | 1900 | "Written block @%llu (%s/%llu/%d) found in hash table, %c.\n", |
1919 | " found in hash table, %c.\n", | 1901 | bytenr, dev_state->name, |
1920 | bytenr, dev_state->name, dev_bytenr, | 1902 | dev_bytenr, block->mirror_num, |
1921 | block->mirror_num, | 1903 | btrfsic_get_block_type(state, |
1922 | btrfsic_get_block_type(state, block)); | 1904 | block)); |
1905 | } | ||
1923 | block->logical_bytenr = bytenr; | 1906 | block->logical_bytenr = bytenr; |
1924 | } else { | 1907 | } else { |
1925 | if (num_pages * PAGE_CACHE_SIZE < | 1908 | if (num_pages * PAGE_CACHE_SIZE < |
@@ -2002,24 +1985,13 @@ again: | |||
2002 | } | 1985 | } |
2003 | } | 1986 | } |
2004 | 1987 | ||
2005 | if (block->is_superblock) | ||
2006 | ret = btrfsic_map_superblock(state, bytenr, | ||
2007 | processed_len, | ||
2008 | bdev, &block_ctx); | ||
2009 | else | ||
2010 | ret = btrfsic_map_block(state, bytenr, processed_len, | ||
2011 | &block_ctx, 0); | ||
2012 | if (ret) { | ||
2013 | printk(KERN_INFO | ||
2014 | "btrfsic: btrfsic_map_block(root @%llu)" | ||
2015 | " failed!\n", bytenr); | ||
2016 | goto continue_loop; | ||
2017 | } | ||
2018 | block_ctx.datav = mapped_datav; | ||
2019 | /* the following is required in case of writes to mirrors, | ||
2020 | * use the same that was used for the lookup */ | ||
2021 | block_ctx.dev = dev_state; | 1988 | block_ctx.dev = dev_state; |
2022 | block_ctx.dev_bytenr = dev_bytenr; | 1989 | block_ctx.dev_bytenr = dev_bytenr; |
1990 | block_ctx.start = bytenr; | ||
1991 | block_ctx.len = processed_len; | ||
1992 | block_ctx.pagev = NULL; | ||
1993 | block_ctx.mem_to_free = NULL; | ||
1994 | block_ctx.datav = mapped_datav; | ||
2023 | 1995 | ||
2024 | if (is_metadata || state->include_extent_data) { | 1996 | if (is_metadata || state->include_extent_data) { |
2025 | block->never_written = 0; | 1997 | block->never_written = 0; |
@@ -2133,10 +2105,6 @@ again: | |||
2133 | /* this is getting ugly for the | 2105 | /* this is getting ugly for the |
2134 | * include_extent_data case... */ | 2106 | * include_extent_data case... */ |
2135 | bytenr = 0; /* unknown */ | 2107 | bytenr = 0; /* unknown */ |
2136 | block_ctx.start = bytenr; | ||
2137 | block_ctx.len = processed_len; | ||
2138 | block_ctx.mem_to_free = NULL; | ||
2139 | block_ctx.pagev = NULL; | ||
2140 | } else { | 2108 | } else { |
2141 | processed_len = state->metablock_size; | 2109 | processed_len = state->metablock_size; |
2142 | bytenr = btrfs_stack_header_bytenr( | 2110 | bytenr = btrfs_stack_header_bytenr( |
@@ -2149,22 +2117,15 @@ again: | |||
2149 | "Written block @%llu (%s/%llu/?)" | 2117 | "Written block @%llu (%s/%llu/?)" |
2150 | " !found in hash table, M.\n", | 2118 | " !found in hash table, M.\n", |
2151 | bytenr, dev_state->name, dev_bytenr); | 2119 | bytenr, dev_state->name, dev_bytenr); |
2152 | |||
2153 | ret = btrfsic_map_block(state, bytenr, processed_len, | ||
2154 | &block_ctx, 0); | ||
2155 | if (ret) { | ||
2156 | printk(KERN_INFO | ||
2157 | "btrfsic: btrfsic_map_block(root @%llu)" | ||
2158 | " failed!\n", | ||
2159 | dev_bytenr); | ||
2160 | goto continue_loop; | ||
2161 | } | ||
2162 | } | 2120 | } |
2163 | block_ctx.datav = mapped_datav; | 2121 | |
2164 | /* the following is required in case of writes to mirrors, | ||
2165 | * use the same that was used for the lookup */ | ||
2166 | block_ctx.dev = dev_state; | 2122 | block_ctx.dev = dev_state; |
2167 | block_ctx.dev_bytenr = dev_bytenr; | 2123 | block_ctx.dev_bytenr = dev_bytenr; |
2124 | block_ctx.start = bytenr; | ||
2125 | block_ctx.len = processed_len; | ||
2126 | block_ctx.pagev = NULL; | ||
2127 | block_ctx.mem_to_free = NULL; | ||
2128 | block_ctx.datav = mapped_datav; | ||
2168 | 2129 | ||
2169 | block = btrfsic_block_alloc(); | 2130 | block = btrfsic_block_alloc(); |
2170 | if (NULL == block) { | 2131 | if (NULL == block) { |
@@ -3130,10 +3091,13 @@ int btrfsic_mount(struct btrfs_root *root, | |||
3130 | root->sectorsize, PAGE_CACHE_SIZE); | 3091 | root->sectorsize, PAGE_CACHE_SIZE); |
3131 | return -1; | 3092 | return -1; |
3132 | } | 3093 | } |
3133 | state = kzalloc(sizeof(*state), GFP_NOFS); | 3094 | state = kzalloc(sizeof(*state), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); |
3134 | if (NULL == state) { | 3095 | if (!state) { |
3135 | printk(KERN_INFO "btrfs check-integrity: kmalloc() failed!\n"); | 3096 | state = vzalloc(sizeof(*state)); |
3136 | return -1; | 3097 | if (!state) { |
3098 | printk(KERN_INFO "btrfs check-integrity: vzalloc() failed!\n"); | ||
3099 | return -1; | ||
3100 | } | ||
3137 | } | 3101 | } |
3138 | 3102 | ||
3139 | if (!btrfsic_is_initialized) { | 3103 | if (!btrfsic_is_initialized) { |
@@ -3277,5 +3241,8 @@ void btrfsic_unmount(struct btrfs_root *root, | |||
3277 | 3241 | ||
3278 | mutex_unlock(&btrfsic_mutex); | 3242 | mutex_unlock(&btrfsic_mutex); |
3279 | 3243 | ||
3280 | kfree(state); | 3244 | if (is_vmalloc_addr(state)) |
3245 | vfree(state); | ||
3246 | else | ||
3247 | kfree(state); | ||
3281 | } | 3248 | } |