diff options
author | Miguel <miguel.filipe@gmail.com> | 2008-04-11 15:45:51 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:01 -0400 |
commit | a5eb62e345fc1818d0d8b6181463200a9e8dfe39 (patch) | |
tree | 2e67b0628c8312d941f52edadc6c49bd8ac4c914 /fs | |
parent | 587f77043a1c86e2a7900ff2ce86bef3c1f4e075 (diff) |
Btrfs: Endianess bug fix for v0.13 with kernels
Fix for a endianess BUG when using btrfs v0.13 with kernels older than 2.6.23
Problem:
Has of v0.13, btrfs-progs is using crc32c.c equivalent to the one found on
linux-2.6.23/lib/libcrc32c.c Since crc32c_le() changed in linux-2.6.23, when
running btrfs v0.13 with older kernels we have a missmatch between the versions
of crc32c_le() from btrfs-progs and libcrc32c in the kernel. This missmatch
causes a bug when using btrfs on big endian machines.
Solution:
btrfs_crc32c() macro that when compiling for kernels older than 2.6.23, does
endianess conversion to parameters and return value of crc32c().
This endianess conversion nullifies the differences in implementation
of crc32c_le().
If kernel 2.6.23 or better, it calls crc32c().
Signed-off-by: Miguel Sousa Filipe <miguel.filipe@gmail.com>
---
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/crc32c.h | 17 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 12 |
3 files changed, 24 insertions, 9 deletions
diff --git a/fs/btrfs/crc32c.h b/fs/btrfs/crc32c.h new file mode 100644 index 000000000000..a93255b4ee27 --- /dev/null +++ b/fs/btrfs/crc32c.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <asm/byteorder.h> | ||
2 | #include <linux/crc32c.h> | ||
3 | #include <linux/version.h> | ||
4 | |||
5 | /** | ||
6 | * implementation of crc32c_le() changed in linux-2.6.23, | ||
7 | * has of v0.13 btrfs-progs is using the latest version. | ||
8 | * We must workaround older implementations of crc32c_le() | ||
9 | * found on older kernel versions. | ||
10 | */ | ||
11 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) | ||
12 | #define btrfs_crc32c(seed, data, length) \ | ||
13 | __cpu_to_le32( crc32c( __le32_to_cpu(seed), data, length) ) | ||
14 | #else | ||
15 | #define btrfs_crc32c(seed, data, length) \ | ||
16 | crc32c(seed, data, length) | ||
17 | #endif | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e22960e23501..0bfcc31d94d7 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -18,13 +18,13 @@ | |||
18 | 18 | ||
19 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
20 | #include <linux/blkdev.h> | 20 | #include <linux/blkdev.h> |
21 | #include <linux/crc32c.h> | ||
22 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
23 | #include <linux/swap.h> | 22 | #include <linux/swap.h> |
24 | #include <linux/radix-tree.h> | 23 | #include <linux/radix-tree.h> |
25 | #include <linux/writeback.h> | 24 | #include <linux/writeback.h> |
26 | #include <linux/buffer_head.h> // for block_sync_page | 25 | #include <linux/buffer_head.h> // for block_sync_page |
27 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include "crc32c.h" | ||
28 | #include "ctree.h" | 28 | #include "ctree.h" |
29 | #include "disk-io.h" | 29 | #include "disk-io.h" |
30 | #include "transaction.h" | 30 | #include "transaction.h" |
@@ -100,7 +100,7 @@ out: | |||
100 | 100 | ||
101 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) | 101 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) |
102 | { | 102 | { |
103 | return crc32c(seed, data, len); | 103 | return btrfs_crc32c(seed, data, len); |
104 | } | 104 | } |
105 | 105 | ||
106 | void btrfs_csum_final(u32 crc, char *result) | 106 | void btrfs_csum_final(u32 crc, char *result) |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 283b08a32a43..a056a2df689a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -15,11 +15,10 @@ | |||
15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | |||
19 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
20 | #include <linux/crc32c.h> | ||
21 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
22 | #include "hash.h" | 20 | #include "hash.h" |
21 | #include "crc32c.h" | ||
23 | #include "ctree.h" | 22 | #include "ctree.h" |
24 | #include "disk-io.h" | 23 | #include "disk-io.h" |
25 | #include "print-tree.h" | 24 | #include "print-tree.h" |
@@ -398,16 +397,15 @@ static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, | |||
398 | u32 high_crc = ~(u32)0; | 397 | u32 high_crc = ~(u32)0; |
399 | u32 low_crc = ~(u32)0; | 398 | u32 low_crc = ~(u32)0; |
400 | __le64 lenum; | 399 | __le64 lenum; |
401 | |||
402 | lenum = cpu_to_le64(root_objectid); | 400 | lenum = cpu_to_le64(root_objectid); |
403 | high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); | 401 | high_crc = btrfs_crc32c(high_crc, &lenum, sizeof(lenum)); |
404 | lenum = cpu_to_le64(ref_generation); | 402 | lenum = cpu_to_le64(ref_generation); |
405 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); | 403 | low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum)); |
406 | if (owner >= BTRFS_FIRST_FREE_OBJECTID) { | 404 | if (owner >= BTRFS_FIRST_FREE_OBJECTID) { |
407 | lenum = cpu_to_le64(owner); | 405 | lenum = cpu_to_le64(owner); |
408 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); | 406 | low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum)); |
409 | lenum = cpu_to_le64(owner_offset); | 407 | lenum = cpu_to_le64(owner_offset); |
410 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); | 408 | low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum)); |
411 | } | 409 | } |
412 | return ((u64)high_crc << 32) | (u64)low_crc; | 410 | return ((u64)high_crc << 32) | (u64)low_crc; |
413 | } | 411 | } |