xref: /dflybsd-src/sys/vfs/ext2fs/ext2_hash.c (revision cfe603905713d4e92a7956678970d5dff8e913f2)
1*cfe60390STomohiro Kusumi /*-
2*cfe60390STomohiro Kusumi  * SPDX-License-Identifier: (BSD-2-Clause-FreeBSD AND RSA-MD)
3*cfe60390STomohiro Kusumi  *
4*cfe60390STomohiro Kusumi  * Copyright (c) 2010, 2013 Zheng Liu <lz@freebsd.org>
5*cfe60390STomohiro Kusumi  * Copyright (c) 2012, Vyacheslav Matyushin
6*cfe60390STomohiro Kusumi  * All rights reserved.
7*cfe60390STomohiro Kusumi  *
8*cfe60390STomohiro Kusumi  * Redistribution and use in source and binary forms, with or without
9*cfe60390STomohiro Kusumi  * modification, are permitted provided that the following conditions
10*cfe60390STomohiro Kusumi  * are met:
11*cfe60390STomohiro Kusumi  * 1. Redistributions of source code must retain the above copyright
12*cfe60390STomohiro Kusumi  *    notice, this list of conditions and the following disclaimer.
13*cfe60390STomohiro Kusumi  * 2. Redistributions in binary form must reproduce the above copyright
14*cfe60390STomohiro Kusumi  *    notice, this list of conditions and the following disclaimer in the
15*cfe60390STomohiro Kusumi  *    documentation and/or other materials provided with the distribution.
16*cfe60390STomohiro Kusumi  *
17*cfe60390STomohiro Kusumi  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18*cfe60390STomohiro Kusumi  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*cfe60390STomohiro Kusumi  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*cfe60390STomohiro Kusumi  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21*cfe60390STomohiro Kusumi  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*cfe60390STomohiro Kusumi  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*cfe60390STomohiro Kusumi  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*cfe60390STomohiro Kusumi  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*cfe60390STomohiro Kusumi  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*cfe60390STomohiro Kusumi  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*cfe60390STomohiro Kusumi  * SUCH DAMAGE.
28*cfe60390STomohiro Kusumi  *
29*cfe60390STomohiro Kusumi  * $FreeBSD$
30*cfe60390STomohiro Kusumi  */
31*cfe60390STomohiro Kusumi 
32*cfe60390STomohiro Kusumi /*
33*cfe60390STomohiro Kusumi  * The following notice applies to the code in ext2_half_md4():
34*cfe60390STomohiro Kusumi  *
35*cfe60390STomohiro Kusumi  * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
36*cfe60390STomohiro Kusumi  *
37*cfe60390STomohiro Kusumi  * License to copy and use this software is granted provided that it
38*cfe60390STomohiro Kusumi  * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
39*cfe60390STomohiro Kusumi  * Algorithm" in all material mentioning or referencing this software
40*cfe60390STomohiro Kusumi  * or this function.
41*cfe60390STomohiro Kusumi  *
42*cfe60390STomohiro Kusumi  * License is also granted to make and use derivative works provided
43*cfe60390STomohiro Kusumi  * that such works are identified as "derived from the RSA Data
44*cfe60390STomohiro Kusumi  * Security, Inc. MD4 Message-Digest Algorithm" in all material
45*cfe60390STomohiro Kusumi  * mentioning or referencing the derived work.
46*cfe60390STomohiro Kusumi  *
47*cfe60390STomohiro Kusumi  * RSA Data Security, Inc. makes no representations concerning either
48*cfe60390STomohiro Kusumi  * the merchantability of this software or the suitability of this
49*cfe60390STomohiro Kusumi  * software for any particular purpose. It is provided "as is"
50*cfe60390STomohiro Kusumi  * without express or implied warranty of any kind.
51*cfe60390STomohiro Kusumi  *
52*cfe60390STomohiro Kusumi  * These notices must be retained in any copies of any part of this
53*cfe60390STomohiro Kusumi  * documentation and/or software.
54*cfe60390STomohiro Kusumi  */
55*cfe60390STomohiro Kusumi 
56*cfe60390STomohiro Kusumi #include <sys/param.h>
57*cfe60390STomohiro Kusumi #include <sys/systm.h>
58*cfe60390STomohiro Kusumi #include <sys/conf.h>
59*cfe60390STomohiro Kusumi #include <sys/vnode.h>
60*cfe60390STomohiro Kusumi #include <sys/stat.h>
61*cfe60390STomohiro Kusumi #include <sys/mount.h>
62*cfe60390STomohiro Kusumi 
63*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2fs.h>
64*cfe60390STomohiro Kusumi #include <vfs/ext2fs/fs.h>
65*cfe60390STomohiro Kusumi #include <vfs/ext2fs/htree.h>
66*cfe60390STomohiro Kusumi #include <vfs/ext2fs/inode.h>
67*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_mount.h>
68*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_extern.h>
69*cfe60390STomohiro Kusumi 
70*cfe60390STomohiro Kusumi SDT_PROVIDER_DECLARE(ext2fs);
71*cfe60390STomohiro Kusumi /*
72*cfe60390STomohiro Kusumi  * ext2fs trace probe:
73*cfe60390STomohiro Kusumi  * arg0: verbosity. Higher numbers give more verbose messages
74*cfe60390STomohiro Kusumi  * arg1: Textual message
75*cfe60390STomohiro Kusumi  */
76*cfe60390STomohiro Kusumi SDT_PROBE_DEFINE2(ext2fs, , trace, hash, "int", "char*");
77*cfe60390STomohiro Kusumi 
78*cfe60390STomohiro Kusumi /* F, G, and H are MD4 functions */
79*cfe60390STomohiro Kusumi #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
80*cfe60390STomohiro Kusumi #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
81*cfe60390STomohiro Kusumi #define H(x, y, z) ((x) ^ (y) ^ (z))
82*cfe60390STomohiro Kusumi 
83*cfe60390STomohiro Kusumi /* ROTATE_LEFT rotates x left n bits */
84*cfe60390STomohiro Kusumi #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
85*cfe60390STomohiro Kusumi 
86*cfe60390STomohiro Kusumi /*
87*cfe60390STomohiro Kusumi  * FF, GG, and HH are transformations for rounds 1, 2, and 3.
88*cfe60390STomohiro Kusumi  * Rotation is separated from addition to prevent recomputation.
89*cfe60390STomohiro Kusumi  */
90*cfe60390STomohiro Kusumi #define FF(a, b, c, d, x, s) { \
91*cfe60390STomohiro Kusumi 	(a) += F ((b), (c), (d)) + (x); \
92*cfe60390STomohiro Kusumi 	(a) = ROTATE_LEFT ((a), (s)); \
93*cfe60390STomohiro Kusumi }
94*cfe60390STomohiro Kusumi 
95*cfe60390STomohiro Kusumi #define GG(a, b, c, d, x, s) { \
96*cfe60390STomohiro Kusumi 	(a) += G ((b), (c), (d)) + (x) + (uint32_t)0x5A827999; \
97*cfe60390STomohiro Kusumi 	(a) = ROTATE_LEFT ((a), (s)); \
98*cfe60390STomohiro Kusumi }
99*cfe60390STomohiro Kusumi 
100*cfe60390STomohiro Kusumi #define HH(a, b, c, d, x, s) { \
101*cfe60390STomohiro Kusumi 	(a) += H ((b), (c), (d)) + (x) + (uint32_t)0x6ED9EBA1; \
102*cfe60390STomohiro Kusumi 	(a) = ROTATE_LEFT ((a), (s)); \
103*cfe60390STomohiro Kusumi }
104*cfe60390STomohiro Kusumi 
105*cfe60390STomohiro Kusumi /*
106*cfe60390STomohiro Kusumi  * MD4 basic transformation.  It transforms state based on block.
107*cfe60390STomohiro Kusumi  *
108*cfe60390STomohiro Kusumi  * This is a half md4 algorithm since Linux uses this algorithm for dir
109*cfe60390STomohiro Kusumi  * index.  This function is derived from the RSA Data Security, Inc. MD4
110*cfe60390STomohiro Kusumi  * Message-Digest Algorithm and was modified as necessary.
111*cfe60390STomohiro Kusumi  *
112*cfe60390STomohiro Kusumi  * The return value of this function is uint32_t in Linux, but actually we don't
113*cfe60390STomohiro Kusumi  * need to check this value, so in our version this function doesn't return any
114*cfe60390STomohiro Kusumi  * value.
115*cfe60390STomohiro Kusumi  */
116*cfe60390STomohiro Kusumi static void
ext2_half_md4(uint32_t hash[4],uint32_t data[8])117*cfe60390STomohiro Kusumi ext2_half_md4(uint32_t hash[4], uint32_t data[8])
118*cfe60390STomohiro Kusumi {
119*cfe60390STomohiro Kusumi 	uint32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3];
120*cfe60390STomohiro Kusumi 
121*cfe60390STomohiro Kusumi 	/* Round 1 */
122*cfe60390STomohiro Kusumi 	FF(a, b, c, d, data[0],  3);
123*cfe60390STomohiro Kusumi 	FF(d, a, b, c, data[1],  7);
124*cfe60390STomohiro Kusumi 	FF(c, d, a, b, data[2], 11);
125*cfe60390STomohiro Kusumi 	FF(b, c, d, a, data[3], 19);
126*cfe60390STomohiro Kusumi 	FF(a, b, c, d, data[4],  3);
127*cfe60390STomohiro Kusumi 	FF(d, a, b, c, data[5],  7);
128*cfe60390STomohiro Kusumi 	FF(c, d, a, b, data[6], 11);
129*cfe60390STomohiro Kusumi 	FF(b, c, d, a, data[7], 19);
130*cfe60390STomohiro Kusumi 
131*cfe60390STomohiro Kusumi 	/* Round 2 */
132*cfe60390STomohiro Kusumi 	GG(a, b, c, d, data[1],  3);
133*cfe60390STomohiro Kusumi 	GG(d, a, b, c, data[3],  5);
134*cfe60390STomohiro Kusumi 	GG(c, d, a, b, data[5],  9);
135*cfe60390STomohiro Kusumi 	GG(b, c, d, a, data[7], 13);
136*cfe60390STomohiro Kusumi 	GG(a, b, c, d, data[0],  3);
137*cfe60390STomohiro Kusumi 	GG(d, a, b, c, data[2],  5);
138*cfe60390STomohiro Kusumi 	GG(c, d, a, b, data[4],  9);
139*cfe60390STomohiro Kusumi 	GG(b, c, d, a, data[6], 13);
140*cfe60390STomohiro Kusumi 
141*cfe60390STomohiro Kusumi 	/* Round 3 */
142*cfe60390STomohiro Kusumi 	HH(a, b, c, d, data[3],  3);
143*cfe60390STomohiro Kusumi 	HH(d, a, b, c, data[7],  9);
144*cfe60390STomohiro Kusumi 	HH(c, d, a, b, data[2], 11);
145*cfe60390STomohiro Kusumi 	HH(b, c, d, a, data[6], 15);
146*cfe60390STomohiro Kusumi 	HH(a, b, c, d, data[1],  3);
147*cfe60390STomohiro Kusumi 	HH(d, a, b, c, data[5],  9);
148*cfe60390STomohiro Kusumi 	HH(c, d, a, b, data[0], 11);
149*cfe60390STomohiro Kusumi 	HH(b, c, d, a, data[4], 15);
150*cfe60390STomohiro Kusumi 
151*cfe60390STomohiro Kusumi 	hash[0] += a;
152*cfe60390STomohiro Kusumi 	hash[1] += b;
153*cfe60390STomohiro Kusumi 	hash[2] += c;
154*cfe60390STomohiro Kusumi 	hash[3] += d;
155*cfe60390STomohiro Kusumi }
156*cfe60390STomohiro Kusumi 
157*cfe60390STomohiro Kusumi /*
158*cfe60390STomohiro Kusumi  * Tiny Encryption Algorithm.
159*cfe60390STomohiro Kusumi  */
160*cfe60390STomohiro Kusumi static void
ext2_tea(uint32_t hash[4],uint32_t data[8])161*cfe60390STomohiro Kusumi ext2_tea(uint32_t hash[4], uint32_t data[8])
162*cfe60390STomohiro Kusumi {
163*cfe60390STomohiro Kusumi 	uint32_t tea_delta = 0x9E3779B9;
164*cfe60390STomohiro Kusumi 	uint32_t sum;
165*cfe60390STomohiro Kusumi 	uint32_t x = hash[0], y = hash[1];
166*cfe60390STomohiro Kusumi 	int n = 16;
167*cfe60390STomohiro Kusumi 	int i = 1;
168*cfe60390STomohiro Kusumi 
169*cfe60390STomohiro Kusumi 	while (n-- > 0) {
170*cfe60390STomohiro Kusumi 		sum = i * tea_delta;
171*cfe60390STomohiro Kusumi 		x += ((y << 4) + data[0]) ^ (y + sum) ^ ((y >> 5) + data[1]);
172*cfe60390STomohiro Kusumi 		y += ((x << 4) + data[2]) ^ (x + sum) ^ ((x >> 5) + data[3]);
173*cfe60390STomohiro Kusumi 		i++;
174*cfe60390STomohiro Kusumi 	}
175*cfe60390STomohiro Kusumi 
176*cfe60390STomohiro Kusumi 	hash[0] += x;
177*cfe60390STomohiro Kusumi 	hash[1] += y;
178*cfe60390STomohiro Kusumi }
179*cfe60390STomohiro Kusumi 
180*cfe60390STomohiro Kusumi static uint32_t
ext2_legacy_hash(const char * name,int len,int unsigned_char)181*cfe60390STomohiro Kusumi ext2_legacy_hash(const char *name, int len, int unsigned_char)
182*cfe60390STomohiro Kusumi {
183*cfe60390STomohiro Kusumi 	uint32_t h0, h1 = 0x12A3FE2D, h2 = 0x37ABE8F9;
184*cfe60390STomohiro Kusumi 	uint32_t multi = 0x6D22F5;
185*cfe60390STomohiro Kusumi 	const unsigned char *uname = (const unsigned char *)name;
186*cfe60390STomohiro Kusumi 	const signed char *sname = (const signed char *)name;
187*cfe60390STomohiro Kusumi 	int val, i;
188*cfe60390STomohiro Kusumi 
189*cfe60390STomohiro Kusumi 	for (i = 0; i < len; i++) {
190*cfe60390STomohiro Kusumi 		if (unsigned_char)
191*cfe60390STomohiro Kusumi 			val = (u_int)*uname++;
192*cfe60390STomohiro Kusumi 		else
193*cfe60390STomohiro Kusumi 			val = (int)*sname++;
194*cfe60390STomohiro Kusumi 
195*cfe60390STomohiro Kusumi 		h0 = h2 + (h1 ^ (val * multi));
196*cfe60390STomohiro Kusumi 		if (h0 & 0x80000000)
197*cfe60390STomohiro Kusumi 			h0 -= 0x7FFFFFFF;
198*cfe60390STomohiro Kusumi 		h2 = h1;
199*cfe60390STomohiro Kusumi 		h1 = h0;
200*cfe60390STomohiro Kusumi 	}
201*cfe60390STomohiro Kusumi 
202*cfe60390STomohiro Kusumi 	return (h1 << 1);
203*cfe60390STomohiro Kusumi }
204*cfe60390STomohiro Kusumi 
205*cfe60390STomohiro Kusumi static void
ext2_prep_hashbuf(const char * src,int slen,uint32_t * dst,int dlen,int unsigned_char)206*cfe60390STomohiro Kusumi ext2_prep_hashbuf(const char *src, int slen, uint32_t *dst, int dlen,
207*cfe60390STomohiro Kusumi     int unsigned_char)
208*cfe60390STomohiro Kusumi {
209*cfe60390STomohiro Kusumi 	uint32_t padding = slen | (slen << 8) | (slen << 16) | (slen << 24);
210*cfe60390STomohiro Kusumi 	uint32_t buf_val;
211*cfe60390STomohiro Kusumi 	const unsigned char *ubuf = (const unsigned char *)src;
212*cfe60390STomohiro Kusumi 	const signed char *sbuf = (const signed char *)src;
213*cfe60390STomohiro Kusumi 	int len, i;
214*cfe60390STomohiro Kusumi 	int buf_byte;
215*cfe60390STomohiro Kusumi 
216*cfe60390STomohiro Kusumi 	if (slen > dlen)
217*cfe60390STomohiro Kusumi 		len = dlen;
218*cfe60390STomohiro Kusumi 	else
219*cfe60390STomohiro Kusumi 		len = slen;
220*cfe60390STomohiro Kusumi 
221*cfe60390STomohiro Kusumi 	buf_val = padding;
222*cfe60390STomohiro Kusumi 
223*cfe60390STomohiro Kusumi 	for (i = 0; i < len; i++) {
224*cfe60390STomohiro Kusumi 		if (unsigned_char)
225*cfe60390STomohiro Kusumi 			buf_byte = (u_int)ubuf[i];
226*cfe60390STomohiro Kusumi 		else
227*cfe60390STomohiro Kusumi 			buf_byte = (int)sbuf[i];
228*cfe60390STomohiro Kusumi 
229*cfe60390STomohiro Kusumi 		if ((i % 4) == 0)
230*cfe60390STomohiro Kusumi 			buf_val = padding;
231*cfe60390STomohiro Kusumi 
232*cfe60390STomohiro Kusumi 		buf_val <<= 8;
233*cfe60390STomohiro Kusumi 		buf_val += buf_byte;
234*cfe60390STomohiro Kusumi 
235*cfe60390STomohiro Kusumi 		if ((i % 4) == 3) {
236*cfe60390STomohiro Kusumi 			*dst++ = buf_val;
237*cfe60390STomohiro Kusumi 			dlen -= sizeof(uint32_t);
238*cfe60390STomohiro Kusumi 			buf_val = padding;
239*cfe60390STomohiro Kusumi 		}
240*cfe60390STomohiro Kusumi 	}
241*cfe60390STomohiro Kusumi 
242*cfe60390STomohiro Kusumi 	dlen -= sizeof(uint32_t);
243*cfe60390STomohiro Kusumi 	if (dlen >= 0)
244*cfe60390STomohiro Kusumi 		*dst++ = buf_val;
245*cfe60390STomohiro Kusumi 
246*cfe60390STomohiro Kusumi 	dlen -= sizeof(uint32_t);
247*cfe60390STomohiro Kusumi 	while (dlen >= 0) {
248*cfe60390STomohiro Kusumi 		*dst++ = padding;
249*cfe60390STomohiro Kusumi 		dlen -= sizeof(uint32_t);
250*cfe60390STomohiro Kusumi 	}
251*cfe60390STomohiro Kusumi }
252*cfe60390STomohiro Kusumi 
253*cfe60390STomohiro Kusumi int
ext2_htree_hash(const char * name,int len,uint32_t * hash_seed,int hash_version,uint32_t * hash_major,uint32_t * hash_minor)254*cfe60390STomohiro Kusumi ext2_htree_hash(const char *name, int len,
255*cfe60390STomohiro Kusumi     uint32_t *hash_seed, int hash_version,
256*cfe60390STomohiro Kusumi     uint32_t *hash_major, uint32_t *hash_minor)
257*cfe60390STomohiro Kusumi {
258*cfe60390STomohiro Kusumi 	uint32_t hash[4];
259*cfe60390STomohiro Kusumi 	uint32_t data[8];
260*cfe60390STomohiro Kusumi 	uint32_t major = 0, minor = 0;
261*cfe60390STomohiro Kusumi 	int unsigned_char = 0;
262*cfe60390STomohiro Kusumi 
263*cfe60390STomohiro Kusumi 	if (!name || !hash_major)
264*cfe60390STomohiro Kusumi 		return (-1);
265*cfe60390STomohiro Kusumi 
266*cfe60390STomohiro Kusumi 	if (len < 1 || len > 255)
267*cfe60390STomohiro Kusumi 		goto error;
268*cfe60390STomohiro Kusumi 
269*cfe60390STomohiro Kusumi 	hash[0] = 0x67452301;
270*cfe60390STomohiro Kusumi 	hash[1] = 0xEFCDAB89;
271*cfe60390STomohiro Kusumi 	hash[2] = 0x98BADCFE;
272*cfe60390STomohiro Kusumi 	hash[3] = 0x10325476;
273*cfe60390STomohiro Kusumi 
274*cfe60390STomohiro Kusumi 	if (hash_seed)
275*cfe60390STomohiro Kusumi 		memcpy(hash, hash_seed, sizeof(hash));
276*cfe60390STomohiro Kusumi 
277*cfe60390STomohiro Kusumi 	switch (hash_version) {
278*cfe60390STomohiro Kusumi 	case EXT2_HTREE_TEA_UNSIGNED:
279*cfe60390STomohiro Kusumi 		unsigned_char = 1;
280*cfe60390STomohiro Kusumi 		/* FALLTHROUGH */
281*cfe60390STomohiro Kusumi 	case EXT2_HTREE_TEA:
282*cfe60390STomohiro Kusumi 		while (len > 0) {
283*cfe60390STomohiro Kusumi 			ext2_prep_hashbuf(name, len, data, 16, unsigned_char);
284*cfe60390STomohiro Kusumi 			ext2_tea(hash, data);
285*cfe60390STomohiro Kusumi 			len -= 16;
286*cfe60390STomohiro Kusumi 			name += 16;
287*cfe60390STomohiro Kusumi 		}
288*cfe60390STomohiro Kusumi 		major = hash[0];
289*cfe60390STomohiro Kusumi 		minor = hash[1];
290*cfe60390STomohiro Kusumi 		break;
291*cfe60390STomohiro Kusumi 	case EXT2_HTREE_LEGACY_UNSIGNED:
292*cfe60390STomohiro Kusumi 		unsigned_char = 1;
293*cfe60390STomohiro Kusumi 		/* FALLTHROUGH */
294*cfe60390STomohiro Kusumi 	case EXT2_HTREE_LEGACY:
295*cfe60390STomohiro Kusumi 		major = ext2_legacy_hash(name, len, unsigned_char);
296*cfe60390STomohiro Kusumi 		break;
297*cfe60390STomohiro Kusumi 	case EXT2_HTREE_HALF_MD4_UNSIGNED:
298*cfe60390STomohiro Kusumi 		unsigned_char = 1;
299*cfe60390STomohiro Kusumi 		/* FALLTHROUGH */
300*cfe60390STomohiro Kusumi 	case EXT2_HTREE_HALF_MD4:
301*cfe60390STomohiro Kusumi 		while (len > 0) {
302*cfe60390STomohiro Kusumi 			ext2_prep_hashbuf(name, len, data, 32, unsigned_char);
303*cfe60390STomohiro Kusumi 			ext2_half_md4(hash, data);
304*cfe60390STomohiro Kusumi 			len -= 32;
305*cfe60390STomohiro Kusumi 			name += 32;
306*cfe60390STomohiro Kusumi 		}
307*cfe60390STomohiro Kusumi 		major = hash[1];
308*cfe60390STomohiro Kusumi 		minor = hash[2];
309*cfe60390STomohiro Kusumi 		break;
310*cfe60390STomohiro Kusumi 	default:
311*cfe60390STomohiro Kusumi 		SDT_PROBE2(ext2fs, , trace, hash, 1, "unexpected hash version");
312*cfe60390STomohiro Kusumi 		goto error;
313*cfe60390STomohiro Kusumi 	}
314*cfe60390STomohiro Kusumi 
315*cfe60390STomohiro Kusumi 	major &= ~1;
316*cfe60390STomohiro Kusumi 	if (major == (EXT2_HTREE_EOF << 1))
317*cfe60390STomohiro Kusumi 		major = (EXT2_HTREE_EOF - 1) << 1;
318*cfe60390STomohiro Kusumi 	*hash_major = major;
319*cfe60390STomohiro Kusumi 	if (hash_minor)
320*cfe60390STomohiro Kusumi 		*hash_minor = minor;
321*cfe60390STomohiro Kusumi 
322*cfe60390STomohiro Kusumi 	return (0);
323*cfe60390STomohiro Kusumi 
324*cfe60390STomohiro Kusumi error:
325*cfe60390STomohiro Kusumi 	*hash_major = 0;
326*cfe60390STomohiro Kusumi 	if (hash_minor)
327*cfe60390STomohiro Kusumi 		*hash_minor = 0;
328*cfe60390STomohiro Kusumi 	return (-1);
329*cfe60390STomohiro Kusumi }
330