aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index dfd5ba05ce45..3eb7c2576fe5 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -176,7 +176,9 @@ void btrfs_csum_final(u32 crc, char *result)
176static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, 176static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
177 int verify) 177 int verify)
178{ 178{
179 char result[BTRFS_CRC32_SIZE]; 179 u16 csum_size =
180 btrfs_super_csum_size(&root->fs_info->super_copy);
181 char *result = NULL;
180 unsigned long len; 182 unsigned long len;
181 unsigned long cur_len; 183 unsigned long cur_len;
182 unsigned long offset = BTRFS_CSUM_SIZE; 184 unsigned long offset = BTRFS_CSUM_SIZE;
@@ -186,6 +188,7 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
186 unsigned long map_len; 188 unsigned long map_len;
187 int err; 189 int err;
188 u32 crc = ~(u32)0; 190 u32 crc = ~(u32)0;
191 unsigned long inline_result;
189 192
190 len = buf->len - offset; 193 len = buf->len - offset;
191 while(len > 0) { 194 while(len > 0) {
@@ -204,25 +207,37 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
204 offset += cur_len; 207 offset += cur_len;
205 unmap_extent_buffer(buf, map_token, KM_USER0); 208 unmap_extent_buffer(buf, map_token, KM_USER0);
206 } 209 }
210 if (csum_size > sizeof(inline_result)) {
211 result = kzalloc(csum_size * sizeof(char), GFP_NOFS);
212 if (!result)
213 return 1;
214 } else {
215 result = (char *)&inline_result;
216 }
217
207 btrfs_csum_final(crc, result); 218 btrfs_csum_final(crc, result);
208 219
209 if (verify) { 220 if (verify) {
210 /* FIXME, this is not good */ 221 /* FIXME, this is not good */
211 if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) { 222 if (memcmp_extent_buffer(buf, result, 0, csum_size)) {
212 u32 val; 223 u32 val;
213 u32 found = 0; 224 u32 found = 0;
214 memcpy(&found, result, BTRFS_CRC32_SIZE); 225 memcpy(&found, result, csum_size);
215 226
216 read_extent_buffer(buf, &val, 0, BTRFS_CRC32_SIZE); 227 read_extent_buffer(buf, &val, 0, csum_size);
217 printk("btrfs: %s checksum verify failed on %llu " 228 printk("btrfs: %s checksum verify failed on %llu "
218 "wanted %X found %X level %d\n", 229 "wanted %X found %X level %d\n",
219 root->fs_info->sb->s_id, 230 root->fs_info->sb->s_id,
220 buf->start, val, found, btrfs_header_level(buf)); 231 buf->start, val, found, btrfs_header_level(buf));
232 if (result != (char *)&inline_result)
233 kfree(result);
221 return 1; 234 return 1;
222 } 235 }
223 } else { 236 } else {
224 write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE); 237 write_extent_buffer(buf, result, 0, csum_size);
225 } 238 }
239 if (result != (char *)&inline_result)
240 kfree(result);
226 return 0; 241 return 0;
227} 242}
228 243