3 * Copyright (C) 2005-2009
4 * Neil Brown <neilb@suse.de>
5 * Released under the GPL, version 2
7 * A directory block is stored as an AVL tree.
8 * Entries are added to the end, and merged into
10 * Deleted entries are left in place, but marked
11 * as deleted (pointer is 0)
12 * When a block becomes full, we re-pack it,
18 /* TEA_transform borrowed from ext3 */
19 #define DELTA 0x9E3779B9
21 static void TEA_transform(u32 buf[2], u32 const in[4])
24 u32 b0 = buf[0], b1 = buf[1];
25 u32 a = in[0], b = in[1], c = in[2], d = in[3];
30 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
31 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
38 static void str2msg(u32 *msg, int len, const char *name)
46 for (i = 0; i < len ; i++) {
47 part = (part << 8) + name[i];
51 for ( ; i < 16 ; i++) {
52 part = (part<<8) + pad;
58 int lafs_hash_name(u32 seed, int len, const char *name)
72 str2msg(msg, len, name);
73 TEA_transform(buf, msg);
77 return buf[0] & 0x7fffffff;
81 static u32 hash_piece(u32 seed, struct dirpiece *dp, u32 *offsetp)
83 u32 hash = lafs_hash_name(seed, dp->length, dp->name);
85 switch (dp->chain_info) {
92 offset = (unsigned char) dp->name[dp->length];
95 memcpy(&offset, dp->name + dp->length, 4);
96 offset = le32_to_cpu(offset);
101 return hash + offset;
104 /* dpaddr assumes that 'psz' (piece size) is valid when called */
105 #define dpaddr(_block, _piece) ((struct dirpiece *)((_block) + ((_piece)<<psz)))
106 #define dlpaddr(_block, _piece) ((struct dirleafpiece *)((_block) \
109 static int dir_set_name(struct dirpiece *dp, const char *name, int len,
112 memcpy(dp->name, name, len);
114 if (chain_offset <= 1)
115 dp->chain_info = chain_offset;
116 else if (chain_offset < 256) {
118 dp->name[len++] = chain_offset;
120 u32 co = cpu_to_le32(chain_offset);
121 memcpy(dp->name+len, &co, 4);
128 void lafs_dir_init_block(char *block, int psz, const char *name, int len,
129 u32 target, int type, int chain_offset)
131 /* create a new directory block containing just the given name.
135 struct dirheader *dh;
141 dh = (struct dirheader *) block;
143 pnum = (sizeof(struct dirheader) + (1<<psz)-1) >> psz;
147 dp = dpaddr(block, pnum);
148 dp->target = cpu_to_le32(target);
151 dp->longer = Neither;
155 memcpy(dp->name, name, len);
157 if (chain_offset <= 1)
158 dp->chain_info = chain_offset;
159 else if (chain_offset < 256) {
161 dp->name[len++] = chain_offset;
163 u32 co = cpu_to_le32(chain_offset);
164 memcpy(dp->name+len, &co, 4);
169 /* NOTE: we want the last piece, not the next free piece, so
170 * we don't add (1<<psz) into this sum
172 dh->lastpiece = pnum + ((offsetof(struct dirpiece, name)+len-1) >> psz);
173 dh->freepieces = 255 - dh->lastpiece;
176 static inline int dir_rotate_2(char *block, int psz, u8 *treep, int dir)
178 unsigned int B, C, D, E;
179 struct dirpiece *b, *d;
181 B = *treep; b = dpaddr(block, B);
182 D = b->next[dir]; d = dpaddr(block, D);
194 static inline int dir_rotate_3(char *block, int psz, u8 *treep,
197 unsigned int B, F, D, C, E;
198 struct dirpiece *b, *f, *d;
200 B = *treep; b = dpaddr(block, B);
201 F = b->next[dir]; f = dpaddr(block, F);
202 D = f->next[1-dir]; d = dpaddr(block, D);
212 b->longer = f->longer = Neither;
214 if (third == Neither)
216 else if (third == dir) {
225 static void dir_check_balance(char *block, int psz);
226 int lafs_dir_add_ent(char *block, int psz, const char *name, int len,
227 u32 target, int type, u32 seed, u32 hash, int hashoffset)
229 /* Add this entry to the directory block,
231 * -2 hash value is in use, same name
232 * -1 hash value is in use, different name
233 * 0 insufficient room
237 struct dirheader *dh = (struct dirheader *) block;
238 struct dirpiece *dp, *dpold;
239 int piece = dh->root;
240 u8 *thisp = &dh->root;
244 int first, second, third;
247 /* path is a list of bits indicate whether each successive step
248 * down from *topp was foreward(1) or backward(0).
250 unsigned long path = 0;
255 int last = 0, cnt = 0, reset = 1;
262 lafs_dir_init_block(block, psz, name, len, target,
266 need = len + (hashoffset > 255 ? 4 : hashoffset > 1 ? 1 : 0);
267 need += offsetof(struct dirpiece, name);
268 need = DIV_ROUND_UP(need, (1<<psz));
270 /* First, find the insertion point */
271 dp = dpaddr(block, piece);
273 u32 hval = hash_piece(seed, dp, NULL);
277 /* deleted entry, no AVL op needed */
278 goto replace_deleted;
280 if (len == dp->length &&
281 strncmp(name, dp->name, len) == 0)
286 if (dp->longer != Neither) {
291 set_bit(depth, &path);
293 clear_bit(depth, &path);
295 if (depth >= sizeof(path)*8)
297 thisp = &dp->next[dir];
299 dp = dpaddr(block, piece);
301 if (cnt > 0 && piece == last) {
313 /* Now see if there is room to store this entry, given the amount of
314 * sharing that we have managed to achieve
316 if (dh->lastpiece + need > 255)
319 /* Special flag to say 'just test if there is room */
321 piece = dh->lastpiece+1;
323 dp = dpaddr(block, piece);
324 dh->lastpiece += need;
325 BUG_ON(dh->lastpiece == 0);
326 dh->freepieces -= need;
327 dp->target = cpu_to_le32(target);
333 dp->longer = Neither;
334 dir_set_name(dp, name, len, hashoffset);
336 /* now merge this piece into the AVL tree, rebalancing
342 dp = dpaddr(block, piece);
345 first = !!test_bit(0, &path);
346 second = !!test_bit(1, &path);
347 if (dp->longer == Neither)
349 else if (dp->longer != first) {
350 /* took the shorter path */
351 dp->longer = Neither;
352 piece = dp->next[first];
354 } else if (first == second) {
355 /* just a two-point rotation */
356 piece = dir_rotate_2(block, psz, topp, first);
362 third = !!test_bit(2, &path);
363 piece = dir_rotate_3(block, psz, topp, first, third);
367 while (piece && st < depth) {
368 first = test_bit(st, &path) ? 1 : 0;
369 dp = dpaddr(block, piece);
371 piece = dp->next[first];
374 BUG_ON(dh->root == 0);
375 dir_check_balance(block, psz);
379 /* If there is room at the end, add an entry,
382 if (dh->lastpiece + need > 255)
387 space = dp->length + (dp->chain_info < 2
388 ? 0 : (dp->chain_info == 2
390 space += offsetof(struct dirpiece, name);
391 space = DIV_ROUND_UP(space, 1<<psz);
393 piece = dh->lastpiece + 1;
395 dp = dpaddr(block, piece);
396 dh->lastpiece += need;
397 dh->freepieces -= need;
398 dh->freepieces += space;
400 dp->next[0] = dpold->next[0];
401 dp->next[1] = dpold->next[1];
402 dp->target = cpu_to_le32(target);
405 dir_set_name(dp, name, len, hashoffset);
409 int lafs_dir_del_ent(char *block, int psz, u32 seed, u32 hash)
411 /* Delete this entry from the directory block.
412 * This involves removing it from the avl tree.
413 * If it was the last entry, we reduce 'lastpiece'
414 * so the space can be used immediately.
417 struct dirheader *dh = (struct dirheader *)block;
419 struct dirpiece *second;
420 int piece = dh->root;
421 u8 *thisp = &dh->root;
428 unsigned long path = 0;
431 dp = dpaddr(block, piece);
433 u32 hval = hash_piece(seed, dp, NULL);
440 if (dp->next[dir] == 0)
442 if (dp->longer == Neither) {
445 } else if (dp->longer == (1-dir)) {
446 struct dirpiece *dp2;
447 dp2 = dpaddr(block, dp->next[1-dir]);
448 if (dp2->longer == Neither) {
454 set_bit(depth, &path);
456 clear_bit(depth, &path);
458 if (depth >= sizeof(path)*8)
461 thisp = &dp->next[dir];
463 dp = dpaddr(block, piece);
468 set_bit(depth, &path);
470 clear_bit(depth, &path);
472 /* now we must walk down from topp to thisp rebalancing nodes,
473 * but making sure that targetp points to the link to target...
478 dir = !!test_bit(st, &path);
479 dp = dpaddr(block, piece);
480 if (dp->next[dir] == 0)
483 if (dp->longer == Neither)
485 else if (dp->longer == dir)
486 dp->longer = Neither;
488 /* need a rotation */
490 dpaddr(block, dp->next[1-dir]);
491 if (second->longer == dir) {
492 struct dirpiece *third =
493 dpaddr(block, second->next[dir]);
494 dir_rotate_3(block, psz, topp, 1-dir,
496 } else if (second->longer == Neither) {
497 dir_rotate_2(block, psz, topp, 1-dir);
499 second = dpaddr(block, *topp);
500 second->longer = dir;
502 dir_rotate_2(block, psz, topp, 1-dir);
503 if (piece == targetn) {
504 second = dpaddr(block, *topp);
505 targetp = &second->next[dir];
508 topp = &dp->next[dir];
512 /* Ok, rebalance all done, now swap *targetp for *thisp and
518 dp = dpaddr(block, piece);
519 second = dpaddr(block, targetn);
520 *thisp = dp->next[1-dir];
521 dp->next[0] = second->next[0];
522 dp->next[1] = second->next[1];
523 dp->longer = second->longer;
525 /* now second can be destroyed */
527 space = second->length + (second->chain_info < 2
528 ? 0 : second->chain_info == 2 ? 1 : 4);
529 space += offsetof(struct dirpiece, name);
530 space = DIV_ROUND_UP(space, 1<<psz);
532 /* we deleted the only entry, clear the block */
533 dh->lastpiece = (sizeof(struct dirheader) + (1<<psz)-1) >> psz;
534 dh->freepieces = 255 - dh->lastpiece;
535 } else if (targetn + space > dh->lastpiece) {
536 /* We are deleting the last entry, so it can be reused */
537 dh->freepieces += dh->lastpiece+1-targetn;
538 dh->lastpiece = targetn-1;
540 dh->freepieces += space;
544 static void dir_linearise(char *block, int psz)
546 /* destructively linearise the entries in the block.
547 * i.e. arrange that for each non-deleted entry,
548 * ->next[0] points to the previous, and
549 * ->next[1] points to the next
551 * The first points to the last, and dh->root
552 * points to the first
554 * Rather than using a stack to walk down, we reverse
555 * each pointer was we step down it, and use
556 * the ->longer field to say which way we came
558 struct dirheader *dh = (struct dirheader *)block;
559 int piece = dh->root;
560 struct dirpiece *dp = NULL;
567 dp = dpaddr(block, piece);
569 case 0: /* stepping down to piece for the first time */
571 /* step further down */
573 dp->next[0] = parent;
581 case 1: /* back up from the left branch */
582 /* This must be next in sequence */
586 /* step down the other way */
589 dp->next[1] = parent;
596 case 2: /* back up from the right branch */
598 dp = dpaddr(block, piece);
600 parent = dp->next[state];
607 /* now 'prev' is the last piece. Walk back along the path setting
613 dp = dpaddr(block, prev);
623 lafs_dir_extract(char *block, int psz, struct dir_ent *de, int pnum,
626 /* extract the directory entry into de. de->name points into
627 * the buffer, and is not nul terminated. */
628 struct dirpiece *dp = dpaddr(block, pnum);
630 BUG_ON(pnum <= 0 || pnum > 255);
631 de->target = le32_to_cpu(dp->target);
634 de->nlen = dp->length;
636 *hash = hash_piece(*hash, dp, NULL);
640 void lafs_dir_set_target(char *block, int psz, struct dir_ent *de, int pnum)
642 /* update the target and type from de */
643 struct dirpiece *dp = dpaddr(block, pnum);
644 dp->target = cpu_to_le32(de->target);
648 void lafs_dir_split(char *orig, int psz, char *new1, char *new2,
649 const char *name, u32 target, int type, u32 *newhash,
650 u32 seed, u32 hash, int chainoffset)
652 /* Split the orig block together with the new name, into new1 and new2.
653 * Linearise orig, then copy one entry into which block is least empty
654 * A hash somewhere between the two blocks is placed in *newhash.
655 * It could be the highest in 'new1' but will be less than the
659 struct dirheader *dh = (struct dirheader *)orig;
660 struct dirheader *dh1 = (struct dirheader *)new1;
661 struct dirheader *dh2 = (struct dirheader *)new2;
664 int full1 = 0, full2 = 0;
665 u32 offset, maxhash, minhash, hval;
667 dir_linearise(orig, psz);
670 dp = dpaddr(orig, first);
672 if (first == 0 || last == 0)
673 /* orig was empty ?? */
676 /* create new1 and new2 with first and last */
677 hval = hash_piece(seed, dp, &offset);
678 if (type && hash < hval) {
679 lafs_dir_init_block(new1, psz, name, 0, target, type,
684 lafs_dir_init_block(new1, psz, dp->name, dp->length,
685 le32_to_cpu(dp->target), dp->type,
693 dp = dpaddr(orig, last);
694 hval = hash_piece(seed, dp, &offset);
695 if (type && hash > hval) {
696 lafs_dir_init_block(new2, psz, name, 0, target, type,
702 lafs_dir_init_block(new2, psz, dp->name, dp->length,
703 le32_to_cpu(dp->target), dp->type,
712 while (first || type) {
713 /* everything from 'first' to 'last', plus 'name' (if type)
714 * is allowed to go in either block.
715 * Choose a block, and an entry, and insert it (if possible)
717 if (full2 || (dh1->freepieces >= dh2->freepieces && !full1)) {
718 /* insert into new1 from first or name */
719 dp = dpaddr(orig, first);
721 hval = hash_piece(seed, dp, &offset);
722 if (type == 0 || (first && hval < hash)) {
723 /* first is the preferred candidate */
724 if (!lafs_dir_add_ent(new1, psz, dp->name,
726 le32_to_cpu(dp->target),
727 dp->type, seed, hval,
739 if (!lafs_dir_add_ent(new1, psz, name, 0,
749 /* insert into new2 */
750 dp = dpaddr(orig, last);
752 hval = hash_piece(seed, dp, &offset);
753 if (type == 0 || (first && hval > hash)) {
754 /* last is the preferred candidate */
755 if (!lafs_dir_add_ent(new2, psz,
756 dp->name, dp->length,
757 le32_to_cpu(dp->target),
758 dp->type, seed, hval,
769 if (!lafs_dir_add_ent(new2, psz, name, 0,
781 /* newhash could be minhash, but not
783 *newhash = (minhash + maxhash) / 2;
786 void lafs_dir_repack(char *block, int psz, char *new, u32 seed, int merge)
788 struct dirheader *dh = (struct dirheader *)block;
789 int pnum = (sizeof(struct dirheader) + (1<<psz)-1)>>psz;
792 while (pnum <= dh->lastpiece) {
794 struct dirpiece *dp = dpaddr(block, pnum);
798 u32 hash = hash_piece(seed, dp, &offset);
800 lafs_dir_init_block(new, psz, dp->name,
802 le32_to_cpu(dp->target),
805 lafs_dir_add_ent(new, psz, dp->name, dp->length,
806 le32_to_cpu(dp->target),
807 dp->type, seed, hash, offset);
810 space = dp->length + (dp->chain_info < 2
811 ? 0 : (dp->chain_info == 2
813 space += offsetof(struct dirpiece, name);
814 space = DIV_ROUND_UP(space, 1<<psz);
820 int lafs_dir_find(char *block, int psz, u32 seed, u32 hash, u8 *pp)
822 /* Find the entry for 'hash', if it exists.
823 * Return 1 if found, 0 if not.
824 * set 'pp' to the piece number if found, or the
825 * next larger piece if not (zero if nothing is larger).
827 struct dirheader *dh = (struct dirheader *)block;
833 while (pnum && cnt) {
834 struct dirpiece *dp = dpaddr(block, pnum);
835 u32 hval = hash_piece(seed, dp, NULL);
854 static int dir_check_loop(char *block, int psz, int pnum, int depth)
856 /* walk around the tree, and BUG if we ever get a depth > 255 */
857 struct dirheader *dh = (struct dirheader *)block;
863 if (pnum < 0 || pnum >= 256)
867 struct dirpiece *dp = dpaddr(block, pnum);
868 if (dir_check_loop(block, psz, dp->next[0], depth-1) ||
869 dir_check_loop(block, psz, dp->next[1], depth-1)) {
870 printk(" ..%d(%d)\n", pnum, depth);
878 int lafs_dir_empty(char *block)
880 struct dirheader *dh = (struct dirheader *)block;
881 return dh->root == 0;
884 int lafs_dir_blk_size(char *block, int psz)
886 /* how much of this block do we actually need to store */
887 struct dirheader *dh = (struct dirheader *)block;
888 if (lafs_dir_empty(block))
890 return (dh->lastpiece+1) << psz;
893 /* Testing code here - no new important functionality */
896 static void xprintk(char *block, int psz, char *s, int a, int b, int c, int d)
898 printk(s, a, b, c, d);
899 lafs_dir_print(block, psz);
903 static int dir_check_depth(char *block, int psz, int p, int depth)
905 struct dirpiece *dp = dpaddr(block, p);
910 for (i = 0; i < 32; i++)
911 printk("%02x ", block[i]);
917 b = dir_check_depth(block, psz, dp->next[0], depth+1);
918 f = dir_check_depth(block, psz, dp->next[1], depth+1);
920 if (dp->longer != Neither)
921 xprintk(block, psz, "... %d - b=%d f=%d lgr=%d\n",
922 p, b, f, dp->longer);
927 xprintk(block, psz, "... %d - b=%d f=%d lgr=%d\n",
928 p, b, f, dp->longer);
933 xprintk(block, psz, "... %d - b=%d f=%d lgr=%d\n",
934 p, b, f, dp->longer);
937 xprintk(block, psz, "... %d - b=%d f=%d lgr=%d\n", p, b, f, dp->longer);
938 return (b > f ? b : f) + 1;
941 static void dir_check_balance(char *block, int psz)
943 struct dirheader *dh = (struct dirheader *) block;
944 dir_check_depth(block, psz, dh->root, 0);
947 static void dir_print_piece(char *block, int psz, int piece, int depth, int dir)
949 struct dirpiece *dp = dpaddr(block, piece);
954 dir_print_piece(block, psz, dp->next[0], depth+1, 0);
955 printk("%3d - %08lu:%02d %*s%c", piece,
956 (unsigned long) le32_to_cpu(dp->target),
960 printk("%.*s\n", dp->length, dp->name);
961 dir_print_piece(block, psz, dp->next[1], depth+1, 1);
964 static void dir_print_block(char *block, int psz, int sort)
966 struct dirheader *dh;
969 dh = (struct dirheader *)block;
970 printk("===Directory Block===\n");
972 printk(" Root: %d\n", dh->root);
973 printk(" Last Piece : %d (%d left)\n", dh->lastpiece,
974 255 - dh->lastpiece);
975 printk(" Free Pieces: %d (%d deleted)\n", dh->freepieces,
976 dh->freepieces - (255 - dh->lastpiece));
978 dir_print_piece(block, psz, dh->root, 0, 1);
979 else if (sort == 2) {
983 dp = dpaddr(block, pnum);
984 printk("%3d - %08lu: (b:%-3d, f:%-3d, l:%d, type:%d ",
985 pnum, (unsigned long) le32_to_cpu(dp->target),
986 dp->next[0], dp->next[1], dp->longer,
988 printk(": (%d)%.*s\n", dp->length, dp->length,
993 /* don't interpret the pieces too much */
994 int pnum = (sizeof(struct dirheader) + (1<<psz)-1)>>psz;
995 while (pnum <= dh->lastpiece) {
996 dp = dpaddr(block, pnum);
997 printk("%3d - %08lu: (b:%-3d, f:%-3d, l:%d, type:%d ",
998 pnum, (unsigned long)le32_to_cpu(dp->target),
999 dp->next[0], dp->next[1], dp->longer,
1001 printk(": (%d)%.*s\n", dp->length,
1002 dp->length, dp->name);
1003 pnum += (offsetof(struct dirpiece, name)
1004 + dp->length + (1<<psz)-1)>>psz;
1009 void lafs_dir_print(char *buf, int psz)
1011 dir_print_block(buf, psz, 1);
1018 int main(int argc, char **argv)
1022 int psz = blenshift - 8;
1026 lafs_dir_init_block(block, psz, argv[1], 0, 42, 3, 0);
1027 while (arg < argc-1) {
1028 if (argv[arg][0] != '-')
1029 switch (lafs_dir_add_ent(block, psz, argv[arg], 0,
1032 printf("%s didn't fit!\n", argv[arg]);
1035 printf("%s already exists\n", argv[arg]);
1038 printf("%s inserted\n", argv[arg]);
1041 switch (lafs_dir_del_ent(block, psz, argv[arg]+1, 0)) {
1043 printf("%s not found!\n", argv[arg]);
1046 printf("%s not deleted - bad dir\n", argv[arg]);
1049 printf("%s deleted\n", argv[arg]);
1053 dir_check_balance(block, psz);
1056 dir_print_block(block, psz, 0);
1057 dir_print_block(block, psz, 1);
1059 lafs_dir_split(block, psz, block+1024, block+2048, argv[arg],
1061 dir_print_block(block+1024, psz, 1);
1062 dir_print_block(block+2048, psz, 1);
1063 dir_get_prefix(block+1024, block+2048, psz, block+3096);
1064 printf("Prefix is <%s>\n", block+3096);
1065 lafs_dir_repack(block+1024, psz, block, 0);
1066 lafs_dir_repack(block+2048, psz, block, 1);
1067 printf("============= repacked ===================\n");
1068 dir_print_block(block, psz, 1);