Merge with rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[linux-2.6] / 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 static 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 void
370 reiserfs_abort (struct super_block *sb, int errno, const char *fmt, ...)
371 {
372     do_reiserfs_warning (fmt);
373
374     if (reiserfs_error_panic (sb)) {
375         panic (KERN_CRIT "REISERFS: panic (device %s): %s\n",
376                reiserfs_bdevname (sb), error_buf);
377     }
378
379     if (sb->s_flags & MS_RDONLY)
380         return;
381
382     printk (KERN_CRIT "REISERFS: abort (device %s): %s\n",
383             reiserfs_bdevname (sb), error_buf);
384
385     sb->s_flags |= MS_RDONLY;
386     reiserfs_journal_abort (sb, errno);
387 }
388
389 /* this prints internal nodes (4 keys/items in line) (dc_number,
390    dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number,
391    dc_size)...*/
392 static int print_internal (struct buffer_head * bh, int first, int last)
393 {
394     struct reiserfs_key * key;
395     struct disk_child * dc;
396     int i;
397     int from, to;
398     
399     if (!B_IS_KEYS_LEVEL (bh))
400         return 1;
401
402     check_internal (bh);
403     
404     if (first == -1) {
405         from = 0;
406         to = B_NR_ITEMS (bh);
407     } else {
408         from = first;
409         to = last < B_NR_ITEMS (bh) ? last : B_NR_ITEMS (bh);
410     }
411
412     reiserfs_printk ("INTERNAL NODE (%ld) contains %z\n",  bh->b_blocknr, bh);
413     
414     dc = B_N_CHILD (bh, from);
415     reiserfs_printk ("PTR %d: %y ", from, dc);
416     
417     for (i = from, key = B_N_PDELIM_KEY (bh, from), dc ++; i < to; i ++, key ++, dc ++) {
418         reiserfs_printk ("KEY %d: %k PTR %d: %y ", i, key, i + 1, dc);
419         if (i && i % 4 == 0)
420             printk ("\n");
421     }
422     printk ("\n");
423     return 0;
424 }
425
426
427
428
429
430 static int print_leaf (struct buffer_head * bh, int print_mode, int first, int last)
431 {
432     struct block_head * blkh;
433     struct item_head * ih;
434     int i, nr;
435     int from, to;
436
437     if (!B_IS_ITEMS_LEVEL (bh))
438         return 1;
439
440     check_leaf (bh);
441
442     blkh = B_BLK_HEAD (bh);
443     ih = B_N_PITEM_HEAD (bh,0);
444     nr = blkh_nr_item(blkh);
445
446     printk ("\n===================================================================\n");
447     reiserfs_printk ("LEAF NODE (%ld) contains %z\n", bh->b_blocknr, bh);
448
449     if (!(print_mode & PRINT_LEAF_ITEMS)) {
450         reiserfs_printk ("FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n",
451                           &(ih->ih_key), &((ih + nr - 1)->ih_key));
452         return 0;
453     }
454
455     if (first < 0 || first > nr - 1) 
456         from = 0;
457     else 
458         from = first;
459
460     if (last < 0 || last > nr )
461         to = nr;
462     else
463         to = last;
464
465     ih += from;
466     printk ("-------------------------------------------------------------------------------\n");
467     printk ("|##|   type    |           key           | ilen | free_space | version | loc  |\n");
468     for (i = from; i < to; i++, ih ++) {
469         printk ("-------------------------------------------------------------------------------\n");
470         reiserfs_printk ("|%2d| %h |\n", i, ih);
471         if (print_mode & PRINT_LEAF_ITEMS)
472             op_print_item (ih, B_I_PITEM (bh, ih));
473     }
474
475     printk ("===================================================================\n");
476
477     return 0;
478 }
479
480 char * reiserfs_hashname(int code)
481 {
482     if ( code == YURA_HASH)
483         return "rupasov";
484     if ( code == TEA_HASH)
485         return "tea";
486     if ( code == R5_HASH)
487         return "r5";
488
489     return "unknown";
490 }
491
492 /* return 1 if this is not super block */
493 static int print_super_block (struct buffer_head * bh)
494 {
495     struct reiserfs_super_block * rs = (struct reiserfs_super_block *)(bh->b_data);
496     int skipped, data_blocks;
497     char *version;
498     char b[BDEVNAME_SIZE];
499
500     if (is_reiserfs_3_5(rs)) {
501         version = "3.5";
502     } else if (is_reiserfs_3_6(rs)) {
503         version = "3.6";
504     } else if (is_reiserfs_jr(rs)) {
505       version = ((sb_version(rs) == REISERFS_VERSION_2) ?
506                  "3.6" : "3.5");  
507     } else {
508         return 1;
509     }
510
511     printk ("%s\'s super block is in block %llu\n", bdevname (bh->b_bdev, b),
512             (unsigned long long)bh->b_blocknr);
513     printk ("Reiserfs version %s\n", version );
514     printk ("Block count %u\n", sb_block_count(rs));
515     printk ("Blocksize %d\n", sb_blocksize(rs));
516     printk ("Free blocks %u\n", sb_free_blocks(rs));
517     // FIXME: this would be confusing if
518     // someone stores reiserfs super block in some data block ;)
519 //    skipped = (bh->b_blocknr * bh->b_size) / sb_blocksize(rs);
520     skipped = bh->b_blocknr;
521     data_blocks = sb_block_count(rs) - skipped - 1 - sb_bmap_nr(rs) -
522             (!is_reiserfs_jr(rs) ? sb_jp_journal_size(rs) + 1 : sb_reserved_for_journal(rs)) -      
523             sb_free_blocks(rs);
524     printk ("Busy blocks (skipped %d, bitmaps - %d, journal (or reserved) blocks - %d\n"
525             "1 super block, %d data blocks\n", 
526             skipped, sb_bmap_nr(rs), (!is_reiserfs_jr(rs) ? (sb_jp_journal_size(rs) + 1) :
527                                       sb_reserved_for_journal(rs)) , data_blocks);
528     printk ("Root block %u\n", sb_root_block(rs));
529     printk ("Journal block (first) %d\n", sb_jp_journal_1st_block(rs));
530     printk ("Journal dev %d\n", sb_jp_journal_dev(rs));
531     printk ("Journal orig size %d\n", sb_jp_journal_size(rs));
532     printk ("FS state %d\n", sb_fs_state(rs));
533     printk ("Hash function \"%s\"\n",
534             reiserfs_hashname(sb_hash_function_code(rs)));
535     
536     printk ("Tree height %d\n", sb_tree_height(rs));
537     return 0;
538 }
539
540 static int print_desc_block (struct buffer_head * bh)
541 {
542     struct reiserfs_journal_desc * desc;
543
544     if (memcmp(get_journal_desc_magic (bh), JOURNAL_DESC_MAGIC, 8))
545         return 1;
546
547     desc = (struct reiserfs_journal_desc *)(bh->b_data);
548     printk ("Desc block %llu (j_trans_id %d, j_mount_id %d, j_len %d)",
549             (unsigned long long)bh->b_blocknr, get_desc_trans_id (desc), get_desc_mount_id (desc),
550             get_desc_trans_len (desc));
551
552     return 0;
553 }
554
555
556 void print_block (struct buffer_head * bh, ...)//int print_mode, int first, int last)
557 {
558     va_list args;
559     int mode, first, last;
560
561     va_start (args, bh);
562
563     if ( ! bh ) {
564         printk("print_block: buffer is NULL\n");
565         return;
566     }
567
568     mode = va_arg (args, int);
569     first = va_arg (args, int);
570     last = va_arg (args, int);
571     if (print_leaf (bh, mode, first, last))
572         if (print_internal (bh, first, last))
573             if (print_super_block (bh))
574                 if (print_desc_block (bh))
575                     printk ("Block %llu contains unformatted data\n", (unsigned long long)bh->b_blocknr);
576 }
577
578
579
580 static char print_tb_buf[2048];
581
582 /* this stores initial state of tree balance in the print_tb_buf */
583 void store_print_tb (struct tree_balance * tb)
584 {
585     int h = 0;
586     int i;
587     struct buffer_head * tbSh, * tbFh;
588
589     if (!tb)
590         return;
591
592     sprintf (print_tb_buf, "\n"
593              "BALANCING %d\n"
594              "MODE=%c, ITEM_POS=%d POS_IN_ITEM=%d\n" 
595              "=====================================================================\n"
596              "* h *    S    *    L    *    R    *   F   *   FL  *   FR  *  CFL  *  CFR  *\n",
597              REISERFS_SB(tb->tb_sb)->s_do_balance,
598              tb->tb_mode, PATH_LAST_POSITION (tb->tb_path), tb->tb_path->pos_in_item);
599   
600     for (h = 0; h < sizeof(tb->insert_size) / sizeof (tb->insert_size[0]); h ++) {
601         if (PATH_H_PATH_OFFSET (tb->tb_path, h) <= tb->tb_path->path_length && 
602             PATH_H_PATH_OFFSET (tb->tb_path, h) > ILLEGAL_PATH_ELEMENT_OFFSET) {
603             tbSh = PATH_H_PBUFFER (tb->tb_path, h);
604             tbFh = PATH_H_PPARENT (tb->tb_path, h);
605         } else {
606             tbSh = NULL;
607             tbFh = NULL;
608         }
609         sprintf (print_tb_buf + strlen (print_tb_buf),
610                  "* %d * %3lld(%2d) * %3lld(%2d) * %3lld(%2d) * %5lld * %5lld * %5lld * %5lld * %5lld *\n",
611                  h, 
612                  (tbSh) ? (long long)(tbSh->b_blocknr):(-1LL),
613                  (tbSh) ? atomic_read (&(tbSh->b_count)) : -1,
614                  (tb->L[h]) ? (long long)(tb->L[h]->b_blocknr):(-1LL),
615                  (tb->L[h]) ? atomic_read (&(tb->L[h]->b_count)) : -1,
616                  (tb->R[h]) ? (long long)(tb->R[h]->b_blocknr):(-1LL),
617                  (tb->R[h]) ? atomic_read (&(tb->R[h]->b_count)) : -1,
618                  (tbFh) ? (long long)(tbFh->b_blocknr):(-1LL),
619                  (tb->FL[h]) ? (long long)(tb->FL[h]->b_blocknr):(-1LL),
620                  (tb->FR[h]) ? (long long)(tb->FR[h]->b_blocknr):(-1LL),
621                  (tb->CFL[h]) ? (long long)(tb->CFL[h]->b_blocknr):(-1LL),
622                  (tb->CFR[h]) ? (long long)(tb->CFR[h]->b_blocknr):(-1LL));
623     }
624
625     sprintf (print_tb_buf + strlen (print_tb_buf), 
626              "=====================================================================\n"
627              "* h * size * ln * lb * rn * rb * blkn * s0 * s1 * s1b * s2 * s2b * curb * lk * rk *\n"
628              "* 0 * %4d * %2d * %2d * %2d * %2d * %4d * %2d * %2d * %3d * %2d * %3d * %4d * %2d * %2d *\n",
629              tb->insert_size[0], tb->lnum[0], tb->lbytes, tb->rnum[0],tb->rbytes, tb->blknum[0], 
630              tb->s0num, tb->s1num,tb->s1bytes,  tb->s2num, tb->s2bytes, tb->cur_blknum, tb->lkey[0], tb->rkey[0]);
631
632     /* this prints balance parameters for non-leaf levels */
633     h = 0;
634     do {
635         h++;
636         sprintf (print_tb_buf + strlen (print_tb_buf),
637                  "* %d * %4d * %2d *    * %2d *    * %2d *\n",
638                 h, tb->insert_size[h], tb->lnum[h], tb->rnum[h], tb->blknum[h]);
639     } while (tb->insert_size[h]);
640
641     sprintf (print_tb_buf + strlen (print_tb_buf), 
642              "=====================================================================\n"
643              "FEB list: ");
644
645     /* print FEB list (list of buffers in form (bh (b_blocknr, b_count), that will be used for new nodes) */
646     h = 0;
647     for (i = 0; i < sizeof (tb->FEB) / sizeof (tb->FEB[0]); i ++)
648         sprintf (print_tb_buf + strlen (print_tb_buf),
649                  "%p (%llu %d)%s", tb->FEB[i], tb->FEB[i] ? (unsigned long long)tb->FEB[i]->b_blocknr : 0ULL,
650                  tb->FEB[i] ? atomic_read (&(tb->FEB[i]->b_count)) : 0, 
651                  (i == sizeof (tb->FEB) / sizeof (tb->FEB[0]) - 1) ? "\n" : ", ");
652
653     sprintf (print_tb_buf + strlen (print_tb_buf), 
654              "======================== the end ====================================\n");
655 }
656
657 void print_cur_tb (char * mes)
658 {
659     printk ("%s\n%s", mes, print_tb_buf);
660 }
661
662 static void check_leaf_block_head (struct buffer_head * bh)
663 {
664   struct block_head * blkh;
665   int nr;
666
667   blkh = B_BLK_HEAD (bh);
668   nr = blkh_nr_item(blkh);
669   if ( nr > (bh->b_size - BLKH_SIZE) / IH_SIZE)
670     reiserfs_panic (NULL, "vs-6010: check_leaf_block_head: invalid item number %z", bh);
671   if ( blkh_free_space(blkh) > 
672       bh->b_size - BLKH_SIZE - IH_SIZE * nr )
673     reiserfs_panic (NULL, "vs-6020: check_leaf_block_head: invalid free space %z", bh);
674     
675 }
676
677 static void check_internal_block_head (struct buffer_head * bh)
678 {
679     struct block_head * blkh;
680     
681     blkh = B_BLK_HEAD (bh);
682     if (!(B_LEVEL (bh) > DISK_LEAF_NODE_LEVEL && B_LEVEL (bh) <= MAX_HEIGHT))
683         reiserfs_panic (NULL, "vs-6025: check_internal_block_head: invalid level %z", bh);
684
685     if (B_NR_ITEMS (bh) > (bh->b_size - BLKH_SIZE) / IH_SIZE)
686         reiserfs_panic (NULL, "vs-6030: check_internal_block_head: invalid item number %z", bh);
687
688     if (B_FREE_SPACE (bh) != 
689         bh->b_size - BLKH_SIZE - KEY_SIZE * B_NR_ITEMS (bh) - DC_SIZE * (B_NR_ITEMS (bh) + 1))
690         reiserfs_panic (NULL, "vs-6040: check_internal_block_head: invalid free space %z", bh);
691
692 }
693
694
695 void check_leaf (struct buffer_head * bh)
696 {
697     int i;
698     struct item_head * ih;
699
700     if (!bh)
701         return;
702     check_leaf_block_head (bh);
703     for (i = 0, ih = B_N_PITEM_HEAD (bh, 0); i < B_NR_ITEMS (bh); i ++, ih ++)
704         op_check_item (ih, B_I_PITEM (bh, ih));
705 }
706
707
708 void check_internal (struct buffer_head * bh)
709 {
710   if (!bh)
711     return;
712   check_internal_block_head (bh);
713 }
714
715
716 void print_statistics (struct super_block * s)
717 {
718
719   /*
720   printk ("reiserfs_put_super: session statistics: balances %d, fix_nodes %d, \
721 bmap with search %d, without %d, dir2ind %d, ind2dir %d\n",
722           REISERFS_SB(s)->s_do_balance, REISERFS_SB(s)->s_fix_nodes,
723           REISERFS_SB(s)->s_bmaps, REISERFS_SB(s)->s_bmaps_without_search,
724           REISERFS_SB(s)->s_direct2indirect, REISERFS_SB(s)->s_indirect2direct);
725   */
726
727 }