diff options
Diffstat (limited to 'fs/ubifs/key.h')
-rw-r--r-- | fs/ubifs/key.h | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h new file mode 100644 index 000000000000..8f7476007549 --- /dev/null +++ b/fs/ubifs/key.h | |||
@@ -0,0 +1,533 @@ | |||
1 | /* | ||
2 | * This file is part of UBIFS. | ||
3 | * | ||
4 | * Copyright (C) 2006-2008 Nokia Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., 51 | ||
17 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | * | ||
19 | * Authors: Artem Bityutskiy (Битюцкий Артём) | ||
20 | * Adrian Hunter | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * This header contains various key-related definitions and helper function. | ||
25 | * UBIFS allows several key schemes, so we access key fields only via these | ||
26 | * helpers. At the moment only one key scheme is supported. | ||
27 | * | ||
28 | * Simple key scheme | ||
29 | * ~~~~~~~~~~~~~~~~~ | ||
30 | * | ||
31 | * Keys are 64-bits long. First 32-bits are inode number (parent inode number | ||
32 | * in case of direntry key). Next 3 bits are node type. The last 29 bits are | ||
33 | * 4KiB offset in case of inode node, and direntry hash in case of a direntry | ||
34 | * node. We use "r5" hash borrowed from reiserfs. | ||
35 | */ | ||
36 | |||
37 | #ifndef __UBIFS_KEY_H__ | ||
38 | #define __UBIFS_KEY_H__ | ||
39 | |||
40 | /** | ||
41 | * key_r5_hash - R5 hash function (borrowed from reiserfs). | ||
42 | * @s: direntry name | ||
43 | * @len: name length | ||
44 | */ | ||
45 | static inline uint32_t key_r5_hash(const char *s, int len) | ||
46 | { | ||
47 | uint32_t a = 0; | ||
48 | const signed char *str = (const signed char *)s; | ||
49 | |||
50 | while (*str) { | ||
51 | a += *str << 4; | ||
52 | a += *str >> 4; | ||
53 | a *= 11; | ||
54 | str++; | ||
55 | } | ||
56 | |||
57 | a &= UBIFS_S_KEY_HASH_MASK; | ||
58 | |||
59 | /* | ||
60 | * We use hash values as offset in directories, so values %0 and %1 are | ||
61 | * reserved for "." and "..". %2 is reserved for "end of readdir" | ||
62 | * marker. | ||
63 | */ | ||
64 | if (unlikely(a >= 0 && a <= 2)) | ||
65 | a += 3; | ||
66 | return a; | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * key_test_hash - testing hash function. | ||
71 | * @str: direntry name | ||
72 | * @len: name length | ||
73 | */ | ||
74 | static inline uint32_t key_test_hash(const char *str, int len) | ||
75 | { | ||
76 | uint32_t a = 0; | ||
77 | |||
78 | len = min_t(uint32_t, len, 4); | ||
79 | memcpy(&a, str, len); | ||
80 | a &= UBIFS_S_KEY_HASH_MASK; | ||
81 | if (unlikely(a >= 0 && a <= 2)) | ||
82 | a += 3; | ||
83 | return a; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * ino_key_init - initialize inode key. | ||
88 | * @c: UBIFS file-system description object | ||
89 | * @key: key to initialize | ||
90 | * @inum: inode number | ||
91 | */ | ||
92 | static inline void ino_key_init(const struct ubifs_info *c, | ||
93 | union ubifs_key *key, ino_t inum) | ||
94 | { | ||
95 | key->u32[0] = inum; | ||
96 | key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * ino_key_init_flash - initialize on-flash inode key. | ||
101 | * @c: UBIFS file-system description object | ||
102 | * @k: key to initialize | ||
103 | * @inum: inode number | ||
104 | */ | ||
105 | static inline void ino_key_init_flash(const struct ubifs_info *c, void *k, | ||
106 | ino_t inum) | ||
107 | { | ||
108 | union ubifs_key *key = k; | ||
109 | |||
110 | key->j32[0] = cpu_to_le32(inum); | ||
111 | key->j32[1] = cpu_to_le32(UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS); | ||
112 | memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * lowest_ino_key - get the lowest possible inode key. | ||
117 | * @c: UBIFS file-system description object | ||
118 | * @key: key to initialize | ||
119 | * @inum: inode number | ||
120 | */ | ||
121 | static inline void lowest_ino_key(const struct ubifs_info *c, | ||
122 | union ubifs_key *key, ino_t inum) | ||
123 | { | ||
124 | key->u32[0] = inum; | ||
125 | key->u32[1] = 0; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * highest_ino_key - get the highest possible inode key. | ||
130 | * @c: UBIFS file-system description object | ||
131 | * @key: key to initialize | ||
132 | * @inum: inode number | ||
133 | */ | ||
134 | static inline void highest_ino_key(const struct ubifs_info *c, | ||
135 | union ubifs_key *key, ino_t inum) | ||
136 | { | ||
137 | key->u32[0] = inum; | ||
138 | key->u32[1] = 0xffffffff; | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * dent_key_init - initialize directory entry key. | ||
143 | * @c: UBIFS file-system description object | ||
144 | * @key: key to initialize | ||
145 | * @inum: parent inode number | ||
146 | * @nm: direntry name and length | ||
147 | */ | ||
148 | static inline void dent_key_init(const struct ubifs_info *c, | ||
149 | union ubifs_key *key, ino_t inum, | ||
150 | const struct qstr *nm) | ||
151 | { | ||
152 | uint32_t hash = c->key_hash(nm->name, nm->len); | ||
153 | |||
154 | ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); | ||
155 | key->u32[0] = inum; | ||
156 | key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * dent_key_init_hash - initialize directory entry key without re-calculating | ||
161 | * hash function. | ||
162 | * @c: UBIFS file-system description object | ||
163 | * @key: key to initialize | ||
164 | * @inum: parent inode number | ||
165 | * @hash: direntry name hash | ||
166 | */ | ||
167 | static inline void dent_key_init_hash(const struct ubifs_info *c, | ||
168 | union ubifs_key *key, ino_t inum, | ||
169 | uint32_t hash) | ||
170 | { | ||
171 | ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); | ||
172 | key->u32[0] = inum; | ||
173 | key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * dent_key_init_flash - initialize on-flash directory entry key. | ||
178 | * @c: UBIFS file-system description object | ||
179 | * @k: key to initialize | ||
180 | * @inum: parent inode number | ||
181 | * @nm: direntry name and length | ||
182 | */ | ||
183 | static inline void dent_key_init_flash(const struct ubifs_info *c, void *k, | ||
184 | ino_t inum, const struct qstr *nm) | ||
185 | { | ||
186 | union ubifs_key *key = k; | ||
187 | uint32_t hash = c->key_hash(nm->name, nm->len); | ||
188 | |||
189 | ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); | ||
190 | key->j32[0] = cpu_to_le32(inum); | ||
191 | key->j32[1] = cpu_to_le32(hash | | ||
192 | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS)); | ||
193 | memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * lowest_dent_key - get the lowest possible directory entry key. | ||
198 | * @c: UBIFS file-system description object | ||
199 | * @key: where to store the lowest key | ||
200 | * @inum: parent inode number | ||
201 | */ | ||
202 | static inline void lowest_dent_key(const struct ubifs_info *c, | ||
203 | union ubifs_key *key, ino_t inum) | ||
204 | { | ||
205 | key->u32[0] = inum; | ||
206 | key->u32[1] = UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS; | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * xent_key_init - initialize extended attribute entry key. | ||
211 | * @c: UBIFS file-system description object | ||
212 | * @key: key to initialize | ||
213 | * @inum: host inode number | ||
214 | * @nm: extended attribute entry name and length | ||
215 | */ | ||
216 | static inline void xent_key_init(const struct ubifs_info *c, | ||
217 | union ubifs_key *key, ino_t inum, | ||
218 | const struct qstr *nm) | ||
219 | { | ||
220 | uint32_t hash = c->key_hash(nm->name, nm->len); | ||
221 | |||
222 | ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); | ||
223 | key->u32[0] = inum; | ||
224 | key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS); | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * xent_key_init_hash - initialize extended attribute entry key without | ||
229 | * re-calculating hash function. | ||
230 | * @c: UBIFS file-system description object | ||
231 | * @key: key to initialize | ||
232 | * @inum: host inode number | ||
233 | * @hash: extended attribute entry name hash | ||
234 | */ | ||
235 | static inline void xent_key_init_hash(const struct ubifs_info *c, | ||
236 | union ubifs_key *key, ino_t inum, | ||
237 | uint32_t hash) | ||
238 | { | ||
239 | ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); | ||
240 | key->u32[0] = inum; | ||
241 | key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS); | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * xent_key_init_flash - initialize on-flash extended attribute entry key. | ||
246 | * @c: UBIFS file-system description object | ||
247 | * @k: key to initialize | ||
248 | * @inum: host inode number | ||
249 | * @nm: extended attribute entry name and length | ||
250 | */ | ||
251 | static inline void xent_key_init_flash(const struct ubifs_info *c, void *k, | ||
252 | ino_t inum, const struct qstr *nm) | ||
253 | { | ||
254 | union ubifs_key *key = k; | ||
255 | uint32_t hash = c->key_hash(nm->name, nm->len); | ||
256 | |||
257 | ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK)); | ||
258 | key->j32[0] = cpu_to_le32(inum); | ||
259 | key->j32[1] = cpu_to_le32(hash | | ||
260 | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS)); | ||
261 | memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); | ||
262 | } | ||
263 | |||
264 | /** | ||
265 | * lowest_xent_key - get the lowest possible extended attribute entry key. | ||
266 | * @c: UBIFS file-system description object | ||
267 | * @key: where to store the lowest key | ||
268 | * @inum: host inode number | ||
269 | */ | ||
270 | static inline void lowest_xent_key(const struct ubifs_info *c, | ||
271 | union ubifs_key *key, ino_t inum) | ||
272 | { | ||
273 | key->u32[0] = inum; | ||
274 | key->u32[1] = UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS; | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * data_key_init - initialize data key. | ||
279 | * @c: UBIFS file-system description object | ||
280 | * @key: key to initialize | ||
281 | * @inum: inode number | ||
282 | * @block: block number | ||
283 | */ | ||
284 | static inline void data_key_init(const struct ubifs_info *c, | ||
285 | union ubifs_key *key, ino_t inum, | ||
286 | unsigned int block) | ||
287 | { | ||
288 | ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK)); | ||
289 | key->u32[0] = inum; | ||
290 | key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS); | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * data_key_init_flash - initialize on-flash data key. | ||
295 | * @c: UBIFS file-system description object | ||
296 | * @k: key to initialize | ||
297 | * @inum: inode number | ||
298 | * @block: block number | ||
299 | */ | ||
300 | static inline void data_key_init_flash(const struct ubifs_info *c, void *k, | ||
301 | ino_t inum, unsigned int block) | ||
302 | { | ||
303 | union ubifs_key *key = k; | ||
304 | |||
305 | ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK)); | ||
306 | key->j32[0] = cpu_to_le32(inum); | ||
307 | key->j32[1] = cpu_to_le32(block | | ||
308 | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS)); | ||
309 | memset(k + 8, 0, UBIFS_MAX_KEY_LEN - 8); | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * trun_key_init - initialize truncation node key. | ||
314 | * @c: UBIFS file-system description object | ||
315 | * @key: key to initialize | ||
316 | * @inum: inode number | ||
317 | * | ||
318 | * Note, UBIFS does not have truncation keys on the media and this function is | ||
319 | * only used for purposes of replay. | ||
320 | */ | ||
321 | static inline void trun_key_init(const struct ubifs_info *c, | ||
322 | union ubifs_key *key, ino_t inum) | ||
323 | { | ||
324 | key->u32[0] = inum; | ||
325 | key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS; | ||
326 | } | ||
327 | |||
328 | /** | ||
329 | * key_type - get key type. | ||
330 | * @c: UBIFS file-system description object | ||
331 | * @key: key to get type of | ||
332 | */ | ||
333 | static inline int key_type(const struct ubifs_info *c, | ||
334 | const union ubifs_key *key) | ||
335 | { | ||
336 | return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS; | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * key_type_flash - get type of a on-flash formatted key. | ||
341 | * @c: UBIFS file-system description object | ||
342 | * @k: key to get type of | ||
343 | */ | ||
344 | static inline int key_type_flash(const struct ubifs_info *c, const void *k) | ||
345 | { | ||
346 | const union ubifs_key *key = k; | ||
347 | |||
348 | return le32_to_cpu(key->u32[1]) >> UBIFS_S_KEY_BLOCK_BITS; | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * key_inum - fetch inode number from key. | ||
353 | * @c: UBIFS file-system description object | ||
354 | * @k: key to fetch inode number from | ||
355 | */ | ||
356 | static inline ino_t key_inum(const struct ubifs_info *c, const void *k) | ||
357 | { | ||
358 | const union ubifs_key *key = k; | ||
359 | |||
360 | return key->u32[0]; | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * key_inum_flash - fetch inode number from an on-flash formatted key. | ||
365 | * @c: UBIFS file-system description object | ||
366 | * @k: key to fetch inode number from | ||
367 | */ | ||
368 | static inline ino_t key_inum_flash(const struct ubifs_info *c, const void *k) | ||
369 | { | ||
370 | const union ubifs_key *key = k; | ||
371 | |||
372 | return le32_to_cpu(key->j32[0]); | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * key_hash - get directory entry hash. | ||
377 | * @c: UBIFS file-system description object | ||
378 | * @key: the key to get hash from | ||
379 | */ | ||
380 | static inline int key_hash(const struct ubifs_info *c, | ||
381 | const union ubifs_key *key) | ||
382 | { | ||
383 | return key->u32[1] & UBIFS_S_KEY_HASH_MASK; | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * key_hash_flash - get directory entry hash from an on-flash formatted key. | ||
388 | * @c: UBIFS file-system description object | ||
389 | * @k: the key to get hash from | ||
390 | */ | ||
391 | static inline int key_hash_flash(const struct ubifs_info *c, const void *k) | ||
392 | { | ||
393 | const union ubifs_key *key = k; | ||
394 | |||
395 | return le32_to_cpu(key->j32[1]) & UBIFS_S_KEY_HASH_MASK; | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * key_block - get data block number. | ||
400 | * @c: UBIFS file-system description object | ||
401 | * @key: the key to get the block number from | ||
402 | */ | ||
403 | static inline unsigned int key_block(const struct ubifs_info *c, | ||
404 | const union ubifs_key *key) | ||
405 | { | ||
406 | return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK; | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * key_block_flash - get data block number from an on-flash formatted key. | ||
411 | * @c: UBIFS file-system description object | ||
412 | * @k: the key to get the block number from | ||
413 | */ | ||
414 | static inline unsigned int key_block_flash(const struct ubifs_info *c, | ||
415 | const void *k) | ||
416 | { | ||
417 | const union ubifs_key *key = k; | ||
418 | |||
419 | return le32_to_cpu(key->u32[1]) & UBIFS_S_KEY_BLOCK_MASK; | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * key_read - transform a key to in-memory format. | ||
424 | * @c: UBIFS file-system description object | ||
425 | * @from: the key to transform | ||
426 | * @to: the key to store the result | ||
427 | */ | ||
428 | static inline void key_read(const struct ubifs_info *c, const void *from, | ||
429 | union ubifs_key *to) | ||
430 | { | ||
431 | const union ubifs_key *f = from; | ||
432 | |||
433 | to->u32[0] = le32_to_cpu(f->j32[0]); | ||
434 | to->u32[1] = le32_to_cpu(f->j32[1]); | ||
435 | } | ||
436 | |||
437 | /** | ||
438 | * key_write - transform a key from in-memory format. | ||
439 | * @c: UBIFS file-system description object | ||
440 | * @from: the key to transform | ||
441 | * @to: the key to store the result | ||
442 | */ | ||
443 | static inline void key_write(const struct ubifs_info *c, | ||
444 | const union ubifs_key *from, void *to) | ||
445 | { | ||
446 | union ubifs_key *t = to; | ||
447 | |||
448 | t->j32[0] = cpu_to_le32(from->u32[0]); | ||
449 | t->j32[1] = cpu_to_le32(from->u32[1]); | ||
450 | memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8); | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * key_write_idx - transform a key from in-memory format for the index. | ||
455 | * @c: UBIFS file-system description object | ||
456 | * @from: the key to transform | ||
457 | * @to: the key to store the result | ||
458 | */ | ||
459 | static inline void key_write_idx(const struct ubifs_info *c, | ||
460 | const union ubifs_key *from, void *to) | ||
461 | { | ||
462 | union ubifs_key *t = to; | ||
463 | |||
464 | t->j32[0] = cpu_to_le32(from->u32[0]); | ||
465 | t->j32[1] = cpu_to_le32(from->u32[1]); | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * key_copy - copy a key. | ||
470 | * @c: UBIFS file-system description object | ||
471 | * @from: the key to copy from | ||
472 | * @to: the key to copy to | ||
473 | */ | ||
474 | static inline void key_copy(const struct ubifs_info *c, | ||
475 | const union ubifs_key *from, union ubifs_key *to) | ||
476 | { | ||
477 | to->u64[0] = from->u64[0]; | ||
478 | } | ||
479 | |||
480 | /** | ||
481 | * keys_cmp - compare keys. | ||
482 | * @c: UBIFS file-system description object | ||
483 | * @key1: the first key to compare | ||
484 | * @key2: the second key to compare | ||
485 | * | ||
486 | * This function compares 2 keys and returns %-1 if @key1 is less than | ||
487 | * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2. | ||
488 | */ | ||
489 | static inline int keys_cmp(const struct ubifs_info *c, | ||
490 | const union ubifs_key *key1, | ||
491 | const union ubifs_key *key2) | ||
492 | { | ||
493 | if (key1->u32[0] < key2->u32[0]) | ||
494 | return -1; | ||
495 | if (key1->u32[0] > key2->u32[0]) | ||
496 | return 1; | ||
497 | if (key1->u32[1] < key2->u32[1]) | ||
498 | return -1; | ||
499 | if (key1->u32[1] > key2->u32[1]) | ||
500 | return 1; | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | /** | ||
506 | * is_hash_key - is a key vulnerable to hash collisions. | ||
507 | * @c: UBIFS file-system description object | ||
508 | * @key: key | ||
509 | * | ||
510 | * This function returns %1 if @key is a hashed key or %0 otherwise. | ||
511 | */ | ||
512 | static inline int is_hash_key(const struct ubifs_info *c, | ||
513 | const union ubifs_key *key) | ||
514 | { | ||
515 | int type = key_type(c, key); | ||
516 | |||
517 | return type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY; | ||
518 | } | ||
519 | |||
520 | /** | ||
521 | * key_max_inode_size - get maximum file size allowed by current key format. | ||
522 | * @c: UBIFS file-system description object | ||
523 | */ | ||
524 | static inline unsigned long long key_max_inode_size(const struct ubifs_info *c) | ||
525 | { | ||
526 | switch (c->key_fmt) { | ||
527 | case UBIFS_SIMPLE_KEY_FMT: | ||
528 | return (1ULL << UBIFS_S_KEY_BLOCK_BITS) * UBIFS_BLOCK_SIZE; | ||
529 | default: | ||
530 | return 0; | ||
531 | } | ||
532 | } | ||
533 | #endif /* !__UBIFS_KEY_H__ */ | ||