Commit a5eb62e3 authored by Miguel's avatar Miguel Committed by Chris Mason

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: default avatarMiguel Sousa Filipe <miguel.filipe@gmail.com>
---
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 587f7704
#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), data, length) )
#else
#define btrfs_crc32c(seed, data, length) \
crc32c(seed, data, length)
#endif
...@@ -18,13 +18,13 @@ ...@@ -18,13 +18,13 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/crc32c.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/radix-tree.h> #include <linux/radix-tree.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/buffer_head.h> // for block_sync_page #include <linux/buffer_head.h> // for block_sync_page
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include "crc32c.h"
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"
...@@ -100,7 +100,7 @@ struct extent_map *btree_get_extent(struct inode *inode, struct page *page, ...@@ -100,7 +100,7 @@ struct extent_map *btree_get_extent(struct inode *inode, struct page *page,
u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) 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) void btrfs_csum_final(u32 crc, char *result)
......
...@@ -15,11 +15,10 @@ ...@@ -15,11 +15,10 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA. * Boston, MA 021110-1307, USA.
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/crc32c.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include "hash.h" #include "hash.h"
#include "crc32c.h"
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "print-tree.h" #include "print-tree.h"
...@@ -398,16 +397,15 @@ static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, ...@@ -398,16 +397,15 @@ static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation,
u32 high_crc = ~(u32)0; u32 high_crc = ~(u32)0;
u32 low_crc = ~(u32)0; u32 low_crc = ~(u32)0;
__le64 lenum; __le64 lenum;
lenum = cpu_to_le64(root_objectid); 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); 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) { if (owner >= BTRFS_FIRST_FREE_OBJECTID) {
lenum = cpu_to_le64(owner); 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); 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; return ((u64)high_crc << 32) | (u64)low_crc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment