aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel <miguel.filipe@gmail.com>2008-04-11 15:45:51 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commita5eb62e345fc1818d0d8b6181463200a9e8dfe39 (patch)
tree2e67b0628c8312d941f52edadc6c49bd8ac4c914
parent587f77043a1c86e2a7900ff2ce86bef3c1f4e075 (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>
-rw-r--r--fs/btrfs/crc32c.h17
-rw-r--r--fs/btrfs/disk-io.c4
-rw-r--r--fs/btrfs/extent-tree.c12
3 files changed, 24 insertions, 9 deletions
diff --git a/fs/btrfs/crc32c.h b/fs/btrfs/crc32c.h
new file mode 100644
index 00000000000..a93255b4ee2
--- /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 e22960e2350..0bfcc31d94d 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
101u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) 101u32 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
106void btrfs_csum_final(u32 crc, char *result) 106void btrfs_csum_final(u32 crc, char *result)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 283b08a32a4..a056a2df689 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}