mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-14 17:50:58 +00:00
8871a0eaa9
The first problem is that these SETGET macros lose typing information, and therefore can't see the 'packed' attribute and therefore take unaligned access SIGBUS signals on sparc64 when trying to derefernce the member. The next problem is a similar issue in btrfs_name_hash(). This gets passed things like &key.offset which is a member of a packed structure, losing this packed'ness information btrfs_name_hash() performs a potentially unaligned memory access, again resulting in a SIGBUS.
106 lines
2.3 KiB
C
106 lines
2.3 KiB
C
/*
|
|
* Copyright (C) 2007 Oracle. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License v2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 021110-1307, USA.
|
|
*/
|
|
|
|
/*
|
|
* Original copy from:
|
|
* linux/fs/ext3/hash.c
|
|
*
|
|
* Copyright (C) 2002 by Theodore Ts'o
|
|
*
|
|
* This file is released under the GPL v2.
|
|
*
|
|
* This file may be redistributed under the terms of the GNU Public
|
|
* License.
|
|
*/
|
|
|
|
#include "kerncompat.h"
|
|
#define DELTA 0x9E3779B9
|
|
|
|
static void TEA_transform(__u32 buf[2], __u32 const in[])
|
|
{
|
|
__u32 sum = 0;
|
|
__u32 b0 = buf[0], b1 = buf[1];
|
|
__u32 a = in[0], b = in[1], c = in[2], d = in[3];
|
|
int n = 16;
|
|
|
|
do {
|
|
sum += DELTA;
|
|
b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
|
|
b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
|
|
} while(--n);
|
|
|
|
buf[0] += b0;
|
|
buf[1] += b1;
|
|
}
|
|
|
|
static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
|
|
{
|
|
__u32 pad, val;
|
|
int i;
|
|
|
|
pad = (__u32)len | ((__u32)len << 8);
|
|
pad |= pad << 16;
|
|
|
|
val = pad;
|
|
if (len > num*4)
|
|
len = num * 4;
|
|
for (i=0; i < len; i++) {
|
|
if ((i % 4) == 0)
|
|
val = pad;
|
|
val = msg[i] + (val << 8);
|
|
if ((i % 4) == 3) {
|
|
*buf++ = val;
|
|
val = pad;
|
|
num--;
|
|
}
|
|
}
|
|
if (--num >= 0)
|
|
*buf++ = val;
|
|
while (--num >= 0)
|
|
*buf++ = pad;
|
|
}
|
|
|
|
u64 btrfs_name_hash(const char *name, int len)
|
|
{
|
|
__u32 hash;
|
|
__u32 minor_hash = 0;
|
|
const char *p;
|
|
__u32 in[8], buf[2];
|
|
u64 hash_result;
|
|
|
|
/* Initialize the default seed for the hash checksum functions */
|
|
buf[0] = 0x67452301;
|
|
buf[1] = 0xefcdab89;
|
|
buf[2] = 0x98badcfe;
|
|
buf[3] = 0x10325476;
|
|
|
|
p = name;
|
|
while (len > 0) {
|
|
str2hashbuf(p, len, in, 4);
|
|
TEA_transform(buf, in);
|
|
len -= 16;
|
|
p += 16;
|
|
}
|
|
hash = buf[0];
|
|
minor_hash = buf[1];
|
|
hash_result = buf[0];
|
|
hash_result <<= 32;
|
|
hash_result |= buf[1];
|
|
return hash_result;
|
|
}
|