blob: 78b40621b88b7571e5065aa005feae888092cb0e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
14static char error_buf[1024];
15static char fmt_buf[1024];
16static char off_buf[80];
17
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070018static char *reiserfs_cpu_offset(struct cpu_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070019{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070020 if (cpu_key_k_type(key) == TYPE_DIRENTRY)
21 sprintf(off_buf, "%Lu(%Lu)",
22 (unsigned long long)
23 GET_HASH_VALUE(cpu_key_k_offset(key)),
24 (unsigned long long)
25 GET_GENERATION_NUMBER(cpu_key_k_offset(key)));
26 else
27 sprintf(off_buf, "0x%Lx",
28 (unsigned long long)cpu_key_k_offset(key));
29 return off_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -070030}
31
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070032static char *le_offset(struct reiserfs_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070034 int version;
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070036 version = le_key_version(key);
37 if (le_key_k_type(version, key) == TYPE_DIRENTRY)
38 sprintf(off_buf, "%Lu(%Lu)",
39 (unsigned long long)
40 GET_HASH_VALUE(le_key_k_offset(version, key)),
41 (unsigned long long)
42 GET_GENERATION_NUMBER(le_key_k_offset(version, key)));
43 else
44 sprintf(off_buf, "0x%Lx",
45 (unsigned long long)le_key_k_offset(version, key));
46 return off_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -070047}
48
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070049static char *cpu_type(struct cpu_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070051 if (cpu_key_k_type(key) == TYPE_STAT_DATA)
52 return "SD";
53 if (cpu_key_k_type(key) == TYPE_DIRENTRY)
54 return "DIR";
55 if (cpu_key_k_type(key) == TYPE_DIRECT)
56 return "DIRECT";
57 if (cpu_key_k_type(key) == TYPE_INDIRECT)
58 return "IND";
59 return "UNKNOWN";
Linus Torvalds1da177e2005-04-16 15:20:36 -070060}
61
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070062static char *le_type(struct reiserfs_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070063{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070064 int version;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070066 version = le_key_version(key);
67
68 if (le_key_k_type(version, key) == TYPE_STAT_DATA)
69 return "SD";
70 if (le_key_k_type(version, key) == TYPE_DIRENTRY)
71 return "DIR";
72 if (le_key_k_type(version, key) == TYPE_DIRECT)
73 return "DIRECT";
74 if (le_key_k_type(version, key) == TYPE_INDIRECT)
75 return "IND";
76 return "UNKNOWN";
Linus Torvalds1da177e2005-04-16 15:20:36 -070077}
78
Linus Torvalds1da177e2005-04-16 15:20:36 -070079/* %k */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070080static void sprintf_le_key(char *buf, struct reiserfs_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070082 if (key)
83 sprintf(buf, "[%d %d %s %s]", le32_to_cpu(key->k_dir_id),
84 le32_to_cpu(key->k_objectid), le_offset(key),
85 le_type(key));
86 else
87 sprintf(buf, "[NULL]");
Linus Torvalds1da177e2005-04-16 15:20:36 -070088}
89
Linus Torvalds1da177e2005-04-16 15:20:36 -070090/* %K */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070091static void sprintf_cpu_key(char *buf, struct cpu_key *key)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070093 if (key)
94 sprintf(buf, "[%d %d %s %s]", key->on_disk_key.k_dir_id,
95 key->on_disk_key.k_objectid, reiserfs_cpu_offset(key),
96 cpu_type(key));
97 else
98 sprintf(buf, "[NULL]");
Linus Torvalds1da177e2005-04-16 15:20:36 -070099}
100
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700101static void sprintf_de_head(char *buf, struct reiserfs_de_head *deh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700103 if (deh)
104 sprintf(buf,
105 "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]",
106 deh_offset(deh), deh_dir_id(deh), deh_objectid(deh),
107 deh_location(deh), deh_state(deh));
108 else
109 sprintf(buf, "[NULL]");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111}
112
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700113static void sprintf_item_head(char *buf, struct item_head *ih)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700115 if (ih) {
116 strcpy(buf,
117 (ih_version(ih) == KEY_FORMAT_3_6) ? "*3.6* " : "*3.5*");
118 sprintf_le_key(buf + strlen(buf), &(ih->ih_key));
119 sprintf(buf + strlen(buf), ", item_len %d, item_location %d, "
120 "free_space(entry_count) %d",
121 ih_item_len(ih), ih_location(ih), ih_free_space(ih));
122 } else
123 sprintf(buf, "[NULL]");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124}
125
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700126static void sprintf_direntry(char *buf, struct reiserfs_dir_entry *de)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700128 char name[20];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700130 memcpy(name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen);
131 name[de->de_namelen > 19 ? 19 : de->de_namelen] = 0;
132 sprintf(buf, "\"%s\"==>[%d %d]", name, de->de_dir_id, de->de_objectid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133}
134
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700135static void sprintf_block_head(char *buf, struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700137 sprintf(buf, "level=%d, nr_items=%d, free_space=%d rdkey ",
138 B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139}
140
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700141static void sprintf_buffer_head(char *buf, struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700143 char b[BDEVNAME_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700145 sprintf(buf,
146 "dev %s, size %d, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)",
147 bdevname(bh->b_bdev, b), bh->b_size,
148 (unsigned long long)bh->b_blocknr, atomic_read(&(bh->b_count)),
149 bh->b_state, bh->b_page,
150 buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE",
151 buffer_dirty(bh) ? "DIRTY" : "CLEAN",
152 buffer_locked(bh) ? "LOCKED" : "UNLOCKED");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153}
154
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700155static void sprintf_disk_child(char *buf, struct disk_child *dc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700157 sprintf(buf, "[dc_number=%d, dc_size=%u]", dc_block_number(dc),
158 dc_size(dc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159}
160
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700161static char *is_there_reiserfs_struct(char *fmt, int *what, int *skip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700163 char *k = fmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700165 *skip = 0;
166
167 while ((k = strchr(k, '%')) != NULL) {
168 if (k[1] == 'k' || k[1] == 'K' || k[1] == 'h' || k[1] == 't' ||
169 k[1] == 'z' || k[1] == 'b' || k[1] == 'y' || k[1] == 'a') {
170 *what = k[1];
171 break;
172 }
173 (*skip)++;
174 k++;
175 }
176 return k;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179/* debugging reiserfs we used to print out a lot of different
180 variables, like keys, item headers, buffer heads etc. Values of
181 most fields matter. So it took a long time just to write
182 appropriative printk. With this reiserfs_warning you can use format
183 specification for complex structures like you used to do with
184 printfs for integers, doubles and pointers. For instance, to print
185 out key structure you have to write just:
186 reiserfs_warning ("bad key %k", key);
187 instead of
188 printk ("bad key %lu %lu %lu %lu", key->k_dir_id, key->k_objectid,
189 key->k_offset, key->k_uniqueness);
190*/
191
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700192static void prepare_error_buf(const char *fmt, va_list args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700194 char *fmt1 = fmt_buf;
195 char *k;
196 char *p = error_buf;
197 int i, j, what, skip;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700199 strcpy(fmt1, fmt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700201 while ((k = is_there_reiserfs_struct(fmt1, &what, &skip)) != NULL) {
202 *k = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700204 p += vsprintf(p, fmt1, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700206 for (i = 0; i < skip; i++)
207 j = va_arg(args, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700209 switch (what) {
210 case 'k':
211 sprintf_le_key(p, va_arg(args, struct reiserfs_key *));
212 break;
213 case 'K':
214 sprintf_cpu_key(p, va_arg(args, struct cpu_key *));
215 break;
216 case 'h':
217 sprintf_item_head(p, va_arg(args, struct item_head *));
218 break;
219 case 't':
220 sprintf_direntry(p,
221 va_arg(args,
222 struct reiserfs_dir_entry *));
223 break;
224 case 'y':
225 sprintf_disk_child(p,
226 va_arg(args, struct disk_child *));
227 break;
228 case 'z':
229 sprintf_block_head(p,
230 va_arg(args, struct buffer_head *));
231 break;
232 case 'b':
233 sprintf_buffer_head(p,
234 va_arg(args, struct buffer_head *));
235 break;
236 case 'a':
237 sprintf_de_head(p,
238 va_arg(args,
239 struct reiserfs_de_head *));
240 break;
241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700243 p += strlen(p);
244 fmt1 = k + 2;
245 }
246 vsprintf(p, fmt1, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
248}
249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250/* in addition to usual conversion specifiers this accepts reiserfs
251 specific conversion specifiers:
252 %k to print little endian key,
253 %K to print cpu key,
254 %h to print item_head,
255 %t to print directory entry
256 %z to print block head (arg must be struct buffer_head *
257 %b to print buffer_head
258*/
259
260#define do_reiserfs_warning(fmt)\
261{\
262 va_list args;\
263 va_start( args, fmt );\
264 prepare_error_buf( fmt, args );\
265 va_end( args );\
266}
267
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700268void reiserfs_warning(struct super_block *sb, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700270 do_reiserfs_warning(fmt);
271 if (sb)
272 printk(KERN_WARNING "ReiserFS: %s: warning: %s\n",
273 reiserfs_bdevname(sb), error_buf);
274 else
275 printk(KERN_WARNING "ReiserFS: warning: %s\n", error_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276}
277
278/* No newline.. reiserfs_info calls can be followed by printk's */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700279void reiserfs_info(struct super_block *sb, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700281 do_reiserfs_warning(fmt);
282 if (sb)
283 printk(KERN_NOTICE "ReiserFS: %s: %s",
284 reiserfs_bdevname(sb), error_buf);
285 else
286 printk(KERN_NOTICE "ReiserFS: %s", error_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287}
288
289/* No newline.. reiserfs_printk calls can be followed by printk's */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700290static void reiserfs_printk(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700292 do_reiserfs_warning(fmt);
293 printk(error_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294}
295
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700296void reiserfs_debug(struct super_block *s, int level, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297{
298#ifdef CONFIG_REISERFS_CHECK
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700299 do_reiserfs_warning(fmt);
300 if (s)
301 printk(KERN_DEBUG "ReiserFS: %s: %s\n",
302 reiserfs_bdevname(s), error_buf);
303 else
304 printk(KERN_DEBUG "ReiserFS: %s\n", error_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305#endif
306}
307
308/* The format:
309
310 maintainer-errorid: [function-name:] message
311
312 where errorid is unique to the maintainer and function-name is
313 optional, is recommended, so that anyone can easily find the bug
314 with a simple grep for the short to type string
315 maintainer-errorid. Don't bother with reusing errorids, there are
316 lots of numbers out there.
317
318 Example:
319
320 reiserfs_panic(
321 p_sb, "reiser-29: reiserfs_new_blocknrs: "
322 "one of search_start or rn(%d) is equal to MAX_B_NUM,"
323 "which means that we are optimizing location based on the bogus location of a temp buffer (%p).",
324 rn, bh
325 );
326
327 Regular panic()s sometimes clear the screen before the message can
328 be read, thus the need for the while loop.
329
330 Numbering scheme for panic used by Vladimir and Anatoly( Hans completely ignores this scheme, and considers it
331 pointless complexity):
332
333 panics in reiserfs_fs.h have numbers from 1000 to 1999
334 super.c 2000 to 2999
335 preserve.c (unused) 3000 to 3999
336 bitmap.c 4000 to 4999
337 stree.c 5000 to 5999
338 prints.c 6000 to 6999
339 namei.c 7000 to 7999
340 fix_nodes.c 8000 to 8999
341 dir.c 9000 to 9999
342 lbalance.c 10000 to 10999
343 ibalance.c 11000 to 11999 not ready
344 do_balan.c 12000 to 12999
345 inode.c 13000 to 13999
346 file.c 14000 to 14999
347 objectid.c 15000 - 15999
348 buffer.c 16000 - 16999
349 symlink.c 17000 - 17999
350
351 . */
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353#ifdef CONFIG_REISERFS_CHECK
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700354extern struct tree_balance *cur_tb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355#endif
356
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700357void reiserfs_panic(struct super_block *sb, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700359 do_reiserfs_warning(fmt);
360 printk(KERN_EMERG "REISERFS: panic (device %s): %s\n",
361 reiserfs_bdevname(sb), error_buf);
362 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700364 /* this is not actually called, but makes reiserfs_panic() "noreturn" */
365 panic("REISERFS: panic (device %s): %s\n",
366 reiserfs_bdevname(sb), error_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367}
368
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700369void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700371 do_reiserfs_warning(fmt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700373 if (reiserfs_error_panic(sb)) {
374 panic(KERN_CRIT "REISERFS: panic (device %s): %s\n",
375 reiserfs_bdevname(sb), error_buf);
376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700378 if (sb->s_flags & MS_RDONLY)
379 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700381 printk(KERN_CRIT "REISERFS: abort (device %s): %s\n",
382 reiserfs_bdevname(sb), error_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700384 sb->s_flags |= MS_RDONLY;
385 reiserfs_journal_abort(sb, errno);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386}
387
388/* this prints internal nodes (4 keys/items in line) (dc_number,
389 dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number,
390 dc_size)...*/
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700391static int print_internal(struct buffer_head *bh, int first, int last)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700393 struct reiserfs_key *key;
394 struct disk_child *dc;
395 int i;
396 int from, to;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700398 if (!B_IS_KEYS_LEVEL(bh))
399 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700401 check_internal(bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700403 if (first == -1) {
404 from = 0;
405 to = B_NR_ITEMS(bh);
406 } else {
407 from = first;
408 to = last < B_NR_ITEMS(bh) ? last : B_NR_ITEMS(bh);
409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700411 reiserfs_printk("INTERNAL NODE (%ld) contains %z\n", bh->b_blocknr, bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700413 dc = B_N_CHILD(bh, from);
414 reiserfs_printk("PTR %d: %y ", from, dc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700416 for (i = from, key = B_N_PDELIM_KEY(bh, from), dc++; i < to;
417 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");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424}
425
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700426static int print_leaf(struct buffer_head *bh, int print_mode, int first,
427 int last)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700429 struct block_head *blkh;
430 struct item_head *ih;
431 int i, nr;
432 int from, to;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700434 if (!B_IS_ITEMS_LEVEL(bh))
435 return 1;
436
437 check_leaf(bh);
438
439 blkh = B_BLK_HEAD(bh);
440 ih = B_N_PITEM_HEAD(bh, 0);
441 nr = blkh_nr_item(blkh);
442
443 printk
444 ("\n===================================================================\n");
445 reiserfs_printk("LEAF NODE (%ld) contains %z\n", bh->b_blocknr, bh);
446
447 if (!(print_mode & PRINT_LEAF_ITEMS)) {
448 reiserfs_printk("FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n",
449 &(ih->ih_key), &((ih + nr - 1)->ih_key));
450 return 0;
451 }
452
453 if (first < 0 || first > nr - 1)
454 from = 0;
455 else
456 from = first;
457
458 if (last < 0 || last > nr)
459 to = nr;
460 else
461 to = last;
462
463 ih += from;
464 printk
465 ("-------------------------------------------------------------------------------\n");
466 printk
467 ("|##| type | key | ilen | free_space | version | loc |\n");
468 for (i = from; i < to; i++, ih++) {
469 printk
470 ("-------------------------------------------------------------------------------\n");
471 reiserfs_printk("|%2d| %h |\n", i, ih);
472 if (print_mode & PRINT_LEAF_ITEMS)
473 op_print_item(ih, B_I_PITEM(bh, ih));
474 }
475
476 printk
477 ("===================================================================\n");
478
479 return 0;
480}
481
482char *reiserfs_hashname(int code)
483{
484 if (code == YURA_HASH)
485 return "rupasov";
486 if (code == TEA_HASH)
487 return "tea";
488 if (code == R5_HASH)
489 return "r5";
490
491 return "unknown";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492}
493
494/* return 1 if this is not super block */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700495static int print_super_block(struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700497 struct reiserfs_super_block *rs =
498 (struct reiserfs_super_block *)(bh->b_data);
499 int skipped, data_blocks;
500 char *version;
501 char b[BDEVNAME_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700503 if (is_reiserfs_3_5(rs)) {
504 version = "3.5";
505 } else if (is_reiserfs_3_6(rs)) {
506 version = "3.6";
507 } else if (is_reiserfs_jr(rs)) {
508 version = ((sb_version(rs) == REISERFS_VERSION_2) ?
509 "3.6" : "3.5");
510 } else {
511 return 1;
512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700514 printk("%s\'s super block is in block %llu\n", bdevname(bh->b_bdev, b),
515 (unsigned long long)bh->b_blocknr);
516 printk("Reiserfs version %s\n", version);
517 printk("Block count %u\n", sb_block_count(rs));
518 printk("Blocksize %d\n", sb_blocksize(rs));
519 printk("Free blocks %u\n", sb_free_blocks(rs));
520 // FIXME: this would be confusing if
521 // someone stores reiserfs super block in some data block ;)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522// skipped = (bh->b_blocknr * bh->b_size) / sb_blocksize(rs);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700523 skipped = bh->b_blocknr;
524 data_blocks = sb_block_count(rs) - skipped - 1 - sb_bmap_nr(rs) -
525 (!is_reiserfs_jr(rs) ? sb_jp_journal_size(rs) +
526 1 : sb_reserved_for_journal(rs)) - sb_free_blocks(rs);
527 printk
528 ("Busy blocks (skipped %d, bitmaps - %d, journal (or reserved) blocks - %d\n"
529 "1 super block, %d data blocks\n", skipped, sb_bmap_nr(rs),
530 (!is_reiserfs_jr(rs) ? (sb_jp_journal_size(rs) + 1) :
531 sb_reserved_for_journal(rs)), data_blocks);
532 printk("Root block %u\n", sb_root_block(rs));
533 printk("Journal block (first) %d\n", sb_jp_journal_1st_block(rs));
534 printk("Journal dev %d\n", sb_jp_journal_dev(rs));
535 printk("Journal orig size %d\n", sb_jp_journal_size(rs));
536 printk("FS state %d\n", sb_fs_state(rs));
537 printk("Hash function \"%s\"\n",
538 reiserfs_hashname(sb_hash_function_code(rs)));
539
540 printk("Tree height %d\n", sb_tree_height(rs));
541 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542}
543
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700544static int print_desc_block(struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700546 struct reiserfs_journal_desc *desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700548 if (memcmp(get_journal_desc_magic(bh), JOURNAL_DESC_MAGIC, 8))
549 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700551 desc = (struct reiserfs_journal_desc *)(bh->b_data);
552 printk("Desc block %llu (j_trans_id %d, j_mount_id %d, j_len %d)",
553 (unsigned long long)bh->b_blocknr, get_desc_trans_id(desc),
554 get_desc_mount_id(desc), get_desc_trans_len(desc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700556 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557}
558
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700559void print_block(struct buffer_head *bh, ...) //int print_mode, int first, int last)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700561 va_list args;
562 int mode, first, last;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700564 va_start(args, bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700566 if (!bh) {
567 printk("print_block: buffer is NULL\n");
568 return;
569 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700571 mode = va_arg(args, int);
572 first = va_arg(args, int);
573 last = va_arg(args, int);
574 if (print_leaf(bh, mode, first, last))
575 if (print_internal(bh, first, last))
576 if (print_super_block(bh))
577 if (print_desc_block(bh))
578 printk
579 ("Block %llu contains unformatted data\n",
580 (unsigned long long)bh->b_blocknr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581}
582
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583static char print_tb_buf[2048];
584
585/* this stores initial state of tree balance in the print_tb_buf */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700586void store_print_tb(struct tree_balance *tb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700588 int h = 0;
589 int i;
590 struct buffer_head *tbSh, *tbFh;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700592 if (!tb)
593 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700595 sprintf(print_tb_buf, "\n"
596 "BALANCING %d\n"
597 "MODE=%c, ITEM_POS=%d POS_IN_ITEM=%d\n"
598 "=====================================================================\n"
599 "* h * S * L * R * F * FL * FR * CFL * CFR *\n",
600 REISERFS_SB(tb->tb_sb)->s_do_balance,
601 tb->tb_mode, PATH_LAST_POSITION(tb->tb_path),
602 tb->tb_path->pos_in_item);
603
Tobias Klausere8c96f82006-03-24 03:15:34 -0800604 for (h = 0; h < ARRAY_SIZE(tb->insert_size); h++) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700605 if (PATH_H_PATH_OFFSET(tb->tb_path, h) <=
606 tb->tb_path->path_length
607 && PATH_H_PATH_OFFSET(tb->tb_path,
608 h) > ILLEGAL_PATH_ELEMENT_OFFSET) {
609 tbSh = PATH_H_PBUFFER(tb->tb_path, h);
610 tbFh = PATH_H_PPARENT(tb->tb_path, h);
611 } else {
612 tbSh = NULL;
613 tbFh = NULL;
614 }
615 sprintf(print_tb_buf + strlen(print_tb_buf),
616 "* %d * %3lld(%2d) * %3lld(%2d) * %3lld(%2d) * %5lld * %5lld * %5lld * %5lld * %5lld *\n",
617 h,
618 (tbSh) ? (long long)(tbSh->b_blocknr) : (-1LL),
619 (tbSh) ? atomic_read(&(tbSh->b_count)) : -1,
620 (tb->L[h]) ? (long long)(tb->L[h]->b_blocknr) : (-1LL),
621 (tb->L[h]) ? atomic_read(&(tb->L[h]->b_count)) : -1,
622 (tb->R[h]) ? (long long)(tb->R[h]->b_blocknr) : (-1LL),
623 (tb->R[h]) ? atomic_read(&(tb->R[h]->b_count)) : -1,
624 (tbFh) ? (long long)(tbFh->b_blocknr) : (-1LL),
625 (tb->FL[h]) ? (long long)(tb->FL[h]->
626 b_blocknr) : (-1LL),
627 (tb->FR[h]) ? (long long)(tb->FR[h]->
628 b_blocknr) : (-1LL),
629 (tb->CFL[h]) ? (long long)(tb->CFL[h]->
630 b_blocknr) : (-1LL),
631 (tb->CFR[h]) ? (long long)(tb->CFR[h]->
632 b_blocknr) : (-1LL));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700635 sprintf(print_tb_buf + strlen(print_tb_buf),
636 "=====================================================================\n"
637 "* h * size * ln * lb * rn * rb * blkn * s0 * s1 * s1b * s2 * s2b * curb * lk * rk *\n"
638 "* 0 * %4d * %2d * %2d * %2d * %2d * %4d * %2d * %2d * %3d * %2d * %3d * %4d * %2d * %2d *\n",
639 tb->insert_size[0], tb->lnum[0], tb->lbytes, tb->rnum[0],
640 tb->rbytes, tb->blknum[0], tb->s0num, tb->s1num, tb->s1bytes,
641 tb->s2num, tb->s2bytes, tb->cur_blknum, tb->lkey[0],
642 tb->rkey[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700644 /* this prints balance parameters for non-leaf levels */
645 h = 0;
646 do {
647 h++;
648 sprintf(print_tb_buf + strlen(print_tb_buf),
649 "* %d * %4d * %2d * * %2d * * %2d *\n",
650 h, tb->insert_size[h], tb->lnum[h], tb->rnum[h],
651 tb->blknum[h]);
652 } while (tb->insert_size[h]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700654 sprintf(print_tb_buf + strlen(print_tb_buf),
655 "=====================================================================\n"
656 "FEB list: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700658 /* print FEB list (list of buffers in form (bh (b_blocknr, b_count), that will be used for new nodes) */
659 h = 0;
Tobias Klausere8c96f82006-03-24 03:15:34 -0800660 for (i = 0; i < ARRAY_SIZE(tb->FEB); i++)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700661 sprintf(print_tb_buf + strlen(print_tb_buf),
662 "%p (%llu %d)%s", tb->FEB[i],
663 tb->FEB[i] ? (unsigned long long)tb->FEB[i]->
664 b_blocknr : 0ULL,
665 tb->FEB[i] ? atomic_read(&(tb->FEB[i]->b_count)) : 0,
Tobias Klausere8c96f82006-03-24 03:15:34 -0800666 (i == ARRAY_SIZE(tb->FEB) - 1) ? "\n" : ", ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700668 sprintf(print_tb_buf + strlen(print_tb_buf),
669 "======================== the end ====================================\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670}
671
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700672void print_cur_tb(char *mes)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700674 printk("%s\n%s", mes, print_tb_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675}
676
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700677static void check_leaf_block_head(struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700679 struct block_head *blkh;
680 int nr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700682 blkh = B_BLK_HEAD(bh);
683 nr = blkh_nr_item(blkh);
684 if (nr > (bh->b_size - BLKH_SIZE) / IH_SIZE)
685 reiserfs_panic(NULL,
686 "vs-6010: check_leaf_block_head: invalid item number %z",
687 bh);
688 if (blkh_free_space(blkh) > bh->b_size - BLKH_SIZE - IH_SIZE * nr)
689 reiserfs_panic(NULL,
690 "vs-6020: check_leaf_block_head: invalid free space %z",
691 bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693}
694
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700695static void check_internal_block_head(struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700697 struct block_head *blkh;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700699 blkh = B_BLK_HEAD(bh);
700 if (!(B_LEVEL(bh) > DISK_LEAF_NODE_LEVEL && B_LEVEL(bh) <= MAX_HEIGHT))
701 reiserfs_panic(NULL,
702 "vs-6025: check_internal_block_head: invalid level %z",
703 bh);
704
705 if (B_NR_ITEMS(bh) > (bh->b_size - BLKH_SIZE) / IH_SIZE)
706 reiserfs_panic(NULL,
707 "vs-6030: check_internal_block_head: invalid item number %z",
708 bh);
709
710 if (B_FREE_SPACE(bh) !=
711 bh->b_size - BLKH_SIZE - KEY_SIZE * B_NR_ITEMS(bh) -
712 DC_SIZE * (B_NR_ITEMS(bh) + 1))
713 reiserfs_panic(NULL,
714 "vs-6040: check_internal_block_head: invalid free space %z",
715 bh);
716
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717}
718
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700719void check_leaf(struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700721 int i;
722 struct item_head *ih;
723
724 if (!bh)
725 return;
726 check_leaf_block_head(bh);
727 for (i = 0, ih = B_N_PITEM_HEAD(bh, 0); i < B_NR_ITEMS(bh); i++, ih++)
728 op_check_item(ih, B_I_PITEM(bh, ih));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729}
730
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700731void check_internal(struct buffer_head *bh)
732{
733 if (!bh)
734 return;
735 check_internal_block_head(bh);
736}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700738void print_statistics(struct super_block *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739{
740
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700741 /*
742 printk ("reiserfs_put_super: session statistics: balances %d, fix_nodes %d, \
743 bmap with search %d, without %d, dir2ind %d, ind2dir %d\n",
744 REISERFS_SB(s)->s_do_balance, REISERFS_SB(s)->s_fix_nodes,
745 REISERFS_SB(s)->s_bmaps, REISERFS_SB(s)->s_bmaps_without_search,
746 REISERFS_SB(s)->s_direct2indirect, REISERFS_SB(s)->s_indirect2direct);
747 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749}