[Btrfs-devel] [PATCH] Endianess bug fix for v0.13 with kernels older than 2.6.23.

Miguel Figueiredo Mascarenhas Sousa Filipe miguel.filipe at gmail.com
Mon Mar 24 05:44:54 PDT 2008


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 at gmail.com>
---
diff -r 5c0d66b6195b -r e8daa3967ff4 crc32c.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crc32c.h	Mon Mar 24 12:31:37 2008 +0000
@@ -0,0 +1,17 @@
+#include <asm/byteorder.h>
+#include <linux/crc32c.h>
+#include <linux/version.h>
+
+/**
+ * implementation of crc32c_le() changed in linux-2.6.23,
+ * has of v0.13 btrfs-progs is using the latest version.
+ * We must workaround older implementations of crc32c_le()
+ * found on older kernel versions.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+#define btrfs_crc32c(seed, data, length) \
+	__cpu_to_le32( crc32c( __le32_to_cpu(seed), (unsigned char const
*)data, length) )
+#else
+#define btrfs_crc32c(seed, data, length) \
+	crc32c(seed, (unsigned char const *)data, length)
+#endif
diff -r 5c0d66b6195b -r e8daa3967ff4 disk-io.c
--- a/disk-io.c	Mon Mar 24 01:03:20 2008 +0000
+++ b/disk-io.c	Mon Mar 24 12:31:37 2008 +0000
@@ -18,12 +18,12 @@

 #include <linux/fs.h>
 #include <linux/blkdev.h>
-#include <linux/crc32c.h>
 #include <linux/scatterlist.h>
 #include <linux/swap.h>
 #include <linux/radix-tree.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h> // for block_sync_page
+#include "crc32c.h"
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
@@ -108,7 +108,7 @@ out:

 u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len)
 {
-	return crc32c(seed, data, len);
+	return btrfs_crc32c(seed, data, len);
 }

 void btrfs_csum_final(u32 crc, char *result)
diff -r 5c0d66b6195b -r e8daa3967ff4 extent-tree.c
--- a/extent-tree.c	Mon Mar 24 01:03:20 2008 +0000
+++ b/extent-tree.c	Mon Mar 24 12:31:37 2008 +0000
@@ -17,9 +17,9 @@
  */

 #include <linux/sched.h>
-#include <linux/crc32c.h>
 #include <linux/pagemap.h>
 #include "hash.h"
+#include "crc32c.h"
 #include "ctree.h"
 #include "disk-io.h"
 #include "print-tree.h"
@@ -402,14 +402,14 @@ static u64 hash_extent_ref(u64 root_obje
 	__le64 lenum;

 	lenum = cpu_to_le64(root_objectid);
-	high_crc = crc32c(high_crc, &lenum, sizeof(lenum));
+	high_crc = btrfs_crc32c(high_crc, &lenum, sizeof(lenum));
 	lenum = cpu_to_le64(ref_generation);
-	low_crc = crc32c(low_crc, &lenum, sizeof(lenum));
+	low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum));
 	if (owner >= BTRFS_FIRST_FREE_OBJECTID) {
 		lenum = cpu_to_le64(owner);
-		low_crc = crc32c(low_crc, &lenum, sizeof(lenum));
+		low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum));
 		lenum = cpu_to_le64(owner_offset);
-		low_crc = crc32c(low_crc, &lenum, sizeof(lenum));
+		low_crc = btrfs_crc32c(low_crc, &lenum, sizeof(lenum));
 	}
 	return ((u64)high_crc << 32) | (u64)low_crc;
 }


-- 
Miguel Sousa Filipe



More information about the Btrfs-devel mailing list