This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / reiserfs / prints.c
1 /*
2  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
3  */
4
5 #include <linux/config.h>
6 #include <linux/time.h>
7 #include <linux/fs.h>
8 #include <linux/reiserfs_fs.h>
9 #include <linux/string.h>
10 #include <linux/buffer_head.h>
11
12 #include <stdarg.h>
13
14 static char error_buf[1024];
15 static char fmt_buf[1024];
16 static char off_buf[80];
17
18
19 static char * reiserfs_cpu_offset (struct cpu_key * key)
20 {
21   if (cpu_key_k_type(key) == TYPE_DIRENTRY)
22     sprintf (off_buf, "%Lu(%Lu)", 
23              (unsigned long long)GET_HASH_VALUE (cpu_key_k_offset (key)),
24              (unsigned long long)GET_GENERATION_NUMBER (cpu_key_k_offset (key)));
25   else
26     sprintf (off_buf, "0x%Lx", (unsigned long long)cpu_key_k_offset (key));
27   return off_buf;
28 }
29
30
31 static char * le_offset (struct reiserfs_key * key)
32 {
33   int version;
34
35   version = le_key_version (key);
36   if (le_key_k_type (version, key) == TYPE_DIRENTRY)
37     sprintf (off_buf, "%Lu(%Lu)", 
38              (unsigned long long)GET_HASH_VALUE (le_key_k_offset (version, key)),
39              (unsigned long long)GET_GENERATION_NUMBER (le_key_k_offset (version, key)));
40   else
41     sprintf (off_buf, "0x%Lx", (unsigned long long)le_key_k_offset (version, key));
42   return off_buf;
43 }
44
45
46 static char * cpu_type (struct cpu_key * key)
47 {
48     if (cpu_key_k_type (key) == TYPE_STAT_DATA)
49         return "SD";
50     if (cpu_key_k_type (key) == TYPE_DIRENTRY)
51         return "DIR";
52     if (cpu_key_k_type (key) == TYPE_DIRECT)
53         return "DIRECT";
54     if (cpu_key_k_type (key) == TYPE_INDIRECT)
55         return "IND";
56     return "UNKNOWN";
57 }
58
59
60 static char * le_type (struct reiserfs_key * key)
61 {
62     int version;
63     
64     version = le_key_version (key);
65
66     if (le_key_k_type (version, key) == TYPE_STAT_DATA)
67         return "SD";
68     if (le_key_k_type (version, key) == TYPE_DIRENTRY)
69         return "DIR";
70     if (le_key_k_type (version, key) == TYPE_DIRECT)
71         return "DIRECT";
72     if (le_key_k_type (version, key) == TYPE_INDIRECT)
73         return "IND";
74     return "UNKNOWN";
75 }
76
77
78 /* %k */
79 static void sprintf_le_key (char * buf, struct reiserfs_key * key)
80 {
81   if (key)
82     sprintf (buf, "[%d %d %s %s]", le32_to_cpu (key->k_dir_id),
83              le32_to_cpu (key->k_objectid), le_offset (key), le_type (key));
84   else
85     sprintf (buf, "[NULL]");
86 }
87
88
89 /* %K */
90 static void sprintf_cpu_key (char * buf, struct cpu_key * key)
91 {
92   if (key)
93     sprintf (buf, "[%d %d %s %s]", key->on_disk_key.k_dir_id,
94              key->on_disk_key.k_objectid, reiserfs_cpu_offset (key),
95              cpu_type (key));
96   else
97     sprintf (buf, "[NULL]");
98 }
99
100 static void sprintf_de_head( char *buf, struct reiserfs_de_head *deh )
101 {
102     if( deh )
103         sprintf( buf, "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", deh_offset(deh), deh_dir_id(deh),
104                  deh_objectid(deh), deh_location(deh), deh_state(deh) );
105     else
106         sprintf( buf, "[NULL]" );
107
108 }
109
110 static void sprintf_item_head (char * buf, struct item_head * ih)
111 {
112     if (ih) {
113         strcpy (buf, (ih_version (ih) == KEY_FORMAT_3_6) ? "*3.6* " : "*3.5*");
114         sprintf_le_key (buf + strlen (buf), &(ih->ih_key));
115         sprintf (buf + strlen (buf), ", item_len %d, item_location %d, "
116                  "free_space(entry_count) %d",
117                  ih_item_len(ih), ih_location(ih), ih_free_space (ih));
118     } else
119         sprintf (buf, "[NULL]");
120 }
121
122
123 static void sprintf_direntry (char * buf, struct reiserfs_dir_entry * de)
124 {
125   char name[20];
126
127   memcpy (name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen);
128   name [de->de_namelen > 19 ? 19 : de->de_namelen] = 0;
129   sprintf (buf, "\"%s\"==>[%d %d]", name, de->de_dir_id, de->de_objectid);
130 }
131
132
133 static void sprintf_block_head (char * buf, struct buffer_head * bh)
134 {
135   sprintf (buf, "level=%d, nr_items=%d, free_space=%d rdkey ",
136            B_LEVEL (bh), B_NR_ITEMS (bh), B_FREE_SPACE (bh));
137 }
138
139
140 static void sprintf_buffer_head (char * buf, struct buffer_head * bh) 
141 {
142   char b[BDEVNAME_SIZE];
143
144   sprintf (buf, "dev %s, size %d, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)",
145            bdevname (bh->b_bdev, b), bh->b_size,
146            (unsigned long long)bh->b_blocknr,
147            atomic_read (&(bh->b_count)),
148            bh->b_state, bh->b_page,
149            buffer_uptodate (bh) ? "UPTODATE" : "!UPTODATE",
150            buffer_dirty (bh) ? "DIRTY" : "CLEAN",
151            buffer_locked (bh) ? "LOCKED" : "UNLOCKED");
152 }
153
154
155 static void sprintf_disk_child (char * buf, struct disk_child * dc)
156 {
157   sprintf (buf, "[dc_number=%d, dc_size=%u]", dc_block_number(dc), dc_size(dc));
158 }
159
160
161 static char * is_there_reiserfs_struct (char * fmt, int * what, int * skip)
162 {
163   char * k = fmt;
164
165   *skip = 0;
166   
167   while ((k = strchr (k, '%')) != NULL)
168   {
169     if (k[1] == 'k' || k[1] == 'K' || k[1] == 'h' || k[1] == 't' ||
170               k[1] == 'z' || k[1] == 'b' || k[1] == 'y' || k[1] == 'a' ) {
171       *what = k[1];
172       break;
173     }
174     (*skip) ++;
175     k ++;
176   }
177   return k;
178 }
179
180
181 /* debugging reiserfs we used to print out a lot of different
182    variables, like keys, item headers, buffer heads etc. Values of
183    most fields matter. So it took a long time just to write
184    appropriative printk. With this reiserfs_warning you can use format
185    specification for complex structures like you used to do with
186    printfs for integers, doubles and pointers. For instance, to print
187    out key structure you have to write just: 
188    reiserfs_warning ("bad key %k", key); 
189    instead of 
190    printk ("bad key %lu %lu %lu %lu", key->k_dir_id, key->k_objectid, 
191            key->k_offset, key->k_uniqueness); 
192 */
193
194
195 static void
196 prepare_error_buf( const char *fmt, va_list args )
197 {
198     char * fmt1 = fmt_buf;
199     char * k;
200     char * p = error_buf;
201     int i, j, what, skip;
202
203     strcpy (fmt1, fmt);
204
205     while( (k = is_there_reiserfs_struct( fmt1, &what, &skip )) != NULL )
206     {
207         *k = 0;
208
209         p += vsprintf (p, fmt1, args);
210
211         for (i = 0; i < skip; i ++)
212             j = va_arg (args, int);
213
214         switch (what) {
215         case 'k':
216             sprintf_le_key (p, va_arg(args, struct reiserfs_key *));
217             break;
218         case 'K':
219             sprintf_cpu_key (p, va_arg(args, struct cpu_key *));
220             break;
221         case 'h':
222             sprintf_item_head (p, va_arg(args, struct item_head *));
223             break;
224         case 't':
225             sprintf_direntry (p, va_arg(args, struct reiserfs_dir_entry *));
226             break;
227         case 'y':
228             sprintf_disk_child (p, va_arg(args, struct disk_child *));
229             break;
230         case 'z':
231             sprintf_block_head (p, va_arg(args, struct buffer_head *));
232             break;
233         case 'b':
234             sprintf_buffer_head (p, va_arg(args, struct buffer_head *));
235             break;
236         case 'a':
237             sprintf_de_head (p, va_arg(args, struct reiserfs_de_head *));
238             break;
239         }
240
241         p += strlen (p);
242         fmt1 = k + 2;
243     }
244     vsprintf (p, fmt1, args);
245
246 }
247
248
249 /* in addition to usual conversion specifiers this accepts reiserfs
250    specific conversion specifiers: 
251    %k to print little endian key, 
252    %K to print cpu key, 
253    %h to print item_head,
254    %t to print directory entry 
255    %z to print block head (arg must be struct buffer_head *
256    %b to print buffer_head
257 */
258
259 #define do_reiserfs_warning(fmt)\
260 {\
261     va_list args;\
262     va_start( args, fmt );\
263     prepare_error_buf( fmt, args );\
264     va_end( args );\
265 }
266
267 void reiserfs_warning (struct super_block *sb, const char * fmt, ...)
268 {
269   do_reiserfs_warning(fmt);
270   if (sb)
271       printk (KERN_WARNING "ReiserFS: %s: warning: %s\n",
272              reiserfs_bdevname (sb), error_buf);
273   else
274       printk (KERN_WARNING "ReiserFS: warning: %s\n", error_buf);
275 }
276
277 /* No newline.. reiserfs_info calls can be followed by printk's */
278 void reiserfs_info (struct super_block *sb, const char * fmt, ...)
279 {
280   do_reiserfs_warning(fmt);
281   if (sb)
282       printk (KERN_NOTICE "ReiserFS: %s: %s",
283              reiserfs_bdevname (sb), error_buf);
284   else
285       printk (KERN_NOTICE "ReiserFS: %s", error_buf);
286 }
287
288 /* No newline.. reiserfs_printk calls can be followed by printk's */
289 void reiserfs_printk (const char * fmt, ...)
290 {
291   do_reiserfs_warning(fmt);
292   printk (error_buf);
293 }
294
295 void reiserfs_debug (struct super_block *s, int level, const char * fmt, ...)
296 {
297 #ifdef CONFIG_REISERFS_CHECK
298   do_reiserfs_warning(fmt);
299   if (s)
300       printk (KERN_DEBUG "ReiserFS: %s: %s\n",
301              reiserfs_bdevname (s), error_buf);
302   else
303       printk (KERN_DEBUG "ReiserFS: %s\n", error_buf);
304 #endif
305 }
306
307 /* The format:
308
309            maintainer-errorid: [function-name:] message
310
311     where errorid is unique to the maintainer and function-name is
312     optional, is recommended, so that anyone can easily find the bug
313     with a simple grep for the short to type string
314     maintainer-errorid.  Don't bother with reusing errorids, there are
315     lots of numbers out there.
316
317     Example: 
318     
319     reiserfs_panic(
320         p_sb, "reiser-29: reiserfs_new_blocknrs: "
321         "one of search_start or rn(%d) is equal to MAX_B_NUM,"
322         "which means that we are optimizing location based on the bogus location of a temp buffer (%p).", 
323         rn, bh
324     );
325
326     Regular panic()s sometimes clear the screen before the message can
327     be read, thus the need for the while loop.  
328
329     Numbering scheme for panic used by Vladimir and Anatoly( Hans completely ignores this scheme, and considers it
330     pointless complexity):
331
332     panics in reiserfs_fs.h have numbers from 1000 to 1999
333     super.c                                     2000 to 2999
334     preserve.c (unused)                     3000 to 3999
335     bitmap.c                                4000 to 4999
336     stree.c                                     5000 to 5999
337     prints.c                                6000 to 6999
338     namei.c                     7000 to 7999
339     fix_nodes.c                 8000 to 8999
340     dir.c                       9000 to 9999
341         lbalance.c                                      10000 to 10999
342         ibalance.c              11000 to 11999 not ready
343         do_balan.c              12000 to 12999
344         inode.c                 13000 to 13999
345         file.c                  14000 to 14999
346     objectid.c                       15000 - 15999
347     buffer.c                         16000 - 16999
348     symlink.c                        17000 - 17999
349
350    .  */
351
352
353 #ifdef CONFIG_REISERFS_CHECK
354 extern struct tree_balance * cur_tb;
355 #endif
356
357 void reiserfs_panic (struct super_block * sb, const char * fmt, ...)
358 {
359   do_reiserfs_warning(fmt);
360   printk (KERN_EMERG "REISERFS: panic (device %s): %s\n",
361           reiserfs_bdevname (sb), error_buf);
362   BUG ();
363
364   /* this is not actually called, but makes reiserfs_panic() "noreturn" */
365   panic ("REISERFS: panic (device %s): %s\n",
366          reiserfs_bdevname (sb), error_buf);
367 }
368
369 static void
370 do_handle_error (struct super_block *sb, int errno)
371 {
372     if (reiserfs_error_panic (sb)) {
373         panic ("REISERFS: panic (device %s): Panic forced after error\n",
374                reiserfs_bdevname (sb));
375     }
376
377     if (reiserfs_error_ro (sb)) {
378         printk (KERN_CRIT "REISERFS: error (device %s): Re-mounting fs "
379                 "readonly\n", reiserfs_bdevname (sb));
380         reiserfs_journal_abort (sb, errno);
381     }
382 }
383
384 void
385 reiserfs_error (struct super_block * sb, int errno, const char *fmt, ...)
386 {
387     do_reiserfs_warning (fmt);
388     printk (KERN_CRIT "REISERFS: error (device %s): %s\n",
389             reiserfs_bdevname (sb), error_buf);
390     do_handle_error (sb, errno);
391 }
392
393 void
394 reiserfs_abort (struct super_block *sb, int errno, const char *fmt, ...)
395 {
396     do_reiserfs_warning (fmt);
397
398     if (reiserfs_error_panic (sb)) {
399         panic (KERN_CRIT "REISERFS: panic (device %s): %s\n",
400                reiserfs_bdevname (sb), error_buf);
401     }
402
403     if (sb->s_flags & MS_RDONLY)
404         return;
405
406     printk (KERN_CRIT "REISERFS: abort (device %s): %s\n",
407             reiserfs_bdevname (sb), error_buf);
408
409     sb->s_flags |= MS_RDONLY;
410     reiserfs_journal_abort (sb, errno);
411 }
412
413 void print_virtual_node (struct virtual_node * vn)
414 {
415     int i;
416     struct virtual_item * vi;
417
418     printk ("VIRTUAL NODE CONTAINS %d items, has size %d,%s,%s, ITEM_POS=%d POS_IN_ITEM=%d MODE=\'%c\'\n",
419             vn->vn_nr_item, vn->vn_size,
420             (vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE )? "left mergeable" : "", 
421             (vn->vn_vi[vn->vn_nr_item - 1].vi_type & VI_TYPE_RIGHT_MERGEABLE) ? "right mergeable" : "",
422             vn->vn_affected_item_num, vn->vn_pos_in_item, vn->vn_mode);
423     
424     vi = vn->vn_vi;
425     for (i = 0; i < vn->vn_nr_item; i ++, vi ++)
426         op_print_vi (vi);
427         
428 }
429
430
431 void print_path (struct tree_balance * tb, struct path * path)
432 {
433     int h = 0;
434     struct buffer_head * bh;
435     
436     if (tb) {
437         while (tb->insert_size[h]) {
438             bh = PATH_H_PBUFFER (path, h);
439             printk ("block %llu (level=%d), position %d\n", bh ? (unsigned long long)bh->b_blocknr : 0LL,
440                     bh ? B_LEVEL (bh) : 0, PATH_H_POSITION (path, h));
441             h ++;
442         }
443   } else {
444       int offset = path->path_length;
445       struct buffer_head * bh;
446       printk ("Offset    Bh     (b_blocknr, b_count) Position Nr_item\n");
447       while ( offset > ILLEGAL_PATH_ELEMENT_OFFSET ) {
448           bh = PATH_OFFSET_PBUFFER (path, offset);
449           printk ("%6d %10p (%9llu, %7d) %8d %7d\n", offset, 
450                   bh, bh ? (unsigned long long)bh->b_blocknr : 0LL, bh ? atomic_read (&(bh->b_count)) : 0,
451                   PATH_OFFSET_POSITION (path, offset), bh ? B_NR_ITEMS (bh) : -1);
452           
453           offset --;
454       }
455   }
456
457 }
458
459
460 /* this prints internal nodes (4 keys/items in line) (dc_number,
461    dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number,
462    dc_size)...*/
463 static int print_internal (struct buffer_head * bh, int first, int last)
464 {
465     struct reiserfs_key * key;
466     struct disk_child * dc;
467     int i;
468     int from, to;
469     
470     if (!B_IS_KEYS_LEVEL (bh))
471         return 1;
472
473     check_internal (bh);
474     
475     if (first == -1) {
476         from = 0;
477         to = B_NR_ITEMS (bh);
478     } else {
479         from = first;
480         to = last < B_NR_ITEMS (bh) ? last : B_NR_ITEMS (bh);
481     }
482
483     reiserfs_printk ("INTERNAL NODE (%ld) contains %z\n",  bh->b_blocknr, bh);
484     
485     dc = B_N_CHILD (bh, from);
486     reiserfs_printk ("PTR %d: %y ", from, dc);
487     
488     for (i = from, key = B_N_PDELIM_KEY (bh, from), dc ++; i < to; i ++, key ++, dc ++) {
489         reiserfs_printk ("KEY %d: %k PTR %d: %y ", i, key, i + 1, dc);
490         if (i && i % 4 == 0)
491             printk ("\n");
492     }
493     printk ("\n");
494     return 0;
495 }
496
497
498
499
500
501 static int print_leaf (struct buffer_head * bh, int print_mode, int first, int last)
502 {
503     struct block_head * blkh;
504     struct item_head * ih;
505     int i, nr;
506     int from, to;
507
508     if (!B_IS_ITEMS_LEVEL (bh))
509         return 1;
510
511     check_leaf (bh);
512
513     blkh = B_BLK_HEAD (bh);
514     ih = B_N_PITEM_HEAD (bh,0);
515     nr = blkh_nr_item(blkh);
516
517     printk ("\n===================================================================\n");
518     reiserfs_printk ("LEAF NODE (%ld) contains %z\n", bh->b_blocknr, bh);
519
520     if (!(print_mode & PRINT_LEAF_ITEMS)) {
521         reiserfs_printk ("FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n",
522                           &(ih->ih_key), &((ih + nr - 1)->ih_key));
523         return 0;
524     }
525
526     if (first < 0 || first > nr - 1) 
527         from = 0;
528     else 
529         from = first;
530
531     if (last < 0 || last > nr )
532         to = nr;
533     else
534         to = last;
535
536     ih += from;
537     printk ("-------------------------------------------------------------------------------\n");
538     printk ("|##|   type    |           key           | ilen | free_space | version | loc  |\n");
539     for (i = from; i < to; i++, ih ++) {
540         printk ("-------------------------------------------------------------------------------\n");
541         reiserfs_printk ("|%2d| %h |\n", i, ih);
542         if (print_mode & PRINT_LEAF_ITEMS)
543             op_print_item (ih, B_I_PITEM (bh, ih));
544     }
545
546     printk ("===================================================================\n");
547
548     return 0;
549 }
550
551 char * reiserfs_hashname(int code)
552 {
553     if ( code == YURA_HASH)
554         return "rupasov";
555     if ( code == TEA_HASH)
556         return "tea";
557     if ( code == R5_HASH)
558         return "r5";
559
560     return "unknown";
561 }
562
563 /* return 1 if this is not super block */
564 static int print_super_block (struct buffer_head * bh)
565 {
566     struct reiserfs_super_block * rs = (struct reiserfs_super_block *)(bh->b_data);
567     int skipped, data_blocks;
568     char *version;
569     char b[BDEVNAME_SIZE];
570
571     if (is_reiserfs_3_5(rs)) {
572         version = "3.5";
573     } else if (is_reiserfs_3_6(rs)) {
574         version = "3.6";
575     } else if (is_reiserfs_jr(rs)) {
576       version = ((sb_version(rs) == REISERFS_VERSION_2) ?
577                  "3.6" : "3.5");  
578     } else {
579         return 1;
580     }
581
582     printk ("%s\'s super block is in block %llu\n", bdevname (bh->b_bdev, b),
583             (unsigned long long)bh->b_blocknr);
584     printk ("Reiserfs version %s\n", version );
585     printk ("Block count %u\n", sb_block_count(rs));
586     printk ("Blocksize %d\n", sb_blocksize(rs));
587     printk ("Free blocks %u\n", sb_free_blocks(rs));
588     // FIXME: this would be confusing if
589     // someone stores reiserfs super block in some data block ;)
590 //    skipped = (bh->b_blocknr * bh->b_size) / sb_blocksize(rs);
591     skipped = bh->b_blocknr;
592     data_blocks = sb_block_count(rs) - skipped - 1 - sb_bmap_nr(rs) -
593             (!is_reiserfs_jr(rs) ? sb_jp_journal_size(rs) + 1 : sb_reserved_for_journal(rs)) -      
594             sb_free_blocks(rs);
595     printk ("Busy blocks (skipped %d, bitmaps - %d, journal (or reserved) blocks - %d\n"
596             "1 super block, %d data blocks\n", 
597             skipped, sb_bmap_nr(rs), (!is_reiserfs_jr(rs) ? (sb_jp_journal_size(rs) + 1) :
598                                       sb_reserved_for_journal(rs)) , data_blocks);
599     printk ("Root block %u\n", sb_root_block(rs));
600     printk ("Journal block (first) %d\n", sb_jp_journal_1st_block(rs));
601     printk ("Journal dev %d\n", sb_jp_journal_dev(rs));
602     printk ("Journal orig size %d\n", sb_jp_journal_size(rs));
603     printk ("FS state %d\n", sb_fs_state(rs));
604     printk ("Hash function \"%s\"\n",
605             reiserfs_hashname(sb_hash_function_code(rs)));
606     
607     printk ("Tree height %d\n", sb_tree_height(rs));
608     return 0;
609 }
610
611 static int print_desc_block (struct buffer_head * bh)
612 {
613     struct reiserfs_journal_desc * desc;
614
615     if (memcmp(get_journal_desc_magic (bh), JOURNAL_DESC_MAGIC, 8))
616         return 1;
617
618     desc = (struct reiserfs_journal_desc *)(bh->b_data);
619     printk ("Desc block %llu (j_trans_id %d, j_mount_id %d, j_len %d)",
620             (unsigned long long)bh->b_blocknr, get_desc_trans_id (desc), get_desc_mount_id (desc),
621             get_desc_trans_len (desc));
622
623     return 0;
624 }
625
626
627 void print_block (struct buffer_head * bh, ...)//int print_mode, int first, int last)
628 {
629     va_list args;
630     int mode, first, last;
631
632     va_start (args, bh);
633
634     if ( ! bh ) {
635         printk("print_block: buffer is NULL\n");
636         return;
637     }
638
639     mode = va_arg (args, int);
640     first = va_arg (args, int);
641     last = va_arg (args, int);
642     if (print_leaf (bh, mode, first, last))
643         if (print_internal (bh, first, last))
644             if (print_super_block (bh))
645                 if (print_desc_block (bh))
646                     printk ("Block %llu contains unformatted data\n", (unsigned long long)bh->b_blocknr);
647 }
648
649
650
651 char print_tb_buf[2048];
652
653 /* this stores initial state of tree balance in the print_tb_buf */
654 void store_print_tb (struct tree_balance * tb)
655 {
656     int h = 0;
657     int i;
658     struct buffer_head * tbSh, * tbFh;
659
660     if (!tb)
661         return;
662
663     sprintf (print_tb_buf, "\n"
664              "BALANCING %d\n"
665              "MODE=%c, ITEM_POS=%d POS_IN_ITEM=%d\n" 
666              "=====================================================================\n"
667              "* h *    S    *    L    *    R    *   F   *   FL  *   FR  *  CFL  *  CFR  *\n",
668              REISERFS_SB(tb->tb_sb)->s_do_balance,
669              tb->tb_mode, PATH_LAST_POSITION (tb->tb_path), tb->tb_path->pos_in_item);
670   
671     for (h = 0; h < sizeof(tb->insert_size) / sizeof (tb->insert_size[0]); h ++) {
672         if (PATH_H_PATH_OFFSET (tb->tb_path, h) <= tb->tb_path->path_length && 
673             PATH_H_PATH_OFFSET (tb->tb_path, h) > ILLEGAL_PATH_ELEMENT_OFFSET) {
674             tbSh = PATH_H_PBUFFER (tb->tb_path, h);
675             tbFh = PATH_H_PPARENT (tb->tb_path, h);
676         } else {
677             tbSh = NULL;
678             tbFh = NULL;
679         }
680         sprintf (print_tb_buf + strlen (print_tb_buf),
681                  "* %d * %3lld(%2d) * %3lld(%2d) * %3lld(%2d) * %5lld * %5lld * %5lld * %5lld * %5lld *\n",
682                  h, 
683                  (tbSh) ? (long long)(tbSh->b_blocknr):(-1LL),
684                  (tbSh) ? atomic_read (&(tbSh->b_count)) : -1,
685                  (tb->L[h]) ? (long long)(tb->L[h]->b_blocknr):(-1LL),
686                  (tb->L[h]) ? atomic_read (&(tb->L[h]->b_count)) : -1,
687                  (tb->R[h]) ? (long long)(tb->R[h]->b_blocknr):(-1LL),
688                  (tb->R[h]) ? atomic_read (&(tb->R[h]->b_count)) : -1,
689                  (tbFh) ? (long long)(tbFh->b_blocknr):(-1LL),
690                  (tb->FL[h]) ? (long long)(tb->FL[h]->b_blocknr):(-1LL),
691                  (tb->FR[h]) ? (long long)(tb->FR[h]->b_blocknr):(-1LL),
692                  (tb->CFL[h]) ? (long long)(tb->CFL[h]->b_blocknr):(-1LL),
693                  (tb->CFR[h]) ? (long long)(tb->CFR[h]->b_blocknr):(-1LL));
694     }
695
696     sprintf (print_tb_buf + strlen (print_tb_buf), 
697              "=====================================================================\n"
698              "* h * size * ln * lb * rn * rb * blkn * s0 * s1 * s1b * s2 * s2b * curb * lk * rk *\n"
699              "* 0 * %4d * %2d * %2d * %2d * %2d * %4d * %2d * %2d * %3d * %2d * %3d * %4d * %2d * %2d *\n",
700              tb->insert_size[0], tb->lnum[0], tb->lbytes, tb->rnum[0],tb->rbytes, tb->blknum[0], 
701              tb->s0num, tb->s1num,tb->s1bytes,  tb->s2num, tb->s2bytes, tb->cur_blknum, tb->lkey[0], tb->rkey[0]);
702
703     /* this prints balance parameters for non-leaf levels */
704     h = 0;
705     do {
706         h++;
707         sprintf (print_tb_buf + strlen (print_tb_buf),
708                  "* %d * %4d * %2d *    * %2d *    * %2d *\n",
709                 h, tb->insert_size[h], tb->lnum[h], tb->rnum[h], tb->blknum[h]);
710     } while (tb->insert_size[h]);
711
712     sprintf (print_tb_buf + strlen (print_tb_buf), 
713              "=====================================================================\n"
714              "FEB list: ");
715
716     /* print FEB list (list of buffers in form (bh (b_blocknr, b_count), that will be used for new nodes) */
717     h = 0;
718     for (i = 0; i < sizeof (tb->FEB) / sizeof (tb->FEB[0]); i ++)
719         sprintf (print_tb_buf + strlen (print_tb_buf),
720                  "%p (%llu %d)%s", tb->FEB[i], tb->FEB[i] ? (unsigned long long)tb->FEB[i]->b_blocknr : 0ULL,
721                  tb->FEB[i] ? atomic_read (&(tb->FEB[i]->b_count)) : 0, 
722                  (i == sizeof (tb->FEB) / sizeof (tb->FEB[0]) - 1) ? "\n" : ", ");
723
724     sprintf (print_tb_buf + strlen (print_tb_buf), 
725              "======================== the end ====================================\n");
726 }
727
728 void print_cur_tb (char * mes)
729 {
730     printk ("%s\n%s", mes, print_tb_buf);
731 }
732
733 static void check_leaf_block_head (struct buffer_head * bh)
734 {
735   struct block_head * blkh;
736   int nr;
737
738   blkh = B_BLK_HEAD (bh);
739   nr = blkh_nr_item(blkh);
740   if ( nr > (bh->b_size - BLKH_SIZE) / IH_SIZE)
741     reiserfs_panic (NULL, "vs-6010: check_leaf_block_head: invalid item number %z", bh);
742   if ( blkh_free_space(blkh) > 
743       bh->b_size - BLKH_SIZE - IH_SIZE * nr )
744     reiserfs_panic (NULL, "vs-6020: check_leaf_block_head: invalid free space %z", bh);
745     
746 }
747
748 static void check_internal_block_head (struct buffer_head * bh)
749 {
750     struct block_head * blkh;
751     
752     blkh = B_BLK_HEAD (bh);
753     if (!(B_LEVEL (bh) > DISK_LEAF_NODE_LEVEL && B_LEVEL (bh) <= MAX_HEIGHT))
754         reiserfs_panic (NULL, "vs-6025: check_internal_block_head: invalid level %z", bh);
755
756     if (B_NR_ITEMS (bh) > (bh->b_size - BLKH_SIZE) / IH_SIZE)
757         reiserfs_panic (NULL, "vs-6030: check_internal_block_head: invalid item number %z", bh);
758
759     if (B_FREE_SPACE (bh) != 
760         bh->b_size - BLKH_SIZE - KEY_SIZE * B_NR_ITEMS (bh) - DC_SIZE * (B_NR_ITEMS (bh) + 1))
761         reiserfs_panic (NULL, "vs-6040: check_internal_block_head: invalid free space %z", bh);
762
763 }
764
765
766 void check_leaf (struct buffer_head * bh)
767 {
768     int i;
769     struct item_head * ih;
770
771     if (!bh)
772         return;
773     check_leaf_block_head (bh);
774     for (i = 0, ih = B_N_PITEM_HEAD (bh, 0); i < B_NR_ITEMS (bh); i ++, ih ++)
775         op_check_item (ih, B_I_PITEM (bh, ih));
776 }
777
778
779 void check_internal (struct buffer_head * bh)
780 {
781   if (!bh)
782     return;
783   check_internal_block_head (bh);
784 }
785
786
787 void print_statistics (struct super_block * s)
788 {
789
790   /*
791   printk ("reiserfs_put_super: session statistics: balances %d, fix_nodes %d, \
792 bmap with search %d, without %d, dir2ind %d, ind2dir %d\n",
793           REISERFS_SB(s)->s_do_balance, REISERFS_SB(s)->s_fix_nodes,
794           REISERFS_SB(s)->s_bmaps, REISERFS_SB(s)->s_bmaps_without_search,
795           REISERFS_SB(s)->s_direct2indirect, REISERFS_SB(s)->s_indirect2direct);
796   */
797
798 }