2 * A directory block is stored as an AVL tree.
3 * Entries are added to the end, and merged into
5 * Deleted entries are left in place, but marked
6 * as deleted (pointer is 0)
7 * When a block becomes full, we re-pack it,
13 /* TEA_transform borrowed from ext3 */
14 #define DELTA 0x9E3779B9
16 static void TEA_transform(u32 buf[2], u32 const in[4])
19 u32 b0 = buf[0], b1 = buf[1];
20 u32 a = in[0], b = in[1], c = in[2], d = in[3];
25 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
26 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
33 static void str2msg(u32 *msg, int len, const char *name)
41 for (i = 0; i < len ; i++) {
42 part = (part << 8) + name[i];
46 for ( ; i < 16 ; i++) {
47 part = (part<<8) + pad;
53 int lafs_hash_name(u32 seed, int len, const char *name)
67 str2msg(msg, len, name);
68 TEA_transform(buf, msg);
72 return buf[0] & 0x7fffffff;
76 static u32 hash_piece(u32 seed, struct dirpiece *dp, u32 *offsetp)
78 u32 hash = lafs_hash_name(seed, dp->length, dp->name);
80 switch (dp->chain_info) {
87 offset = (unsigned char) dp->name[dp->length];
90 memcpy(&offset, dp->name + dp->length, 4);
91 offset = le32_to_cpu(offset);
94 if (offsetp) *offsetp = offset;
99 /* dpaddr assumes that 'psz' (piece size) is valid when called */
100 #define dpaddr(_block, _piece) ((struct dirpiece*)((_block) + ((_piece)<<psz)))
101 #define dlpaddr(_block, _piece) ((struct dirleafpiece*)((_block) + ((_piece)<<psz)))
103 static int dir_set_name(struct dirpiece *dp, const char *name, int len,
106 memcpy(dp->name, name, len);
108 if (chain_offset <= 1)
109 dp->chain_info = chain_offset;
110 else if (chain_offset < 256) {
112 dp->name[len++] = chain_offset;
114 u32 co = cpu_to_le32(chain_offset);
115 memcpy(dp->name+len, &co, 4);
122 void lafs_dir_init_block(char *block, int psz, const char *name, int len,
123 u32 target, int type, int chain_offset)
125 /* create a new directory block containing just the given name.
129 struct dirheader *dh;
135 dh = (struct dirheader*) block;
137 pnum = (sizeof(struct dirheader)+ (1<<psz)-1) >> psz;
141 dp = dpaddr(block, pnum);
142 dp->target = cpu_to_le32(target);
145 dp->longer = Neither;
149 memcpy(dp->name, name, len);
151 if (chain_offset <= 1)
152 dp->chain_info = chain_offset;
153 else if (chain_offset < 256) {
155 dp->name[len++] = chain_offset;
157 u32 co = cpu_to_le32(chain_offset);
158 memcpy(dp->name+len, &co, 4);
163 /* NOTE: we want the last piece, not the next free piece, so we don't add
164 * (1<<psz) into this sum
166 dh->lastpiece = pnum + ((offsetof(struct dirpiece, name)+len-1)>> psz);
167 dh->freepieces = 255 - dh->lastpiece;
173 static inline int dir_rotate_2(char *block, int psz, u8 *treep, int dir)
175 unsigned int B,C,D,E;
176 struct dirpiece *b,*d;
178 B = *treep; b = dpaddr(block, B);
179 D = b->next[dir]; d = dpaddr(block, D);
191 static inline int dir_rotate_3(char *block, int psz, u8 *treep, int dir, int third)
193 unsigned int B, F, D, C, E;
194 struct dirpiece *b, *f, *d;
196 B = *treep; b = dpaddr(block, B);
197 F = b->next[dir]; f = dpaddr(block, F);
198 D = f->next[1-dir]; d = dpaddr(block, D);
208 b->longer = f->longer = Neither;
210 if (third == Neither)
212 else if (third == dir) {
221 static void dir_check_balance(char *block, int psz);
222 int lafs_dir_add_ent(char *block, int psz, const char *name, int len, u32 target,
223 int type, u32 seed, u32 hash, int hashoffset)
225 /* Add this entry to the directory block,
227 * -2 hash value is in use, same name
228 * -1 hash value is in use, different name
229 * 0 insufficient room
233 struct dirheader *dh = (struct dirheader*) block;
234 struct dirpiece *dp, *dpold;
235 int piece = dh->root;
236 u8 *thisp = &dh->root;
240 int first, second, third;
243 /* path is a list of bits indicate whether each successive step
244 * down from *topp was foreward(1) or backward(0).
246 unsigned long path = 0;
251 int last=0, cnt=0, reset=1;
258 lafs_dir_init_block(block, psz, name, len, target,
262 need = len + (hashoffset > 255 ? 4 : hashoffset > 1 ? 1 : 0);
263 need += offsetof(struct dirpiece, name);
264 need = DIV_ROUND_UP(need, (1<<psz));
266 /* First, find the insertion point */
267 dp = dpaddr(block, piece);
269 u32 hval = hash_piece(seed, dp, NULL);
273 /* deleted entry, no AVL op needed */
274 goto replace_deleted;
276 if (len == dp->length &&
277 strncmp(name, dp->name, len) == 0)
282 if (dp->longer != Neither) { depth = 0; topp = thisp;}
283 if (dir) set_bit(depth, &path);
284 else clear_bit(depth, &path);
286 if (depth >= sizeof(path)*8) return -2;
287 thisp = &dp->next[dir];
289 dp = dpaddr(block, piece);
291 if (cnt > 0 && piece == last) {
303 /* Now see if there is room to store this entry, given the amount of
304 * sharing that we have managed to achieve
306 if (dh->lastpiece + need > 255)
309 /* Special flag to say 'just test if there is room */
311 piece = dh->lastpiece+1;
312 /* printf("inserting %s at %d, sharelen %d\n", name, piece, sharelen);*/
313 dp = dpaddr(block, piece);
314 dh->lastpiece += need;
315 BUG_ON(dh->lastpiece==0);
316 dh->freepieces -= need;
317 dp->target = cpu_to_le32(target);
323 dp->longer = Neither;
324 dir_set_name(dp, name, len, hashoffset);
326 /* now merge this piece into the AVL tree, rebalancing
332 dp = dpaddr(block, piece);
335 if (dp->longer == Neither)
337 else if (dp->longer != (first = !!test_bit(0, &path))) {
338 /* took the shorter path */
339 dp->longer = Neither;
340 piece = dp->next[first];
342 } else if (first == (second = !!test_bit(1, &path))) {
343 /* just a two-point rotation */
344 piece = dir_rotate_2(block, psz, topp, first);
347 if (depth < 3) third = Neither;
348 else third = !!test_bit(2, &path);
349 piece = dir_rotate_3(block, psz, topp, first, third);
353 while (piece && st < depth) {
354 first = test_bit(st, &path) ? 1 : 0;
355 dp = dpaddr(block, piece);
357 piece = dp->next[first];
360 BUG_ON(dh->root == 0);
361 dir_check_balance(block, psz);
365 /* If there is room at the end, add an entry,
368 if (dh->lastpiece + need > 255)
373 space = dp->length + (dp->chain_info < 2 ? 0 : dp->chain_info == 2 ? 1 : 4);
374 space += offsetof(struct dirpiece, name);
375 space = DIV_ROUND_UP(space, 1<<psz);
377 piece = dh->lastpiece + 1;
379 dp = dpaddr(block, piece);
380 dh->lastpiece += need;
381 dh->freepieces -= need;
382 dh->freepieces += space;
384 dp->next[0] = dpold->next[0];
385 dp->next[1] = dpold->next[1];
386 dp->target = cpu_to_le32(target);
389 dir_set_name(dp, name, len, hashoffset);
393 int lafs_dir_del_ent(char *block, int psz, u32 seed, u32 hash)
395 /* Delete this entry from the directory block.
396 * This involves either it from the avl tree.
397 * If it was the last entry, we reduce 'lastpiece'
398 * so the space can be used immediately.
401 struct dirheader *dh = (struct dirheader*)block;
403 struct dirpiece *second;
404 int piece = dh->root;
405 u8 *thisp = &dh->root;
412 unsigned long path = 0;
415 dp = dpaddr(block, piece);
417 u32 hval = hash_piece(seed, dp, NULL);
424 if (dp->next[dir] == 0)
426 if (dp->longer == Neither) {
429 } else if (dp->longer == (1-dir)) {
430 struct dirpiece *dp2;
431 dp2 = dpaddr(block, dp->next[1-dir]);
432 if (dp2->longer == Neither) {
437 if (dir) set_bit(depth, &path);
438 else clear_bit(depth, &path);
440 if (depth >= sizeof(path)*8) return -2;
442 thisp = &dp->next[dir];
444 dp = dpaddr(block, piece);
448 if (dir) set_bit(depth, &path);
449 else clear_bit(depth, &path);
451 /* now we must walk down from topp to thisp rebalancing nodes,
452 * but making sure that targetp points to the link to target...
457 dir = !!test_bit(st, &path);
458 dp = dpaddr(block, piece);
459 if (dp->next[dir] == 0) break;
461 if (dp->longer == Neither)
463 else if (dp->longer == dir)
464 dp->longer = Neither;
466 /* need a rotation */
468 dpaddr(block, dp->next[1-dir]);
469 if (second->longer == dir) {
470 struct dirpiece *third =
471 dpaddr(block, second->next[dir]);
472 dir_rotate_3(block, psz, topp, 1-dir,
474 } else if (second->longer == Neither) {
475 dir_rotate_2(block, psz, topp, 1-dir);
477 second = dpaddr(block, *topp);
478 second->longer = dir;
480 dir_rotate_2(block, psz, topp, 1-dir);
481 if (piece == targetn) {
482 second = dpaddr(block, *topp);
483 targetp = &second->next[dir];
486 topp = &dp->next[dir];
490 /* Ok, rebalance all done, now swap *targetp for *thisp and
496 dp = dpaddr(block, piece);
497 second = dpaddr(block, targetn);
498 *thisp = dp->next[1-dir];
499 dp->next[0] = second->next[0];
500 dp->next[1] = second->next[1];
501 dp->longer = second->longer;
503 /* now second can be destroyed */
505 space = second->length + (second->chain_info < 2
506 ? 0 : second->chain_info == 2 ? 1 : 4);
507 space += offsetof(struct dirpiece, name);
508 space = DIV_ROUND_UP(space, 1<<psz);
510 /* we deleted the only entry, clear the block */
511 dh->lastpiece = (sizeof(struct dirheader)+ (1<<psz)-1) >> psz;
512 dh->freepieces = 255 - dh->lastpiece;
513 } else if (targetn + space > dh->lastpiece) {
514 /* We are deleting the last entry, so it can be reused */
515 dh->freepieces += dh->lastpiece+1-targetn;
516 dh->lastpiece = targetn-1;
518 dh->freepieces += space;
522 static void dir_linearise(char *block, int psz)
524 /* destructively linearise the entries in the block.
525 * i.e. arrange that for each non-deleted entry,
526 * ->next[0] points to the previous, and
527 * ->next[1] points to the next
529 * The first points to the last, and dh->root
530 * points to the first
532 * Rather than using a stack to walk down, we reverse
533 * each pointer was we step down it, and use
534 * the ->longer field to say which way we came
536 struct dirheader *dh = (struct dirheader*)block;
537 int piece = dh->root;
538 struct dirpiece *dp = NULL;
545 dp = dpaddr(block, piece);
547 case 0: /* stepping down to piece for the first time */
549 /* step further down */
551 dp->next[0] = parent;
559 case 1: /* back up from the left branch */
560 /* This must be next in sequence */
564 /* step down the other way */
567 dp->next[1] = parent;
574 case 2: /* back up from the right branch */
576 dp = dpaddr(block, piece);
578 parent = dp->next[state];
584 /* now 'prev' is the last piece. Walk back along the path setting
590 dp = dpaddr(block, prev);
600 lafs_dir_extract(char *block, int psz, struct dir_ent *de, int pnum,
603 /* extract the directory entry into de. de->name points into
604 * the buffer, and is not nul terminated. */
605 struct dirpiece *dp = dpaddr(block, pnum);
607 BUG_ON(pnum <= 0 || pnum > 255);
608 de->target = le32_to_cpu(dp->target);
611 de->nlen = dp->length;
613 *hash = hash_piece(*hash, dp, NULL);
617 void lafs_dir_set_target(char *block, int psz, struct dir_ent *de, int pnum)
619 /* update the target and type from de */
620 struct dirpiece *dp = dpaddr(block, pnum);
621 dp->target = cpu_to_le32(de->target);
625 void lafs_dir_split(char *orig, int psz, char *new1, char *new2,
626 const char *name, u32 target, int type, u32 *newhash,
627 u32 seed, u32 hash, int chainoffset)
629 /* Split the orig block together with the new name, into new1 and new2.
630 * Linearise orig, then copy one entry into which block is least empty
631 * A hash somewhere between the two blocks is placed in *newhash.
632 * It could be the highest in 'new1' but will be less than the
636 struct dirheader *dh = (struct dirheader*)orig;
637 struct dirheader *dh1 = (struct dirheader*)new1;
638 struct dirheader *dh2 = (struct dirheader*)new2;
641 int full1=0, full2=0;
642 u32 offset, maxhash, minhash, hval;
644 dir_linearise(orig, psz);
647 dp = dpaddr(orig, first);
649 if (first == 0 || last == 0)
650 /* orig was empty ?? */
653 /* create new1 and new2 with first and last */
654 hval = hash_piece(seed, dp, &offset);
655 if (type && hash < hval) {
656 lafs_dir_init_block(new1, psz, name, 0, target, type,
661 lafs_dir_init_block(new1, psz, dp->name, dp->length,
662 le32_to_cpu(dp->target), dp->type,
670 dp = dpaddr(orig, last);
671 hval = hash_piece(seed, dp, &offset);
672 if (type && hash > hval) {
673 lafs_dir_init_block(new2, psz, name, 0, target, type,
679 lafs_dir_init_block(new2, psz, dp->name, dp->length,
680 le32_to_cpu(dp->target), dp->type,
689 while (first || type) {
690 /* everything from 'first' to 'last', plus 'name' (if type)
691 * is allowed to go in either block.
692 * Choose a block, and an entry, and insert it (if possible)
694 if (full2 || (dh1->freepieces >= dh2->freepieces && ! full1)) {
695 /* insert into new1 from first or name */
696 dp = dpaddr(orig, first);
698 hval = hash_piece(seed, dp, &offset);
699 if (type == 0 || (first && hval < hash)) {
700 /* first is the preferred candidate */
701 if (!lafs_dir_add_ent(new1, psz, dp->name,
703 le32_to_cpu(dp->target),
704 dp->type, seed, hval, offset))
715 if (!lafs_dir_add_ent(new1, psz, name, 0, target,
716 type, seed, hash, chainoffset))
724 /* insert into new2 */
725 dp = dpaddr(orig, last);
727 hval = hash_piece(seed, dp, &offset);
728 if (type == 0 || (first && hval > hash )) {
729 /* last is the preferred candidate */
730 if (!lafs_dir_add_ent(new2, psz,
731 dp->name, dp->length,
732 le32_to_cpu(dp->target),
733 dp->type, seed, hval, offset))
743 if (!lafs_dir_add_ent(new2, psz, name, 0,
755 /* newhash could be minhash, but not
757 *newhash = (minhash + maxhash) / 2;
760 void lafs_dir_repack(char *block, int psz, char *new, u32 seed, int merge)
762 struct dirheader *dh = (struct dirheader*)block;
763 int pnum = (sizeof(struct dirheader) + (1<<psz)-1)>>psz;
766 while (pnum <= dh->lastpiece) {
768 struct dirpiece *dp = dpaddr(block, pnum);
772 u32 hash = hash_piece(seed, dp, &offset);
774 lafs_dir_init_block(new, psz, dp->name,
776 le32_to_cpu(dp->target),
779 lafs_dir_add_ent(new, psz, dp->name, dp->length,
780 le32_to_cpu(dp->target),
781 dp->type, seed, hash, offset);
784 space = dp->length + (dp->chain_info < 2 ? 0 : dp->chain_info == 2 ? 1 : 4);
785 space += offsetof(struct dirpiece, name);
786 space = DIV_ROUND_UP(space, 1<<psz);
792 int lafs_dir_find(char *block, int psz, u32 seed, u32 hash, u8 *pp)
794 /* Find the entry for 'hash', if it exists.
795 * Return 1 if found, 0 if not.
796 * set 'pp' to the piece number if found, or the
797 * next larger piece if not (zero if nothing is larger).
799 struct dirheader *dh = (struct dirheader*)block;
805 while (pnum && cnt) {
806 struct dirpiece *dp = dpaddr(block, pnum);
807 u32 hval = hash_piece(seed, dp, NULL);
825 int dir_check_loop(char *block, int psz, int pnum, int depth)
827 /* walk around the tree, and BUG if we ever get a depth > 255 */
828 struct dirheader *dh = (struct dirheader*)block;
832 if (depth <= 0) return 1;
833 if (pnum < 0 || pnum >= 256)
837 struct dirpiece *dp = dpaddr(block, pnum);
838 if (dir_check_loop(block, psz, dp->next[0], depth-1) ||
839 dir_check_loop(block, psz, dp->next[1], depth-1)) {
840 printk(" ..%d(%d)\n", pnum, depth);
847 int lafs_dir_empty(char *block)
849 struct dirheader *dh = (struct dirheader*)block;
850 return dh->root == 0;
853 int lafs_dir_blk_size(char *block, int psz)
855 /* how much of this block do we actually need to store */
856 struct dirheader *dh = (struct dirheader*)block;
857 if (lafs_dir_empty(block))
859 return (dh->lastpiece+1) << psz;
864 /* Testing code here - no new important functionality */
867 static void xprintk(char *block, int psz, char *s, int a, int b, int c, int d)
870 dir_print(block, psz);
874 static int dir_check_depth(char *block, int psz, int p)
876 struct dirpiece *dp = dpaddr(block,p);
879 if (p == 0) return 0;
880 b = dir_check_depth(block, psz, dp->next[0]);
881 f = dir_check_depth(block, psz, dp->next[1]);
883 if (dp->longer != Neither)
884 xprintk(block,psz, "... %d - b=%d f=%d lgr=%d\n", p, b, f, dp->longer);
889 xprintk(block,psz, "... %d - b=%d f=%d lgr=%d\n", p, b, f, dp->longer);
894 xprintk(block,psz, "... %d - b=%d f=%d lgr=%d\n", p, b, f, dp->longer);
897 xprintk(block,psz, "... %d - b=%d f=%d lgr=%d\n", p, b, f, dp->longer);
901 static void dir_check_balance(char *block, int psz)
903 struct dirheader *dh = (struct dirheader*) block;
904 dir_check_depth(block, psz, dh->root);
907 static void dir_print_piece(char *block, int psz, int piece, int depth, int dir)
909 struct dirpiece *dp = dpaddr(block, piece);
911 if (piece == 0) return;
913 dir_print_piece(block, psz, dp->next[0], depth+1, 0);
914 printk("%3d - %08lu:%02d %*s%c", piece, (unsigned long) le32_to_cpu(dp->target),
918 printk("%.*s\n", dp->length, dp->name);
919 dir_print_piece(block, psz, dp->next[1], depth+1, 1);
922 static void dir_print_block(char *block, int psz, int sort)
924 struct dirheader *dh;
927 dh = (struct dirheader *)block;
928 printk("===Directory Block===\n");
930 printk(" Root: %d\n", dh->root);
931 printk(" Last Piece : %d (%d left)\n", dh->lastpiece, 255 - dh->lastpiece);
932 printk(" Free Pieces: %d (%d deleted)\n", dh->freepieces, dh->freepieces - (255 - dh->lastpiece));
935 printk( "!!!!!! Reserved is non-zero : %d\n", dh->reserved);
938 dir_print_piece(block, psz, dh->root, 0, 1);
939 else if (sort == 2) {
943 dp = dpaddr(block, pnum);
944 printk("%3d - %08lu: (b:%-3d, f:%-3d, l:%d, type:%d ",
945 pnum, (unsigned long) le32_to_cpu(dp->target),
946 dp->next[0], dp->next[1], dp->longer,
948 printk(": (%d)%.*s\n", dp->length, dp->length, dp->name);
952 /* don't interpret the pieces too much */
953 int pnum = (sizeof(struct dirheader)+ (1<<psz)-1)>>psz;
954 while (pnum <= dh->lastpiece) {
955 dp = dpaddr(block, pnum);
956 printk("%3d - %08lu: (b:%-3d, f:%-3d, l:%d, type:%d ",
957 pnum, (unsigned long)le32_to_cpu(dp->target),
958 dp->next[0], dp->next[1], dp->longer,
960 printk(": (%d)%.*s\n", dp->length, dp->length, dp->name);
961 pnum += (offsetof(struct dirpiece, name) + dp->length +(1<<psz)-1)>>psz;
965 void dir_print(char *buf, int psz)
967 dir_print_block(buf, psz, 1);
975 int main(int argc, char **argv)
979 int psz = blenshift - 8;
983 lafs_dir_init_block(block, psz, argv[1], 0, 42, 3, 0);
984 while (arg < argc-1) {
985 if (argv[arg][0] != '-')
986 switch(lafs_dir_add_ent(block, psz, argv[arg], 0, 42+arg, 4, 0)) {
987 case 0: printf("%s didn't fit!\n", argv[arg]); break;
988 case -1: printf("%s already exists\n", argv[arg]); break;
989 case 1: printf("%s inserted\n", argv[arg]);
992 switch (lafs_dir_del_ent(block, psz, argv[arg]+1, 0)) {
993 case 0: printf("%s not found!\n", argv[arg]); break;
994 case -2:printf("%s not deleted - bad dir\n", argv[arg]); break;
995 case 1: printf("%s deleted\n", argv[arg]); break;
998 dir_check_balance(block, psz);
1001 dir_print_block(block, psz, 0);
1002 dir_print_block(block, psz, 1);
1004 lafs_dir_split(block, psz, block+1024, block+2048, argv[arg], 40, 2, nm);
1005 dir_print_block(block+1024, psz, 1);
1006 dir_print_block(block+2048, psz, 1);
1007 dir_get_prefix(block+1024, block+2048, psz, block+3096);
1008 printf("Prefix is <%s>\n", block+3096);
1009 lafs_dir_repack(block+1024, psz, block, 0);
1010 lafs_dir_repack(block+2048, psz, block, 1);
1011 printf("============= repacked ===================\n");
1012 dir_print_block(block, psz, 1);