2012-11-29 08:28:09 +04:00
/*
2012-11-14 11:59:04 +04:00
* fs / f2fs / hash . c
*
* Copyright ( c ) 2012 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com/
*
* Portions of this code from linux / fs / ext3 / hash . c
*
* Copyright ( C ) 2002 by Theodore Ts ' o
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/types.h>
# include <linux/fs.h>
# include <linux/f2fs_fs.h>
# include <linux/cryptohash.h>
# include <linux/pagemap.h>
# include "f2fs.h"
/*
* Hashing code copied from ext3
*/
# define DELTA 0x9E3779B9
static void TEA_transform ( unsigned int buf [ 4 ] , unsigned int 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 ;
}
2014-08-29 11:26:50 +04:00
static void str2hashbuf ( const unsigned char * msg , size_t len ,
unsigned int * buf , int num )
2012-11-14 11:59:04 +04:00
{
unsigned 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 ;
}
2014-06-24 14:21:23 +04:00
f2fs_hash_t f2fs_dentry_hash ( const struct qstr * name_info )
2012-11-14 11:59:04 +04:00
{
2012-12-26 09:39:50 +04:00
__u32 hash ;
2012-11-14 11:59:04 +04:00
f2fs_hash_t f2fs_hash ;
2014-08-29 11:26:50 +04:00
const unsigned char * p ;
2012-11-14 11:59:04 +04:00
__u32 in [ 8 ] , buf [ 4 ] ;
2014-08-29 11:26:50 +04:00
const unsigned char * name = name_info - > name ;
2014-06-24 14:21:23 +04:00
size_t len = name_info - > len ;
2012-11-14 11:59:04 +04:00
2012-12-13 18:44:11 +04:00
if ( ( len < = 2 ) & & ( name [ 0 ] = = ' . ' ) & &
( name [ 1 ] = = ' . ' | | name [ 1 ] = = ' \0 ' ) )
return 0 ;
2012-11-14 11:59:04 +04:00
/* Initialize the default seed for the hash checksum functions */
buf [ 0 ] = 0x67452301 ;
buf [ 1 ] = 0xefcdab89 ;
buf [ 2 ] = 0x98badcfe ;
buf [ 3 ] = 0x10325476 ;
p = name ;
2012-12-27 21:55:46 +04:00
while ( 1 ) {
2012-11-14 11:59:04 +04:00
str2hashbuf ( p , len , in , 4 ) ;
TEA_transform ( buf , in ) ;
p + = 16 ;
2012-12-27 21:55:46 +04:00
if ( len < = 16 )
break ;
len - = 16 ;
2012-11-14 11:59:04 +04:00
}
hash = buf [ 0 ] ;
2012-11-28 11:12:41 +04:00
f2fs_hash = cpu_to_le32 ( hash & ~ F2FS_HASH_COL_BIT ) ;
2012-11-14 11:59:04 +04:00
return f2fs_hash ;
}